diff options
328 files changed, 13507 insertions, 4914 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt index aaa01b0e3ee9..3bbe157b45e4 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt | |||
@@ -19,6 +19,7 @@ This document has the following sections: | |||
19 | - Key overview | 19 | - Key overview |
20 | - Key service overview | 20 | - Key service overview |
21 | - Key access permissions | 21 | - Key access permissions |
22 | - SELinux support | ||
22 | - New procfs files | 23 | - New procfs files |
23 | - Userspace system call interface | 24 | - Userspace system call interface |
24 | - Kernel services | 25 | - Kernel services |
@@ -232,6 +233,34 @@ For changing the ownership, group ID or permissions mask, being the owner of | |||
232 | the key or having the sysadmin capability is sufficient. | 233 | the key or having the sysadmin capability is sufficient. |
233 | 234 | ||
234 | 235 | ||
236 | =============== | ||
237 | SELINUX SUPPORT | ||
238 | =============== | ||
239 | |||
240 | The security class "key" has been added to SELinux so that mandatory access | ||
241 | controls can be applied to keys created within various contexts. This support | ||
242 | is preliminary, and is likely to change quite significantly in the near future. | ||
243 | Currently, all of the basic permissions explained above are provided in SELinux | ||
244 | as well; SE Linux is simply invoked after all basic permission checks have been | ||
245 | performed. | ||
246 | |||
247 | Each key is labeled with the same context as the task to which it belongs. | ||
248 | Typically, this is the same task that was running when the key was created. | ||
249 | The default keyrings are handled differently, but in a way that is very | ||
250 | intuitive: | ||
251 | |||
252 | (*) The user and user session keyrings that are created when the user logs in | ||
253 | are currently labeled with the context of the login manager. | ||
254 | |||
255 | (*) The keyrings associated with new threads are each labeled with the context | ||
256 | of their associated thread, and both session and process keyrings are | ||
257 | handled similarly. | ||
258 | |||
259 | Note, however, that the default keyrings associated with the root user are | ||
260 | labeled with the default kernel context, since they are created early in the | ||
261 | boot process, before root has a chance to log in. | ||
262 | |||
263 | |||
235 | ================ | 264 | ================ |
236 | NEW PROCFS FILES | 265 | NEW PROCFS FILES |
237 | ================ | 266 | ================ |
@@ -935,6 +964,16 @@ The structure has a number of fields, some of which are mandatory: | |||
935 | It is not safe to sleep in this method; the caller may hold spinlocks. | 964 | It is not safe to sleep in this method; the caller may hold spinlocks. |
936 | 965 | ||
937 | 966 | ||
967 | (*) void (*revoke)(struct key *key); | ||
968 | |||
969 | This method is optional. It is called to discard part of the payload | ||
970 | data upon a key being revoked. The caller will have the key semaphore | ||
971 | write-locked. | ||
972 | |||
973 | It is safe to sleep in this method, though care should be taken to avoid | ||
974 | a deadlock against the key semaphore. | ||
975 | |||
976 | |||
938 | (*) void (*destroy)(struct key *key); | 977 | (*) void (*destroy)(struct key *key); |
939 | 978 | ||
940 | This method is optional. It is called to discard the payload data on a key | 979 | This method is optional. It is called to discard the payload data on a key |
diff --git a/Documentation/pci.txt b/Documentation/pci.txt index 66bbbf1d1ef6..3242e5c1ee9c 100644 --- a/Documentation/pci.txt +++ b/Documentation/pci.txt | |||
@@ -213,9 +213,17 @@ have been remapped by the kernel. | |||
213 | 213 | ||
214 | See Documentation/IO-mapping.txt for how to access device memory. | 214 | See Documentation/IO-mapping.txt for how to access device memory. |
215 | 215 | ||
216 | You still need to call request_region() for I/O regions and | 216 | The device driver needs to call pci_request_region() to make sure |
217 | request_mem_region() for memory regions to make sure nobody else is using the | 217 | no other device is already using the same resource. The driver is expected |
218 | same device. | 218 | to determine MMIO and IO Port resource availability _before_ calling |
219 | pci_enable_device(). Conversely, drivers should call pci_release_region() | ||
220 | _after_ calling pci_disable_device(). The idea is to prevent two devices | ||
221 | colliding on the same address range. | ||
222 | |||
223 | Generic flavors of pci_request_region() are request_mem_region() | ||
224 | (for MMIO ranges) and request_region() (for IO Port ranges). | ||
225 | Use these for address resources that are not described by "normal" PCI | ||
226 | interfaces (e.g. BAR). | ||
219 | 227 | ||
220 | All interrupt handlers should be registered with SA_SHIRQ and use the devid | 228 | All interrupt handlers should be registered with SA_SHIRQ and use the devid |
221 | to map IRQs to devices (remember that all PCI interrupts are shared). | 229 | to map IRQs to devices (remember that all PCI interrupts are shared). |
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 0ee2c7dfc482..87d76a5c73d0 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
@@ -366,7 +366,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
366 | 366 | ||
367 | Module for C-Media CMI8338 and 8738 PCI sound cards. | 367 | Module for C-Media CMI8338 and 8738 PCI sound cards. |
368 | 368 | ||
369 | mpu_port - 0x300,0x310,0x320,0x330, 0 = disable (default) | 369 | mpu_port - 0x300,0x310,0x320,0x330 = legacy port, |
370 | 1 = integrated PCI port, | ||
371 | 0 = disable (default) | ||
370 | fm_port - 0x388 (default), 0 = disable (default) | 372 | fm_port - 0x388 (default), 0 = disable (default) |
371 | soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only) | 373 | soft_ac3 - Software-conversion of raw SPDIF packets (model 033 only) |
372 | (default = 1) | 374 | (default = 1) |
@@ -468,7 +470,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
468 | 470 | ||
469 | Module for multifunction CS5535 companion PCI device | 471 | Module for multifunction CS5535 companion PCI device |
470 | 472 | ||
471 | This module supports multiple cards. | 473 | The power-management is supported. |
472 | 474 | ||
473 | Module snd-dt019x | 475 | Module snd-dt019x |
474 | ----------------- | 476 | ----------------- |
@@ -707,8 +709,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
707 | Module snd-hda-intel | 709 | Module snd-hda-intel |
708 | -------------------- | 710 | -------------------- |
709 | 711 | ||
710 | Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450, | 712 | Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8), |
711 | VIA VT8251/VT8237A | 713 | ATI SB450, SB600, RS600, |
714 | VIA VT8251/VT8237A, | ||
715 | SIS966, ULI M5461 | ||
712 | 716 | ||
713 | model - force the model name | 717 | model - force the model name |
714 | position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) | 718 | position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) |
@@ -778,6 +782,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
778 | AD1981 | 782 | AD1981 |
779 | basic 3-jack (default) | 783 | basic 3-jack (default) |
780 | hp HP nx6320 | 784 | hp HP nx6320 |
785 | thinkpad Lenovo Thinkpad T60/X60/Z60 | ||
781 | 786 | ||
782 | AD1986A | 787 | AD1986A |
783 | 6stack 6-jack, separate surrounds (default) | 788 | 6stack 6-jack, separate surrounds (default) |
@@ -1633,9 +1638,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
1633 | 1638 | ||
1634 | About capture IBL, see the description of snd-vx222 module. | 1639 | About capture IBL, see the description of snd-vx222 module. |
1635 | 1640 | ||
1636 | Note: the driver is build only when CONFIG_ISA is set. | 1641 | Note: snd-vxp440 driver is merged to snd-vxpocket driver since |
1637 | |||
1638 | Note2: snd-vxp440 driver is merged to snd-vxpocket driver since | ||
1639 | ALSA 1.0.10. | 1642 | ALSA 1.0.10. |
1640 | 1643 | ||
1641 | The power-management is supported. | 1644 | The power-management is supported. |
@@ -1662,8 +1665,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
1662 | 1665 | ||
1663 | Module for Sound Core PDAudioCF sound card. | 1666 | Module for Sound Core PDAudioCF sound card. |
1664 | 1667 | ||
1665 | Note: the driver is build only when CONFIG_ISA is set. | ||
1666 | |||
1667 | The power-management is supported. | 1668 | The power-management is supported. |
1668 | 1669 | ||
1669 | 1670 | ||
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index 1faf76383bab..635cbb94357c 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | |||
@@ -4215,7 +4215,7 @@ struct _snd_pcm_runtime { | |||
4215 | <programlisting> | 4215 | <programlisting> |
4216 | <![CDATA[ | 4216 | <![CDATA[ |
4217 | struct snd_rawmidi *rmidi; | 4217 | struct snd_rawmidi *rmidi; |
4218 | snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, integrated, | 4218 | snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags, |
4219 | irq, irq_flags, &rmidi); | 4219 | irq, irq_flags, &rmidi); |
4220 | ]]> | 4220 | ]]> |
4221 | </programlisting> | 4221 | </programlisting> |
@@ -4242,15 +4242,36 @@ struct _snd_pcm_runtime { | |||
4242 | </para> | 4242 | </para> |
4243 | 4243 | ||
4244 | <para> | 4244 | <para> |
4245 | The 5th argument is bitflags for additional information. | ||
4245 | When the i/o port address above is a part of the PCI i/o | 4246 | When the i/o port address above is a part of the PCI i/o |
4246 | region, the MPU401 i/o port might have been already allocated | 4247 | region, the MPU401 i/o port might have been already allocated |
4247 | (reserved) by the driver itself. In such a case, pass non-zero | 4248 | (reserved) by the driver itself. In such a case, pass a bit flag |
4248 | to the 5th argument | 4249 | <constant>MPU401_INFO_INTEGRATED</constant>, |
4249 | (<parameter>integrated</parameter>). Otherwise, pass 0 to it, | ||
4250 | and | 4250 | and |
4251 | the mpu401-uart layer will allocate the i/o ports by itself. | 4251 | the mpu401-uart layer will allocate the i/o ports by itself. |
4252 | </para> | 4252 | </para> |
4253 | 4253 | ||
4254 | <para> | ||
4255 | When the controller supports only the input or output MIDI stream, | ||
4256 | pass <constant>MPU401_INFO_INPUT</constant> or | ||
4257 | <constant>MPU401_INFO_OUTPUT</constant> bitflag, respectively. | ||
4258 | Then the rawmidi instance is created as a single stream. | ||
4259 | </para> | ||
4260 | |||
4261 | <para> | ||
4262 | <constant>MPU401_INFO_MMIO</constant> bitflag is used to change | ||
4263 | the access method to MMIO (via readb and writeb) instead of | ||
4264 | iob and outb. In this case, you have to pass the iomapped address | ||
4265 | to <function>snd_mpu401_uart_new()</function>. | ||
4266 | </para> | ||
4267 | |||
4268 | <para> | ||
4269 | When <constant>MPU401_INFO_TX_IRQ</constant> is set, the output | ||
4270 | stream isn't checked in the default interrupt handler. The driver | ||
4271 | needs to call <function>snd_mpu401_uart_interrupt_tx()</function> | ||
4272 | by itself to start processing the output stream in irq handler. | ||
4273 | </para> | ||
4274 | |||
4254 | <para> | 4275 | <para> |
4255 | Usually, the port address corresponds to the command port and | 4276 | Usually, the port address corresponds to the command port and |
4256 | port + 1 corresponds to the data port. If not, you may change | 4277 | port + 1 corresponds to the data port. If not, you may change |
@@ -5333,7 +5354,7 @@ struct _snd_pcm_runtime { | |||
5333 | <informalexample> | 5354 | <informalexample> |
5334 | <programlisting> | 5355 | <programlisting> |
5335 | <![CDATA[ | 5356 | <![CDATA[ |
5336 | snd_info_set_text_ops(entry, chip, read_size, my_proc_read); | 5357 | snd_info_set_text_ops(entry, chip, my_proc_read); |
5337 | ]]> | 5358 | ]]> |
5338 | </programlisting> | 5359 | </programlisting> |
5339 | </informalexample> | 5360 | </informalexample> |
@@ -5394,7 +5415,6 @@ struct _snd_pcm_runtime { | |||
5394 | <informalexample> | 5415 | <informalexample> |
5395 | <programlisting> | 5416 | <programlisting> |
5396 | <![CDATA[ | 5417 | <![CDATA[ |
5397 | entry->c.text.write_size = 256; | ||
5398 | entry->c.text.write = my_proc_write; | 5418 | entry->c.text.write = my_proc_write; |
5399 | ]]> | 5419 | ]]> |
5400 | </programlisting> | 5420 | </programlisting> |
@@ -5402,22 +5422,6 @@ struct _snd_pcm_runtime { | |||
5402 | </para> | 5422 | </para> |
5403 | 5423 | ||
5404 | <para> | 5424 | <para> |
5405 | The buffer size for read is set to 1024 implicitly by | ||
5406 | <function>snd_info_set_text_ops()</function>. It should suffice | ||
5407 | in most cases (the size will be aligned to | ||
5408 | <constant>PAGE_SIZE</constant> anyway), but if you need to handle | ||
5409 | very large text files, you can set it explicitly, too. | ||
5410 | |||
5411 | <informalexample> | ||
5412 | <programlisting> | ||
5413 | <![CDATA[ | ||
5414 | entry->c.text.read_size = 65536; | ||
5415 | ]]> | ||
5416 | </programlisting> | ||
5417 | </informalexample> | ||
5418 | </para> | ||
5419 | |||
5420 | <para> | ||
5421 | For the write callback, you can use | 5425 | For the write callback, you can use |
5422 | <function>snd_info_get_line()</function> to get a text line, and | 5426 | <function>snd_info_get_line()</function> to get a text line, and |
5423 | <function>snd_info_get_str()</function> to retrieve a string from | 5427 | <function>snd_info_get_str()</function> to retrieve a string from |
@@ -5562,7 +5566,7 @@ struct _snd_pcm_runtime { | |||
5562 | power status.</para></listitem> | 5566 | power status.</para></listitem> |
5563 | <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem> | 5567 | <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem> |
5564 | <listitem><para>If AC97 codecs are used, call | 5568 | <listitem><para>If AC97 codecs are used, call |
5565 | <function>snd_ac97_resume()</function> for each codec.</para></listitem> | 5569 | <function>snd_ac97_suspend()</function> for each codec.</para></listitem> |
5566 | <listitem><para>Save the register values if necessary.</para></listitem> | 5570 | <listitem><para>Save the register values if necessary.</para></listitem> |
5567 | <listitem><para>Stop the hardware if necessary.</para></listitem> | 5571 | <listitem><para>Stop the hardware if necessary.</para></listitem> |
5568 | <listitem><para>Disable the PCI device by calling | 5572 | <listitem><para>Disable the PCI device by calling |
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index 40e5aba3ad3d..fbe93084244c 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
@@ -202,6 +202,8 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size) | |||
202 | if (mcfg->config[i].base_reserved) { | 202 | if (mcfg->config[i].base_reserved) { |
203 | printk(KERN_ERR PREFIX | 203 | printk(KERN_ERR PREFIX |
204 | "MMCONFIG not in low 4GB of memory\n"); | 204 | "MMCONFIG not in low 4GB of memory\n"); |
205 | kfree(pci_mmcfg_config); | ||
206 | pci_mmcfg_config_num = 0; | ||
205 | return -ENODEV; | 207 | return -ENODEV; |
206 | } | 208 | } |
207 | } | 209 | } |
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index dbece776c5b2..c624b61e1104 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c | |||
@@ -288,6 +288,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) | |||
288 | 288 | ||
289 | void pcibios_disable_device (struct pci_dev *dev) | 289 | void pcibios_disable_device (struct pci_dev *dev) |
290 | { | 290 | { |
291 | pcibios_disable_resources(dev); | ||
291 | if (pcibios_disable_irq) | 292 | if (pcibios_disable_irq) |
292 | pcibios_disable_irq(dev); | 293 | pcibios_disable_irq(dev); |
293 | } | 294 | } |
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c index ed2c8c899bd3..7852827a599b 100644 --- a/arch/i386/pci/i386.c +++ b/arch/i386/pci/i386.c | |||
@@ -242,6 +242,15 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) | |||
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | void pcibios_disable_resources(struct pci_dev *dev) | ||
246 | { | ||
247 | u16 cmd; | ||
248 | |||
249 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
250 | cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); | ||
251 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
252 | } | ||
253 | |||
245 | /* | 254 | /* |
246 | * If we set up a device for bus mastering, we need to check the latency | 255 | * If we set up a device for bus mastering, we need to check the latency |
247 | * timer as certain crappy BIOSes forget to set it properly. | 256 | * timer as certain crappy BIOSes forget to set it properly. |
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c index 6b1ea0c9a570..e545b0992c48 100644 --- a/arch/i386/pci/mmconfig.c +++ b/arch/i386/pci/mmconfig.c | |||
@@ -15,7 +15,9 @@ | |||
15 | #include <asm/e820.h> | 15 | #include <asm/e820.h> |
16 | #include "pci.h" | 16 | #include "pci.h" |
17 | 17 | ||
18 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 18 | /* aperture is up to 256MB but BIOS may reserve less */ |
19 | #define MMCONFIG_APER_MIN (2 * 1024*1024) | ||
20 | #define MMCONFIG_APER_MAX (256 * 1024*1024) | ||
19 | 21 | ||
20 | /* Assume systems with more busses have correct MCFG */ | 22 | /* Assume systems with more busses have correct MCFG */ |
21 | #define MAX_CHECK_BUS 16 | 23 | #define MAX_CHECK_BUS 16 |
@@ -197,9 +199,10 @@ void __init pci_mmcfg_init(void) | |||
197 | return; | 199 | return; |
198 | 200 | ||
199 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | 201 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, |
200 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, | 202 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, |
201 | E820_RESERVED)) { | 203 | E820_RESERVED)) { |
202 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); | 204 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", |
205 | pci_mmcfg_config[0].base_address); | ||
203 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | 206 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); |
204 | return; | 207 | return; |
205 | } | 208 | } |
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index 12035e29108b..12bf3d8dda29 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h | |||
@@ -35,6 +35,7 @@ extern unsigned int pcibios_max_latency; | |||
35 | 35 | ||
36 | void pcibios_resource_survey(void); | 36 | void pcibios_resource_survey(void); |
37 | int pcibios_enable_resources(struct pci_dev *, int); | 37 | int pcibios_enable_resources(struct pci_dev *, int); |
38 | void pcibios_disable_resources(struct pci_dev *); | ||
38 | 39 | ||
39 | /* pci-pc.c */ | 40 | /* pci-pc.c */ |
40 | 41 | ||
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 6c4d59fd0364..ef9a2b49307a 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c | |||
@@ -46,6 +46,10 @@ | |||
46 | 46 | ||
47 | #define IRQ_DEBUG 0 | 47 | #define IRQ_DEBUG 0 |
48 | 48 | ||
49 | /* These can be overridden in platform_irq_init */ | ||
50 | int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR; | ||
51 | int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR; | ||
52 | |||
49 | /* default base addr of IPI table */ | 53 | /* default base addr of IPI table */ |
50 | void __iomem *ipi_base_addr = ((void __iomem *) | 54 | void __iomem *ipi_base_addr = ((void __iomem *) |
51 | (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR)); | 55 | (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR)); |
@@ -60,7 +64,7 @@ __u8 isa_irq_to_vector_map[16] = { | |||
60 | }; | 64 | }; |
61 | EXPORT_SYMBOL(isa_irq_to_vector_map); | 65 | EXPORT_SYMBOL(isa_irq_to_vector_map); |
62 | 66 | ||
63 | static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)]; | 67 | static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)]; |
64 | 68 | ||
65 | int | 69 | int |
66 | assign_irq_vector (int irq) | 70 | assign_irq_vector (int irq) |
@@ -89,6 +93,19 @@ free_irq_vector (int vector) | |||
89 | printk(KERN_WARNING "%s: double free!\n", __FUNCTION__); | 93 | printk(KERN_WARNING "%s: double free!\n", __FUNCTION__); |
90 | } | 94 | } |
91 | 95 | ||
96 | int | ||
97 | reserve_irq_vector (int vector) | ||
98 | { | ||
99 | int pos; | ||
100 | |||
101 | if (vector < IA64_FIRST_DEVICE_VECTOR || | ||
102 | vector > IA64_LAST_DEVICE_VECTOR) | ||
103 | return -EINVAL; | ||
104 | |||
105 | pos = vector - IA64_FIRST_DEVICE_VECTOR; | ||
106 | return test_and_set_bit(pos, ia64_vector_mask); | ||
107 | } | ||
108 | |||
92 | #ifdef CONFIG_SMP | 109 | #ifdef CONFIG_SMP |
93 | # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) | 110 | # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) |
94 | #else | 111 | #else |
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 5101ac462643..dc09a6a28a37 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c | |||
@@ -58,7 +58,7 @@ static int max_pcibus_number = 255; /* Default highest pci bus number */ | |||
58 | */ | 58 | */ |
59 | 59 | ||
60 | static dma_addr_t | 60 | static dma_addr_t |
61 | sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size) | 61 | sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type) |
62 | { | 62 | { |
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
@@ -457,13 +457,6 @@ void sn_pci_fixup_slot(struct pci_dev *dev) | |||
457 | pcidev_info->pdi_sn_irq_info = NULL; | 457 | pcidev_info->pdi_sn_irq_info = NULL; |
458 | kfree(sn_irq_info); | 458 | kfree(sn_irq_info); |
459 | } | 459 | } |
460 | |||
461 | /* | ||
462 | * MSI currently not supported on altix. Remove this when | ||
463 | * the MSI abstraction patches are integrated into the kernel | ||
464 | * (sometime after 2.6.16 releases) | ||
465 | */ | ||
466 | dev->no_msi = 1; | ||
467 | } | 460 | } |
468 | 461 | ||
469 | /* | 462 | /* |
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index c265e02f5036..dc8e2b696713 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c | |||
@@ -26,11 +26,11 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info); | |||
26 | 26 | ||
27 | int sn_force_interrupt_flag = 1; | 27 | int sn_force_interrupt_flag = 1; |
28 | extern int sn_ioif_inited; | 28 | extern int sn_ioif_inited; |
29 | static struct list_head **sn_irq_lh; | 29 | struct list_head **sn_irq_lh; |
30 | static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ | 30 | static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ |
31 | 31 | ||
32 | static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, | 32 | u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, |
33 | u64 sn_irq_info, | 33 | struct sn_irq_info *sn_irq_info, |
34 | int req_irq, nasid_t req_nasid, | 34 | int req_irq, nasid_t req_nasid, |
35 | int req_slice) | 35 | int req_slice) |
36 | { | 36 | { |
@@ -40,12 +40,13 @@ static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, | |||
40 | 40 | ||
41 | SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, | 41 | SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT, |
42 | (u64) SAL_INTR_ALLOC, (u64) local_nasid, | 42 | (u64) SAL_INTR_ALLOC, (u64) local_nasid, |
43 | (u64) local_widget, (u64) sn_irq_info, (u64) req_irq, | 43 | (u64) local_widget, __pa(sn_irq_info), (u64) req_irq, |
44 | (u64) req_nasid, (u64) req_slice); | 44 | (u64) req_nasid, (u64) req_slice); |
45 | |||
45 | return ret_stuff.status; | 46 | return ret_stuff.status; |
46 | } | 47 | } |
47 | 48 | ||
48 | static inline void sn_intr_free(nasid_t local_nasid, int local_widget, | 49 | void sn_intr_free(nasid_t local_nasid, int local_widget, |
49 | struct sn_irq_info *sn_irq_info) | 50 | struct sn_irq_info *sn_irq_info) |
50 | { | 51 | { |
51 | struct ia64_sal_retval ret_stuff; | 52 | struct ia64_sal_retval ret_stuff; |
@@ -112,73 +113,91 @@ static void sn_end_irq(unsigned int irq) | |||
112 | 113 | ||
113 | static void sn_irq_info_free(struct rcu_head *head); | 114 | static void sn_irq_info_free(struct rcu_head *head); |
114 | 115 | ||
115 | static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) | 116 | struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info, |
117 | nasid_t nasid, int slice) | ||
116 | { | 118 | { |
117 | struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; | 119 | int vector; |
118 | int cpuid, cpuphys; | 120 | int cpuphys; |
121 | int64_t bridge; | ||
122 | int local_widget, status; | ||
123 | nasid_t local_nasid; | ||
124 | struct sn_irq_info *new_irq_info; | ||
125 | struct sn_pcibus_provider *pci_provider; | ||
119 | 126 | ||
120 | cpuid = first_cpu(mask); | 127 | new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); |
121 | cpuphys = cpu_physical_id(cpuid); | 128 | if (new_irq_info == NULL) |
129 | return NULL; | ||
122 | 130 | ||
123 | list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, | 131 | memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); |
124 | sn_irq_lh[irq], list) { | 132 | |
125 | u64 bridge; | 133 | bridge = (u64) new_irq_info->irq_bridge; |
126 | int local_widget, status; | 134 | if (!bridge) { |
127 | nasid_t local_nasid; | 135 | kfree(new_irq_info); |
128 | struct sn_irq_info *new_irq_info; | 136 | return NULL; /* irq is not a device interrupt */ |
129 | struct sn_pcibus_provider *pci_provider; | 137 | } |
130 | |||
131 | new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); | ||
132 | if (new_irq_info == NULL) | ||
133 | break; | ||
134 | memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); | ||
135 | |||
136 | bridge = (u64) new_irq_info->irq_bridge; | ||
137 | if (!bridge) { | ||
138 | kfree(new_irq_info); | ||
139 | break; /* irq is not a device interrupt */ | ||
140 | } | ||
141 | 138 | ||
142 | local_nasid = NASID_GET(bridge); | 139 | local_nasid = NASID_GET(bridge); |
143 | 140 | ||
144 | if (local_nasid & 1) | 141 | if (local_nasid & 1) |
145 | local_widget = TIO_SWIN_WIDGETNUM(bridge); | 142 | local_widget = TIO_SWIN_WIDGETNUM(bridge); |
146 | else | 143 | else |
147 | local_widget = SWIN_WIDGETNUM(bridge); | 144 | local_widget = SWIN_WIDGETNUM(bridge); |
148 | 145 | ||
149 | /* Free the old PROM new_irq_info structure */ | 146 | vector = sn_irq_info->irq_irq; |
150 | sn_intr_free(local_nasid, local_widget, new_irq_info); | 147 | /* Free the old PROM new_irq_info structure */ |
151 | /* Update kernels new_irq_info with new target info */ | 148 | sn_intr_free(local_nasid, local_widget, new_irq_info); |
152 | unregister_intr_pda(new_irq_info); | 149 | /* Update kernels new_irq_info with new target info */ |
150 | unregister_intr_pda(new_irq_info); | ||
153 | 151 | ||
154 | /* allocate a new PROM new_irq_info struct */ | 152 | /* allocate a new PROM new_irq_info struct */ |
155 | status = sn_intr_alloc(local_nasid, local_widget, | 153 | status = sn_intr_alloc(local_nasid, local_widget, |
156 | __pa(new_irq_info), irq, | 154 | new_irq_info, vector, |
157 | cpuid_to_nasid(cpuid), | 155 | nasid, slice); |
158 | cpuid_to_slice(cpuid)); | ||
159 | 156 | ||
160 | /* SAL call failed */ | 157 | /* SAL call failed */ |
161 | if (status) { | 158 | if (status) { |
162 | kfree(new_irq_info); | 159 | kfree(new_irq_info); |
163 | break; | 160 | return NULL; |
164 | } | 161 | } |
165 | 162 | ||
166 | new_irq_info->irq_cpuid = cpuid; | 163 | cpuphys = nasid_slice_to_cpuid(nasid, slice); |
167 | register_intr_pda(new_irq_info); | 164 | new_irq_info->irq_cpuid = cpuphys; |
165 | register_intr_pda(new_irq_info); | ||
168 | 166 | ||
169 | pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; | 167 | pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; |
170 | if (pci_provider && pci_provider->target_interrupt) | ||
171 | (pci_provider->target_interrupt)(new_irq_info); | ||
172 | 168 | ||
173 | spin_lock(&sn_irq_info_lock); | 169 | /* |
174 | list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); | 170 | * If this represents a line interrupt, target it. If it's |
175 | spin_unlock(&sn_irq_info_lock); | 171 | * an msi (irq_int_bit < 0), it's already targeted. |
176 | call_rcu(&sn_irq_info->rcu, sn_irq_info_free); | 172 | */ |
173 | if (new_irq_info->irq_int_bit >= 0 && | ||
174 | pci_provider && pci_provider->target_interrupt) | ||
175 | (pci_provider->target_interrupt)(new_irq_info); | ||
176 | |||
177 | spin_lock(&sn_irq_info_lock); | ||
178 | list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); | ||
179 | spin_unlock(&sn_irq_info_lock); | ||
180 | call_rcu(&sn_irq_info->rcu, sn_irq_info_free); | ||
177 | 181 | ||
178 | #ifdef CONFIG_SMP | 182 | #ifdef CONFIG_SMP |
179 | set_irq_affinity_info((irq & 0xff), cpuphys, 0); | 183 | set_irq_affinity_info((vector & 0xff), cpuphys, 0); |
180 | #endif | 184 | #endif |
181 | } | 185 | |
186 | return new_irq_info; | ||
187 | } | ||
188 | |||
189 | static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) | ||
190 | { | ||
191 | struct sn_irq_info *sn_irq_info, *sn_irq_info_safe; | ||
192 | nasid_t nasid; | ||
193 | int slice; | ||
194 | |||
195 | nasid = cpuid_to_nasid(first_cpu(mask)); | ||
196 | slice = cpuid_to_slice(first_cpu(mask)); | ||
197 | |||
198 | list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, | ||
199 | sn_irq_lh[irq], list) | ||
200 | (void)sn_retarget_vector(sn_irq_info, nasid, slice); | ||
182 | } | 201 | } |
183 | 202 | ||
184 | struct hw_interrupt_type irq_type_sn = { | 203 | struct hw_interrupt_type irq_type_sn = { |
@@ -202,6 +221,9 @@ void sn_irq_init(void) | |||
202 | int i; | 221 | int i; |
203 | irq_desc_t *base_desc = irq_desc; | 222 | irq_desc_t *base_desc = irq_desc; |
204 | 223 | ||
224 | ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR; | ||
225 | ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR; | ||
226 | |||
205 | for (i = 0; i < NR_IRQS; i++) { | 227 | for (i = 0; i < NR_IRQS; i++) { |
206 | if (base_desc[i].handler == &no_irq_type) { | 228 | if (base_desc[i].handler == &no_irq_type) { |
207 | base_desc[i].handler = &irq_type_sn; | 229 | base_desc[i].handler = &irq_type_sn; |
@@ -285,6 +307,7 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info) | |||
285 | /* link it into the sn_irq[irq] list */ | 307 | /* link it into the sn_irq[irq] list */ |
286 | spin_lock(&sn_irq_info_lock); | 308 | spin_lock(&sn_irq_info_lock); |
287 | list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); | 309 | list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]); |
310 | reserve_irq_vector(sn_irq_info->irq_irq); | ||
288 | spin_unlock(&sn_irq_info_lock); | 311 | spin_unlock(&sn_irq_info_lock); |
289 | 312 | ||
290 | register_intr_pda(sn_irq_info); | 313 | register_intr_pda(sn_irq_info); |
@@ -310,8 +333,11 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) | |||
310 | spin_lock(&sn_irq_info_lock); | 333 | spin_lock(&sn_irq_info_lock); |
311 | list_del_rcu(&sn_irq_info->list); | 334 | list_del_rcu(&sn_irq_info->list); |
312 | spin_unlock(&sn_irq_info_lock); | 335 | spin_unlock(&sn_irq_info_lock); |
336 | if (list_empty(sn_irq_lh[sn_irq_info->irq_irq])) | ||
337 | free_irq_vector(sn_irq_info->irq_irq); | ||
313 | call_rcu(&sn_irq_info->rcu, sn_irq_info_free); | 338 | call_rcu(&sn_irq_info->rcu, sn_irq_info_free); |
314 | pci_dev_put(pci_dev); | 339 | pci_dev_put(pci_dev); |
340 | |||
315 | } | 341 | } |
316 | 342 | ||
317 | static inline void | 343 | static inline void |
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index b4b84c269210..7a291a271511 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c | |||
@@ -11,7 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <asm/dma.h> | 13 | #include <asm/dma.h> |
14 | #include <asm/sn/pcibr_provider.h> | 14 | #include <asm/sn/intr.h> |
15 | #include <asm/sn/pcibus_provider_defs.h> | 15 | #include <asm/sn/pcibus_provider_defs.h> |
16 | #include <asm/sn/pcidev.h> | 16 | #include <asm/sn/pcidev.h> |
17 | #include <asm/sn/sn_sal.h> | 17 | #include <asm/sn/sn_sal.h> |
@@ -113,7 +113,8 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, | |||
113 | * resources. | 113 | * resources. |
114 | */ | 114 | */ |
115 | 115 | ||
116 | *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size); | 116 | *dma_handle = provider->dma_map_consistent(pdev, phys_addr, size, |
117 | SN_DMA_ADDR_PHYS); | ||
117 | if (!*dma_handle) { | 118 | if (!*dma_handle) { |
118 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); | 119 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); |
119 | free_pages((unsigned long)cpuaddr, get_order(size)); | 120 | free_pages((unsigned long)cpuaddr, get_order(size)); |
@@ -176,7 +177,7 @@ dma_addr_t sn_dma_map_single(struct device *dev, void *cpu_addr, size_t size, | |||
176 | BUG_ON(dev->bus != &pci_bus_type); | 177 | BUG_ON(dev->bus != &pci_bus_type); |
177 | 178 | ||
178 | phys_addr = __pa(cpu_addr); | 179 | phys_addr = __pa(cpu_addr); |
179 | dma_addr = provider->dma_map(pdev, phys_addr, size); | 180 | dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS); |
180 | if (!dma_addr) { | 181 | if (!dma_addr) { |
181 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); | 182 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); |
182 | return 0; | 183 | return 0; |
@@ -260,7 +261,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | |||
260 | for (i = 0; i < nhwentries; i++, sg++) { | 261 | for (i = 0; i < nhwentries; i++, sg++) { |
261 | phys_addr = SG_ENT_PHYS_ADDRESS(sg); | 262 | phys_addr = SG_ENT_PHYS_ADDRESS(sg); |
262 | sg->dma_address = provider->dma_map(pdev, | 263 | sg->dma_address = provider->dma_map(pdev, |
263 | phys_addr, sg->length); | 264 | phys_addr, sg->length, |
265 | SN_DMA_ADDR_PHYS); | ||
264 | 266 | ||
265 | if (!sg->dma_address) { | 267 | if (!sg->dma_address) { |
266 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); | 268 | printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__); |
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index 9f86bb6519aa..a86c7b945962 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c | |||
@@ -41,7 +41,7 @@ extern int sn_ioif_inited; | |||
41 | 41 | ||
42 | static dma_addr_t | 42 | static dma_addr_t |
43 | pcibr_dmamap_ate32(struct pcidev_info *info, | 43 | pcibr_dmamap_ate32(struct pcidev_info *info, |
44 | u64 paddr, size_t req_size, u64 flags) | 44 | u64 paddr, size_t req_size, u64 flags, int dma_flags) |
45 | { | 45 | { |
46 | 46 | ||
47 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; | 47 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; |
@@ -81,9 +81,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info, | |||
81 | if (IS_PCIX(pcibus_info)) | 81 | if (IS_PCIX(pcibus_info)) |
82 | ate_flags &= ~(PCI32_ATE_PREF); | 82 | ate_flags &= ~(PCI32_ATE_PREF); |
83 | 83 | ||
84 | xio_addr = | 84 | if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS)) |
85 | IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : | 85 | xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : |
86 | PHYS_TO_TIODMA(paddr); | 86 | PHYS_TO_TIODMA(paddr); |
87 | else | ||
88 | xio_addr = paddr; | ||
89 | |||
87 | offset = IOPGOFF(xio_addr); | 90 | offset = IOPGOFF(xio_addr); |
88 | ate = ate_flags | (xio_addr - offset); | 91 | ate = ate_flags | (xio_addr - offset); |
89 | 92 | ||
@@ -91,6 +94,13 @@ pcibr_dmamap_ate32(struct pcidev_info *info, | |||
91 | if (IS_PIC_SOFT(pcibus_info)) { | 94 | if (IS_PIC_SOFT(pcibus_info)) { |
92 | ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT); | 95 | ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT); |
93 | } | 96 | } |
97 | |||
98 | /* | ||
99 | * If we're mapping for MSI, set the MSI bit in the ATE | ||
100 | */ | ||
101 | if (dma_flags & SN_DMA_MSI) | ||
102 | ate |= PCI32_ATE_MSI; | ||
103 | |||
94 | ate_write(pcibus_info, ate_index, ate_count, ate); | 104 | ate_write(pcibus_info, ate_index, ate_count, ate); |
95 | 105 | ||
96 | /* | 106 | /* |
@@ -105,20 +115,27 @@ pcibr_dmamap_ate32(struct pcidev_info *info, | |||
105 | if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR) | 115 | if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR) |
106 | ATE_SWAP_ON(pci_addr); | 116 | ATE_SWAP_ON(pci_addr); |
107 | 117 | ||
118 | |||
108 | return pci_addr; | 119 | return pci_addr; |
109 | } | 120 | } |
110 | 121 | ||
111 | static dma_addr_t | 122 | static dma_addr_t |
112 | pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, | 123 | pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, |
113 | u64 dma_attributes) | 124 | u64 dma_attributes, int dma_flags) |
114 | { | 125 | { |
115 | struct pcibus_info *pcibus_info = (struct pcibus_info *) | 126 | struct pcibus_info *pcibus_info = (struct pcibus_info *) |
116 | ((info->pdi_host_pcidev_info)->pdi_pcibus_info); | 127 | ((info->pdi_host_pcidev_info)->pdi_pcibus_info); |
117 | u64 pci_addr; | 128 | u64 pci_addr; |
118 | 129 | ||
119 | /* Translate to Crosstalk View of Physical Address */ | 130 | /* Translate to Crosstalk View of Physical Address */ |
120 | pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : | 131 | if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) |
121 | PHYS_TO_TIODMA(paddr)) | dma_attributes; | 132 | pci_addr = IS_PIC_SOFT(pcibus_info) ? |
133 | PHYS_TO_DMA(paddr) : | ||
134 | PHYS_TO_TIODMA(paddr) | dma_attributes; | ||
135 | else | ||
136 | pci_addr = IS_PIC_SOFT(pcibus_info) ? | ||
137 | paddr : | ||
138 | paddr | dma_attributes; | ||
122 | 139 | ||
123 | /* Handle Bus mode */ | 140 | /* Handle Bus mode */ |
124 | if (IS_PCIX(pcibus_info)) | 141 | if (IS_PCIX(pcibus_info)) |
@@ -130,7 +147,9 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, | |||
130 | ((u64) pcibus_info-> | 147 | ((u64) pcibus_info-> |
131 | pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); | 148 | pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); |
132 | } else | 149 | } else |
133 | pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; | 150 | pci_addr |= (dma_flags & SN_DMA_MSI) ? |
151 | TIOCP_PCI64_CMDTYPE_MSI : | ||
152 | TIOCP_PCI64_CMDTYPE_MEM; | ||
134 | 153 | ||
135 | /* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */ | 154 | /* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */ |
136 | if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn)) | 155 | if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn)) |
@@ -141,7 +160,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, | |||
141 | 160 | ||
142 | static dma_addr_t | 161 | static dma_addr_t |
143 | pcibr_dmatrans_direct32(struct pcidev_info * info, | 162 | pcibr_dmatrans_direct32(struct pcidev_info * info, |
144 | u64 paddr, size_t req_size, u64 flags) | 163 | u64 paddr, size_t req_size, u64 flags, int dma_flags) |
145 | { | 164 | { |
146 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; | 165 | struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; |
147 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> | 166 | struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> |
@@ -156,8 +175,14 @@ pcibr_dmatrans_direct32(struct pcidev_info * info, | |||
156 | return 0; | 175 | return 0; |
157 | } | 176 | } |
158 | 177 | ||
159 | xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : | 178 | if (dma_flags & SN_DMA_MSI) |
160 | PHYS_TO_TIODMA(paddr); | 179 | return 0; |
180 | |||
181 | if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) | ||
182 | xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : | ||
183 | PHYS_TO_TIODMA(paddr); | ||
184 | else | ||
185 | xio_addr = paddr; | ||
161 | 186 | ||
162 | xio_base = pcibus_info->pbi_dir_xbase; | 187 | xio_base = pcibus_info->pbi_dir_xbase; |
163 | offset = xio_addr - xio_base; | 188 | offset = xio_addr - xio_base; |
@@ -327,7 +352,7 @@ void sn_dma_flush(u64 addr) | |||
327 | */ | 352 | */ |
328 | 353 | ||
329 | dma_addr_t | 354 | dma_addr_t |
330 | pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) | 355 | pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags) |
331 | { | 356 | { |
332 | dma_addr_t dma_handle; | 357 | dma_addr_t dma_handle; |
333 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); | 358 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); |
@@ -344,11 +369,11 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) | |||
344 | */ | 369 | */ |
345 | 370 | ||
346 | dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, | 371 | dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, |
347 | PCI64_ATTR_PREF); | 372 | PCI64_ATTR_PREF, dma_flags); |
348 | } else { | 373 | } else { |
349 | /* Handle 32-63 bit cards via direct mapping */ | 374 | /* Handle 32-63 bit cards via direct mapping */ |
350 | dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr, | 375 | dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr, |
351 | size, 0); | 376 | size, 0, dma_flags); |
352 | if (!dma_handle) { | 377 | if (!dma_handle) { |
353 | /* | 378 | /* |
354 | * It is a 32 bit card and we cannot do direct mapping, | 379 | * It is a 32 bit card and we cannot do direct mapping, |
@@ -356,7 +381,8 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) | |||
356 | */ | 381 | */ |
357 | 382 | ||
358 | dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr, | 383 | dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr, |
359 | size, PCI32_ATE_PREF); | 384 | size, PCI32_ATE_PREF, |
385 | dma_flags); | ||
360 | } | 386 | } |
361 | } | 387 | } |
362 | 388 | ||
@@ -365,18 +391,18 @@ pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size) | |||
365 | 391 | ||
366 | dma_addr_t | 392 | dma_addr_t |
367 | pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr, | 393 | pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr, |
368 | size_t size) | 394 | size_t size, int dma_flags) |
369 | { | 395 | { |
370 | dma_addr_t dma_handle; | 396 | dma_addr_t dma_handle; |
371 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); | 397 | struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev); |
372 | 398 | ||
373 | if (hwdev->dev.coherent_dma_mask == ~0UL) { | 399 | if (hwdev->dev.coherent_dma_mask == ~0UL) { |
374 | dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, | 400 | dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr, |
375 | PCI64_ATTR_BAR); | 401 | PCI64_ATTR_BAR, dma_flags); |
376 | } else { | 402 | } else { |
377 | dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info, | 403 | dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info, |
378 | phys_addr, size, | 404 | phys_addr, size, |
379 | PCI32_ATE_BAR); | 405 | PCI32_ATE_BAR, dma_flags); |
380 | } | 406 | } |
381 | 407 | ||
382 | return dma_handle; | 408 | return dma_handle; |
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index be0176912968..20de72791b97 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c | |||
@@ -515,11 +515,17 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) | |||
515 | * use the GART mapped mode. | 515 | * use the GART mapped mode. |
516 | */ | 516 | */ |
517 | static u64 | 517 | static u64 |
518 | tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count) | 518 | tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) |
519 | { | 519 | { |
520 | u64 mapaddr; | 520 | u64 mapaddr; |
521 | 521 | ||
522 | /* | 522 | /* |
523 | * Not supported for now ... | ||
524 | */ | ||
525 | if (dma_flags & SN_DMA_MSI) | ||
526 | return 0; | ||
527 | |||
528 | /* | ||
523 | * If card is 64 or 48 bit addresable, use a direct mapping. 32 | 529 | * If card is 64 or 48 bit addresable, use a direct mapping. 32 |
524 | * bit direct is so restrictive w.r.t. where the memory resides that | 530 | * bit direct is so restrictive w.r.t. where the memory resides that |
525 | * we don't use it even though CA has some support. | 531 | * we don't use it even though CA has some support. |
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index 833295624e5d..4cac7bdc7c7f 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c | |||
@@ -170,7 +170,8 @@ tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr) | |||
170 | (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1) | 170 | (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1) |
171 | 171 | ||
172 | #define ATE_VALID(ate) ((ate) & (1UL << 63)) | 172 | #define ATE_VALID(ate) ((ate) & (1UL << 63)) |
173 | #define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63)) | 173 | #define ATE_MAKE(addr, ps, msi) \ |
174 | (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0)) | ||
174 | 175 | ||
175 | /* | 176 | /* |
176 | * Flavors of ate-based mapping supported by tioce_alloc_map() | 177 | * Flavors of ate-based mapping supported by tioce_alloc_map() |
@@ -196,15 +197,17 @@ tioce_mmr_war_post(struct tioce_kernel *kern, void *mmr_addr) | |||
196 | * | 197 | * |
197 | * 63 - must be 1 to indicate d64 mode to CE hardware | 198 | * 63 - must be 1 to indicate d64 mode to CE hardware |
198 | * 62 - barrier bit ... controlled with tioce_dma_barrier() | 199 | * 62 - barrier bit ... controlled with tioce_dma_barrier() |
199 | * 61 - 0 since this is not an MSI transaction | 200 | * 61 - msi bit ... specified through dma_flags |
200 | * 60:54 - reserved, MBZ | 201 | * 60:54 - reserved, MBZ |
201 | */ | 202 | */ |
202 | static u64 | 203 | static u64 |
203 | tioce_dma_d64(unsigned long ct_addr) | 204 | tioce_dma_d64(unsigned long ct_addr, int dma_flags) |
204 | { | 205 | { |
205 | u64 bus_addr; | 206 | u64 bus_addr; |
206 | 207 | ||
207 | bus_addr = ct_addr | (1UL << 63); | 208 | bus_addr = ct_addr | (1UL << 63); |
209 | if (dma_flags & SN_DMA_MSI) | ||
210 | bus_addr |= (1UL << 61); | ||
208 | 211 | ||
209 | return bus_addr; | 212 | return bus_addr; |
210 | } | 213 | } |
@@ -261,7 +264,7 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base, | |||
261 | */ | 264 | */ |
262 | static u64 | 265 | static u64 |
263 | tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | 266 | tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, |
264 | u64 ct_addr, int len) | 267 | u64 ct_addr, int len, int dma_flags) |
265 | { | 268 | { |
266 | int i; | 269 | int i; |
267 | int j; | 270 | int j; |
@@ -270,6 +273,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
270 | int entries; | 273 | int entries; |
271 | int nates; | 274 | int nates; |
272 | u64 pagesize; | 275 | u64 pagesize; |
276 | int msi_capable, msi_wanted; | ||
273 | u64 *ate_shadow; | 277 | u64 *ate_shadow; |
274 | u64 *ate_reg; | 278 | u64 *ate_reg; |
275 | u64 addr; | 279 | u64 addr; |
@@ -291,6 +295,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
291 | ate_reg = ce_mmr->ce_ure_ate3240; | 295 | ate_reg = ce_mmr->ce_ure_ate3240; |
292 | pagesize = ce_kern->ce_ate3240_pagesize; | 296 | pagesize = ce_kern->ce_ate3240_pagesize; |
293 | bus_base = TIOCE_M32_MIN; | 297 | bus_base = TIOCE_M32_MIN; |
298 | msi_capable = 1; | ||
294 | break; | 299 | break; |
295 | case TIOCE_ATE_M40: | 300 | case TIOCE_ATE_M40: |
296 | first = 0; | 301 | first = 0; |
@@ -299,6 +304,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
299 | ate_reg = ce_mmr->ce_ure_ate40; | 304 | ate_reg = ce_mmr->ce_ure_ate40; |
300 | pagesize = MB(64); | 305 | pagesize = MB(64); |
301 | bus_base = TIOCE_M40_MIN; | 306 | bus_base = TIOCE_M40_MIN; |
307 | msi_capable = 0; | ||
302 | break; | 308 | break; |
303 | case TIOCE_ATE_M40S: | 309 | case TIOCE_ATE_M40S: |
304 | /* | 310 | /* |
@@ -311,11 +317,16 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
311 | ate_reg = ce_mmr->ce_ure_ate3240; | 317 | ate_reg = ce_mmr->ce_ure_ate3240; |
312 | pagesize = GB(16); | 318 | pagesize = GB(16); |
313 | bus_base = TIOCE_M40S_MIN; | 319 | bus_base = TIOCE_M40S_MIN; |
320 | msi_capable = 0; | ||
314 | break; | 321 | break; |
315 | default: | 322 | default: |
316 | return 0; | 323 | return 0; |
317 | } | 324 | } |
318 | 325 | ||
326 | msi_wanted = dma_flags & SN_DMA_MSI; | ||
327 | if (msi_wanted && !msi_capable) | ||
328 | return 0; | ||
329 | |||
319 | nates = ATE_NPAGES(ct_addr, len, pagesize); | 330 | nates = ATE_NPAGES(ct_addr, len, pagesize); |
320 | if (nates > entries) | 331 | if (nates > entries) |
321 | return 0; | 332 | return 0; |
@@ -344,7 +355,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
344 | for (j = 0; j < nates; j++) { | 355 | for (j = 0; j < nates; j++) { |
345 | u64 ate; | 356 | u64 ate; |
346 | 357 | ||
347 | ate = ATE_MAKE(addr, pagesize); | 358 | ate = ATE_MAKE(addr, pagesize, msi_wanted); |
348 | ate_shadow[i + j] = ate; | 359 | ate_shadow[i + j] = ate; |
349 | tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate); | 360 | tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate); |
350 | addr += pagesize; | 361 | addr += pagesize; |
@@ -371,7 +382,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, | |||
371 | * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. | 382 | * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. |
372 | */ | 383 | */ |
373 | static u64 | 384 | static u64 |
374 | tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) | 385 | tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags) |
375 | { | 386 | { |
376 | int dma_ok; | 387 | int dma_ok; |
377 | int port; | 388 | int port; |
@@ -381,6 +392,9 @@ tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) | |||
381 | u64 ct_lower; | 392 | u64 ct_lower; |
382 | dma_addr_t bus_addr; | 393 | dma_addr_t bus_addr; |
383 | 394 | ||
395 | if (dma_flags & SN_DMA_MSI) | ||
396 | return 0; | ||
397 | |||
384 | ct_upper = ct_addr & ~0x3fffffffUL; | 398 | ct_upper = ct_addr & ~0x3fffffffUL; |
385 | ct_lower = ct_addr & 0x3fffffffUL; | 399 | ct_lower = ct_addr & 0x3fffffffUL; |
386 | 400 | ||
@@ -507,7 +521,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) | |||
507 | */ | 521 | */ |
508 | static u64 | 522 | static u64 |
509 | tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, | 523 | tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, |
510 | int barrier) | 524 | int barrier, int dma_flags) |
511 | { | 525 | { |
512 | unsigned long flags; | 526 | unsigned long flags; |
513 | u64 ct_addr; | 527 | u64 ct_addr; |
@@ -523,15 +537,18 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, | |||
523 | if (dma_mask < 0x7fffffffUL) | 537 | if (dma_mask < 0x7fffffffUL) |
524 | return 0; | 538 | return 0; |
525 | 539 | ||
526 | ct_addr = PHYS_TO_TIODMA(paddr); | 540 | if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS) |
541 | ct_addr = PHYS_TO_TIODMA(paddr); | ||
542 | else | ||
543 | ct_addr = paddr; | ||
527 | 544 | ||
528 | /* | 545 | /* |
529 | * If the device can generate 64 bit addresses, create a D64 map. | 546 | * If the device can generate 64 bit addresses, create a D64 map. |
530 | * Since this should never fail, bypass the rest of the checks. | ||
531 | */ | 547 | */ |
532 | if (dma_mask == ~0UL) { | 548 | if (dma_mask == ~0UL) { |
533 | mapaddr = tioce_dma_d64(ct_addr); | 549 | mapaddr = tioce_dma_d64(ct_addr, dma_flags); |
534 | goto dma_map_done; | 550 | if (mapaddr) |
551 | goto dma_map_done; | ||
535 | } | 552 | } |
536 | 553 | ||
537 | pcidev_to_tioce(pdev, NULL, &ce_kern, &port); | 554 | pcidev_to_tioce(pdev, NULL, &ce_kern, &port); |
@@ -574,18 +591,22 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, | |||
574 | 591 | ||
575 | if (byte_count > MB(64)) { | 592 | if (byte_count > MB(64)) { |
576 | mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, | 593 | mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, |
577 | port, ct_addr, byte_count); | 594 | port, ct_addr, byte_count, |
595 | dma_flags); | ||
578 | if (!mapaddr) | 596 | if (!mapaddr) |
579 | mapaddr = | 597 | mapaddr = |
580 | tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, | 598 | tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, |
581 | ct_addr, byte_count); | 599 | ct_addr, byte_count, |
600 | dma_flags); | ||
582 | } else { | 601 | } else { |
583 | mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, | 602 | mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, |
584 | ct_addr, byte_count); | 603 | ct_addr, byte_count, |
604 | dma_flags); | ||
585 | if (!mapaddr) | 605 | if (!mapaddr) |
586 | mapaddr = | 606 | mapaddr = |
587 | tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, | 607 | tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, |
588 | port, ct_addr, byte_count); | 608 | port, ct_addr, byte_count, |
609 | dma_flags); | ||
589 | } | 610 | } |
590 | } | 611 | } |
591 | 612 | ||
@@ -593,7 +614,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, | |||
593 | * 32-bit direct is the next mode to try | 614 | * 32-bit direct is the next mode to try |
594 | */ | 615 | */ |
595 | if (!mapaddr && dma_mask >= 0xffffffffUL) | 616 | if (!mapaddr && dma_mask >= 0xffffffffUL) |
596 | mapaddr = tioce_dma_d32(pdev, ct_addr); | 617 | mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags); |
597 | 618 | ||
598 | /* | 619 | /* |
599 | * Last resort, try 32-bit ATE-based map. | 620 | * Last resort, try 32-bit ATE-based map. |
@@ -601,7 +622,7 @@ tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, | |||
601 | if (!mapaddr) | 622 | if (!mapaddr) |
602 | mapaddr = | 623 | mapaddr = |
603 | tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr, | 624 | tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr, |
604 | byte_count); | 625 | byte_count, dma_flags); |
605 | 626 | ||
606 | spin_unlock_irqrestore(&ce_kern->ce_lock, flags); | 627 | spin_unlock_irqrestore(&ce_kern->ce_lock, flags); |
607 | 628 | ||
@@ -622,9 +643,9 @@ dma_map_done: | |||
622 | * in the address. | 643 | * in the address. |
623 | */ | 644 | */ |
624 | static u64 | 645 | static u64 |
625 | tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) | 646 | tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) |
626 | { | 647 | { |
627 | return tioce_do_dma_map(pdev, paddr, byte_count, 0); | 648 | return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags); |
628 | } | 649 | } |
629 | 650 | ||
630 | /** | 651 | /** |
@@ -636,9 +657,9 @@ tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) | |||
636 | * Simply call tioce_do_dma_map() to create a map with the barrier bit set | 657 | * Simply call tioce_do_dma_map() to create a map with the barrier bit set |
637 | * in the address. | 658 | * in the address. |
638 | */ static u64 | 659 | */ static u64 |
639 | tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count) | 660 | tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags) |
640 | { | 661 | { |
641 | return tioce_do_dma_map(pdev, paddr, byte_count, 1); | 662 | return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags); |
642 | } | 663 | } |
643 | 664 | ||
644 | /** | 665 | /** |
@@ -696,7 +717,7 @@ tioce_reserve_m32(struct tioce_kernel *ce_kern, u64 base, u64 limit) | |||
696 | while (ate_index <= last_ate) { | 717 | while (ate_index <= last_ate) { |
697 | u64 ate; | 718 | u64 ate; |
698 | 719 | ||
699 | ate = ATE_MAKE(0xdeadbeef, ps); | 720 | ate = ATE_MAKE(0xdeadbeef, ps, 0); |
700 | ce_kern->ce_ate3240_shadow[ate_index] = ate; | 721 | ce_kern->ce_ate3240_shadow[ate_index] = ate; |
701 | tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index], | 722 | tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index], |
702 | ate); | 723 | ate); |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 840ae595a617..d961bfeed05f 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -29,8 +29,8 @@ OBJCOPYFLAGS := contents,alloc,load,readonly,data | |||
29 | OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 | 29 | OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000 |
30 | OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment | 30 | OBJCOPY_MIB_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment |
31 | 31 | ||
32 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c | 32 | zlib := inffast.c inflate.c inftrees.c |
33 | zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h | 33 | zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h |
34 | zliblinuxheader := zlib.h zconf.h zutil.h | 34 | zliblinuxheader := zlib.h zconf.h zutil.h |
35 | 35 | ||
36 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) | 36 | $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader)) |
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile index 80c84d562fa4..2f995f712ec5 100644 --- a/arch/ppc/boot/lib/Makefile +++ b/arch/ppc/boot/lib/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | CFLAGS_kbd.o := -Idrivers/char | 5 | CFLAGS_kbd.o := -Idrivers/char |
6 | CFLAGS_vreset.o := -Iarch/ppc/boot/include | 6 | CFLAGS_vreset.o := -Iarch/ppc/boot/include |
7 | 7 | ||
8 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c | 8 | zlib := inffast.c inflate.c inftrees.c |
9 | 9 | ||
10 | lib-y += $(zlib:.c=.o) div64.o | 10 | lib-y += $(zlib:.c=.o) div64.o |
11 | lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o | 11 | lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o |
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c index c9e0aeeca3d8..4368dc3f3c30 100644 --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c | |||
@@ -379,13 +379,12 @@ mpc85xx_cds_pcibios_fixup(void) | |||
379 | PCI_DEVICE_ID_VIA_82C586_2, NULL))) { | 379 | PCI_DEVICE_ID_VIA_82C586_2, NULL))) { |
380 | dev->irq = 10; | 380 | dev->irq = 10; |
381 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); | 381 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); |
382 | pci_dev_put(dev); | ||
383 | } | ||
384 | 382 | ||
385 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | 383 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, |
386 | PCI_DEVICE_ID_VIA_82C586_2, dev))) { | 384 | PCI_DEVICE_ID_VIA_82C586_2, dev))) { |
387 | dev->irq = 11; | 385 | dev->irq = 11; |
388 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); | 386 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); |
387 | } | ||
389 | pci_dev_put(dev); | 388 | pci_dev_put(dev); |
390 | } | 389 | } |
391 | } | 390 | } |
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 2cbf282f0d00..a893a9cc9534 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c | |||
@@ -332,7 +332,7 @@ void __init setup_arch(char **cmdline_p) | |||
332 | if (!root_flags) | 332 | if (!root_flags) |
333 | root_mountflags &= ~MS_RDONLY; | 333 | root_mountflags &= ~MS_RDONLY; |
334 | ROOT_DEV = old_decode_dev(root_dev); | 334 | ROOT_DEV = old_decode_dev(root_dev); |
335 | #ifdef CONFIG_BLK_DEV_INITRD | 335 | #ifdef CONFIG_BLK_DEV_RAM |
336 | rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; | 336 | rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; |
337 | rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); | 337 | rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0); |
338 | rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); | 338 | rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0); |
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 86f51d04c98d..87cdbc560d36 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c | |||
@@ -87,7 +87,7 @@ void timer_irq(union uml_pt_regs *regs) | |||
87 | 87 | ||
88 | void time_init_kern(void) | 88 | void time_init_kern(void) |
89 | { | 89 | { |
90 | unsigned long long nsecs; | 90 | long long nsecs; |
91 | 91 | ||
92 | nsecs = os_nsecs(); | 92 | nsecs = os_nsecs(); |
93 | set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, | 93 | set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 408d44a59756..7d3bc5ac5db0 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -389,6 +389,7 @@ config GART_IOMMU | |||
389 | bool "K8 GART IOMMU support" | 389 | bool "K8 GART IOMMU support" |
390 | default y | 390 | default y |
391 | select SWIOTLB | 391 | select SWIOTLB |
392 | select AGP | ||
392 | depends on PCI | 393 | depends on PCI |
393 | help | 394 | help |
394 | Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors | 395 | Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors |
@@ -401,11 +402,9 @@ config GART_IOMMU | |||
401 | northbridge and a software emulation used on other systems without | 402 | northbridge and a software emulation used on other systems without |
402 | hardware IOMMU. If unsure, say Y. | 403 | hardware IOMMU. If unsure, say Y. |
403 | 404 | ||
404 | # need this always enabled with GART_IOMMU for the VIA workaround | 405 | # need this always selected by GART_IOMMU for the VIA workaround |
405 | config SWIOTLB | 406 | config SWIOTLB |
406 | bool | 407 | bool |
407 | default y | ||
408 | depends on GART_IOMMU | ||
409 | 408 | ||
410 | config X86_MCE | 409 | config X86_MCE |
411 | bool "Machine check support" if EMBEDDED | 410 | bool "Machine check support" if EMBEDDED |
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c index a2060e4d5de6..3c55c76c6fd5 100644 --- a/arch/x86_64/pci/mmconfig.c +++ b/arch/x86_64/pci/mmconfig.c | |||
@@ -13,7 +13,10 @@ | |||
13 | 13 | ||
14 | #include "pci.h" | 14 | #include "pci.h" |
15 | 15 | ||
16 | #define MMCONFIG_APER_SIZE (256*1024*1024) | 16 | /* aperture is up to 256MB but BIOS may reserve less */ |
17 | #define MMCONFIG_APER_MIN (2 * 1024*1024) | ||
18 | #define MMCONFIG_APER_MAX (256 * 1024*1024) | ||
19 | |||
17 | /* Verify the first 16 busses. We assume that systems with more busses | 20 | /* Verify the first 16 busses. We assume that systems with more busses |
18 | get MCFG right. */ | 21 | get MCFG right. */ |
19 | #define MAX_CHECK_BUS 16 | 22 | #define MAX_CHECK_BUS 16 |
@@ -175,9 +178,10 @@ void __init pci_mmcfg_init(void) | |||
175 | return; | 178 | return; |
176 | 179 | ||
177 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, | 180 | if (!e820_all_mapped(pci_mmcfg_config[0].base_address, |
178 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE, | 181 | pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN, |
179 | E820_RESERVED)) { | 182 | E820_RESERVED)) { |
180 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n"); | 183 | printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n", |
184 | pci_mmcfg_config[0].base_address); | ||
181 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); | 185 | printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); |
182 | return; | 186 | return; |
183 | } | 187 | } |
@@ -190,7 +194,8 @@ void __init pci_mmcfg_init(void) | |||
190 | } | 194 | } |
191 | for (i = 0; i < pci_mmcfg_config_num; ++i) { | 195 | for (i = 0; i < pci_mmcfg_config_num; ++i) { |
192 | pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; | 196 | pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i]; |
193 | pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE); | 197 | pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, |
198 | MMCONFIG_APER_MAX); | ||
194 | if (!pci_mmcfg_virt[i].virt) { | 199 | if (!pci_mmcfg_virt[i].virt) { |
195 | printk("PCI: Cannot map mmconfig aperture for segment %d\n", | 200 | printk("PCI: Cannot map mmconfig aperture for segment %d\n", |
196 | pci_mmcfg_config[i].pci_segment_group_number); | 201 | pci_mmcfg_config[i].pci_segment_group_number); |
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile index 9e73bb8aeb7a..d3d2aa2d883a 100644 --- a/arch/xtensa/boot/lib/Makefile +++ b/arch/xtensa/boot/lib/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for some libs needed by zImage. | 2 | # Makefile for some libs needed by zImage. |
3 | # | 3 | # |
4 | 4 | ||
5 | zlib := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c | 5 | zlib := inffast.c inflate.c inftrees.c |
6 | 6 | ||
7 | lib-y += $(zlib:.c=.o) zmem.o | 7 | lib-y += $(zlib:.c=.o) zmem.o |
8 | 8 | ||
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 7c88c060a9e6..46685a540772 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | config AGP | 1 | config AGP |
2 | tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU | 2 | tristate "/dev/agpgart (AGP Support)" |
3 | depends on ALPHA || IA64 || PPC || X86 | 3 | depends on ALPHA || IA64 || PPC || X86 |
4 | default y if GART_IOMMU | ||
5 | ---help--- | 4 | ---help--- |
6 | AGP (Accelerated Graphics Port) is a bus system mainly used to | 5 | AGP (Accelerated Graphics Port) is a bus system mainly used to |
7 | connect graphics cards to the rest of the system. | 6 | connect graphics cards to the rest of the system. |
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e1feb58bd661..1a2b9785e998 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c | |||
@@ -2120,7 +2120,7 @@ abort_linearize: | |||
2120 | goto drop; | 2120 | goto drop; |
2121 | } | 2121 | } |
2122 | 2122 | ||
2123 | if (skb_linearize(skb, GFP_ATOMIC)) | 2123 | if (skb_linearize(skb)) |
2124 | goto drop; | 2124 | goto drop; |
2125 | 2125 | ||
2126 | mgp->tx_linearized++; | 2126 | mgp->tx_linearized++; |
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 6707df968934..f2d152b818f0 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -26,7 +26,11 @@ obj-$(CONFIG_PPC32) += setup-irq.o | |||
26 | obj-$(CONFIG_PPC64) += setup-bus.o | 26 | obj-$(CONFIG_PPC64) += setup-bus.o |
27 | obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o | 27 | obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o |
28 | obj-$(CONFIG_X86_VISWS) += setup-irq.o | 28 | obj-$(CONFIG_X86_VISWS) += setup-irq.o |
29 | obj-$(CONFIG_PCI_MSI) += msi.o | 29 | |
30 | msiobj-y := msi.o msi-apic.o | ||
31 | msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o | ||
32 | msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o | ||
33 | obj-$(CONFIG_PCI_MSI) += $(msiobj-y) | ||
30 | 34 | ||
31 | # | 35 | # |
32 | # ACPI Related PCI FW Functions | 36 | # ACPI Related PCI FW Functions |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index eed67d9e73bc..723092682023 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -81,9 +81,9 @@ void __devinit pci_bus_add_device(struct pci_dev *dev) | |||
81 | { | 81 | { |
82 | device_add(&dev->dev); | 82 | device_add(&dev->dev); |
83 | 83 | ||
84 | spin_lock(&pci_bus_lock); | 84 | down_write(&pci_bus_sem); |
85 | list_add_tail(&dev->global_list, &pci_devices); | 85 | list_add_tail(&dev->global_list, &pci_devices); |
86 | spin_unlock(&pci_bus_lock); | 86 | up_write(&pci_bus_sem); |
87 | 87 | ||
88 | pci_proc_attach_device(dev); | 88 | pci_proc_attach_device(dev); |
89 | pci_create_sysfs_dev_files(dev); | 89 | pci_create_sysfs_dev_files(dev); |
@@ -125,10 +125,10 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus) | |||
125 | */ | 125 | */ |
126 | if (dev->subordinate) { | 126 | if (dev->subordinate) { |
127 | if (list_empty(&dev->subordinate->node)) { | 127 | if (list_empty(&dev->subordinate->node)) { |
128 | spin_lock(&pci_bus_lock); | 128 | down_write(&pci_bus_sem); |
129 | list_add_tail(&dev->subordinate->node, | 129 | list_add_tail(&dev->subordinate->node, |
130 | &dev->bus->children); | 130 | &dev->bus->children); |
131 | spin_unlock(&pci_bus_lock); | 131 | up_write(&pci_bus_sem); |
132 | } | 132 | } |
133 | pci_bus_add_devices(dev->subordinate); | 133 | pci_bus_add_devices(dev->subordinate); |
134 | 134 | ||
@@ -168,7 +168,7 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), | |||
168 | struct list_head *next; | 168 | struct list_head *next; |
169 | 169 | ||
170 | bus = top; | 170 | bus = top; |
171 | spin_lock(&pci_bus_lock); | 171 | down_read(&pci_bus_sem); |
172 | next = top->devices.next; | 172 | next = top->devices.next; |
173 | for (;;) { | 173 | for (;;) { |
174 | if (next == &bus->devices) { | 174 | if (next == &bus->devices) { |
@@ -180,22 +180,19 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), | |||
180 | continue; | 180 | continue; |
181 | } | 181 | } |
182 | dev = list_entry(next, struct pci_dev, bus_list); | 182 | dev = list_entry(next, struct pci_dev, bus_list); |
183 | pci_dev_get(dev); | ||
184 | if (dev->subordinate) { | 183 | if (dev->subordinate) { |
185 | /* this is a pci-pci bridge, do its devices next */ | 184 | /* this is a pci-pci bridge, do its devices next */ |
186 | next = dev->subordinate->devices.next; | 185 | next = dev->subordinate->devices.next; |
187 | bus = dev->subordinate; | 186 | bus = dev->subordinate; |
188 | } else | 187 | } else |
189 | next = dev->bus_list.next; | 188 | next = dev->bus_list.next; |
190 | spin_unlock(&pci_bus_lock); | ||
191 | 189 | ||
192 | /* Run device routines with the bus unlocked */ | 190 | /* Run device routines with the device locked */ |
191 | down(&dev->dev.sem); | ||
193 | cb(dev, userdata); | 192 | cb(dev, userdata); |
194 | 193 | up(&dev->dev.sem); | |
195 | spin_lock(&pci_bus_lock); | ||
196 | pci_dev_put(dev); | ||
197 | } | 194 | } |
198 | spin_unlock(&pci_bus_lock); | 195 | up_read(&pci_bus_sem); |
199 | } | 196 | } |
200 | EXPORT_SYMBOL_GPL(pci_walk_bus); | 197 | EXPORT_SYMBOL_GPL(pci_walk_bus); |
201 | 198 | ||
diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c new file mode 100644 index 000000000000..bed4183a5e39 --- /dev/null +++ b/drivers/pci/msi-altix.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. | ||
7 | */ | ||
8 | |||
9 | #include <linux/types.h> | ||
10 | #include <linux/pci.h> | ||
11 | #include <linux/cpumask.h> | ||
12 | |||
13 | #include <asm/sn/addrs.h> | ||
14 | #include <asm/sn/intr.h> | ||
15 | #include <asm/sn/pcibus_provider_defs.h> | ||
16 | #include <asm/sn/pcidev.h> | ||
17 | #include <asm/sn/nodepda.h> | ||
18 | |||
19 | #include "msi.h" | ||
20 | |||
21 | struct sn_msi_info { | ||
22 | u64 pci_addr; | ||
23 | struct sn_irq_info *sn_irq_info; | ||
24 | }; | ||
25 | |||
26 | static struct sn_msi_info *sn_msi_info; | ||
27 | |||
28 | static void | ||
29 | sn_msi_teardown(unsigned int vector) | ||
30 | { | ||
31 | nasid_t nasid; | ||
32 | int widget; | ||
33 | struct pci_dev *pdev; | ||
34 | struct pcidev_info *sn_pdev; | ||
35 | struct sn_irq_info *sn_irq_info; | ||
36 | struct pcibus_bussoft *bussoft; | ||
37 | struct sn_pcibus_provider *provider; | ||
38 | |||
39 | sn_irq_info = sn_msi_info[vector].sn_irq_info; | ||
40 | if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) | ||
41 | return; | ||
42 | |||
43 | sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | ||
44 | pdev = sn_pdev->pdi_linux_pcidev; | ||
45 | provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
46 | |||
47 | (*provider->dma_unmap)(pdev, | ||
48 | sn_msi_info[vector].pci_addr, | ||
49 | PCI_DMA_FROMDEVICE); | ||
50 | sn_msi_info[vector].pci_addr = 0; | ||
51 | |||
52 | bussoft = SN_PCIDEV_BUSSOFT(pdev); | ||
53 | nasid = NASID_GET(bussoft->bs_base); | ||
54 | widget = (nasid & 1) ? | ||
55 | TIO_SWIN_WIDGETNUM(bussoft->bs_base) : | ||
56 | SWIN_WIDGETNUM(bussoft->bs_base); | ||
57 | |||
58 | sn_intr_free(nasid, widget, sn_irq_info); | ||
59 | sn_msi_info[vector].sn_irq_info = NULL; | ||
60 | |||
61 | return; | ||
62 | } | ||
63 | |||
64 | int | ||
65 | sn_msi_setup(struct pci_dev *pdev, unsigned int vector, | ||
66 | u32 *addr_hi, u32 *addr_lo, u32 *data) | ||
67 | { | ||
68 | int widget; | ||
69 | int status; | ||
70 | nasid_t nasid; | ||
71 | u64 bus_addr; | ||
72 | struct sn_irq_info *sn_irq_info; | ||
73 | struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); | ||
74 | struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
75 | |||
76 | if (bussoft == NULL) | ||
77 | return -EINVAL; | ||
78 | |||
79 | if (provider == NULL || provider->dma_map_consistent == NULL) | ||
80 | return -EINVAL; | ||
81 | |||
82 | /* | ||
83 | * Set up the vector plumbing. Let the prom (via sn_intr_alloc) | ||
84 | * decide which cpu to direct this msi at by default. | ||
85 | */ | ||
86 | |||
87 | nasid = NASID_GET(bussoft->bs_base); | ||
88 | widget = (nasid & 1) ? | ||
89 | TIO_SWIN_WIDGETNUM(bussoft->bs_base) : | ||
90 | SWIN_WIDGETNUM(bussoft->bs_base); | ||
91 | |||
92 | sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); | ||
93 | if (! sn_irq_info) | ||
94 | return -ENOMEM; | ||
95 | |||
96 | status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1); | ||
97 | if (status) { | ||
98 | kfree(sn_irq_info); | ||
99 | return -ENOMEM; | ||
100 | } | ||
101 | |||
102 | sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */ | ||
103 | sn_irq_fixup(pdev, sn_irq_info); | ||
104 | |||
105 | /* Prom probably should fill these in, but doesn't ... */ | ||
106 | sn_irq_info->irq_bridge_type = bussoft->bs_asic_type; | ||
107 | sn_irq_info->irq_bridge = (void *)bussoft->bs_base; | ||
108 | |||
109 | /* | ||
110 | * Map the xio address into bus space | ||
111 | */ | ||
112 | bus_addr = (*provider->dma_map_consistent)(pdev, | ||
113 | sn_irq_info->irq_xtalkaddr, | ||
114 | sizeof(sn_irq_info->irq_xtalkaddr), | ||
115 | SN_DMA_MSI|SN_DMA_ADDR_XIO); | ||
116 | if (! bus_addr) { | ||
117 | sn_intr_free(nasid, widget, sn_irq_info); | ||
118 | kfree(sn_irq_info); | ||
119 | return -ENOMEM; | ||
120 | } | ||
121 | |||
122 | sn_msi_info[vector].sn_irq_info = sn_irq_info; | ||
123 | sn_msi_info[vector].pci_addr = bus_addr; | ||
124 | |||
125 | *addr_hi = (u32)(bus_addr >> 32); | ||
126 | *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); | ||
127 | |||
128 | /* | ||
129 | * In the SN platform, bit 16 is a "send vector" bit which | ||
130 | * must be present in order to move the vector through the system. | ||
131 | */ | ||
132 | *data = 0x100 + (unsigned int)vector; | ||
133 | |||
134 | #ifdef CONFIG_SMP | ||
135 | set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0); | ||
136 | #endif | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static void | ||
142 | sn_msi_target(unsigned int vector, unsigned int cpu, | ||
143 | u32 *addr_hi, u32 *addr_lo) | ||
144 | { | ||
145 | int slice; | ||
146 | nasid_t nasid; | ||
147 | u64 bus_addr; | ||
148 | struct pci_dev *pdev; | ||
149 | struct pcidev_info *sn_pdev; | ||
150 | struct sn_irq_info *sn_irq_info; | ||
151 | struct sn_irq_info *new_irq_info; | ||
152 | struct sn_pcibus_provider *provider; | ||
153 | |||
154 | sn_irq_info = sn_msi_info[vector].sn_irq_info; | ||
155 | if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) | ||
156 | return; | ||
157 | |||
158 | /* | ||
159 | * Release XIO resources for the old MSI PCI address | ||
160 | */ | ||
161 | |||
162 | sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; | ||
163 | pdev = sn_pdev->pdi_linux_pcidev; | ||
164 | provider = SN_PCIDEV_BUSPROVIDER(pdev); | ||
165 | |||
166 | bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo); | ||
167 | (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE); | ||
168 | sn_msi_info[vector].pci_addr = 0; | ||
169 | |||
170 | nasid = cpuid_to_nasid(cpu); | ||
171 | slice = cpuid_to_slice(cpu); | ||
172 | |||
173 | new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice); | ||
174 | sn_msi_info[vector].sn_irq_info = new_irq_info; | ||
175 | if (new_irq_info == NULL) | ||
176 | return; | ||
177 | |||
178 | /* | ||
179 | * Map the xio address into bus space | ||
180 | */ | ||
181 | |||
182 | bus_addr = (*provider->dma_map_consistent)(pdev, | ||
183 | new_irq_info->irq_xtalkaddr, | ||
184 | sizeof(new_irq_info->irq_xtalkaddr), | ||
185 | SN_DMA_MSI|SN_DMA_ADDR_XIO); | ||
186 | |||
187 | sn_msi_info[vector].pci_addr = bus_addr; | ||
188 | *addr_hi = (u32)(bus_addr >> 32); | ||
189 | *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); | ||
190 | } | ||
191 | |||
192 | struct msi_ops sn_msi_ops = { | ||
193 | .setup = sn_msi_setup, | ||
194 | .teardown = sn_msi_teardown, | ||
195 | #ifdef CONFIG_SMP | ||
196 | .target = sn_msi_target, | ||
197 | #endif | ||
198 | }; | ||
199 | |||
200 | int | ||
201 | sn_msi_init(void) | ||
202 | { | ||
203 | sn_msi_info = | ||
204 | kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL); | ||
205 | if (! sn_msi_info) | ||
206 | return -ENOMEM; | ||
207 | |||
208 | msi_register(&sn_msi_ops); | ||
209 | return 0; | ||
210 | } | ||
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c new file mode 100644 index 000000000000..0eb5fe9003a2 --- /dev/null +++ b/drivers/pci/msi-apic.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * MSI hooks for standard x86 apic | ||
3 | */ | ||
4 | |||
5 | #include <linux/pci.h> | ||
6 | #include <linux/irq.h> | ||
7 | |||
8 | #include "msi.h" | ||
9 | |||
10 | /* | ||
11 | * Shifts for APIC-based data | ||
12 | */ | ||
13 | |||
14 | #define MSI_DATA_VECTOR_SHIFT 0 | ||
15 | #define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) | ||
16 | |||
17 | #define MSI_DATA_DELIVERY_SHIFT 8 | ||
18 | #define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) | ||
19 | #define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) | ||
20 | |||
21 | #define MSI_DATA_LEVEL_SHIFT 14 | ||
22 | #define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) | ||
23 | #define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) | ||
24 | |||
25 | #define MSI_DATA_TRIGGER_SHIFT 15 | ||
26 | #define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) | ||
27 | #define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) | ||
28 | |||
29 | /* | ||
30 | * Shift/mask fields for APIC-based bus address | ||
31 | */ | ||
32 | |||
33 | #define MSI_ADDR_HEADER 0xfee00000 | ||
34 | |||
35 | #define MSI_ADDR_DESTID_MASK 0xfff0000f | ||
36 | #define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) | ||
37 | |||
38 | #define MSI_ADDR_DESTMODE_SHIFT 2 | ||
39 | #define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) | ||
40 | #define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) | ||
41 | |||
42 | #define MSI_ADDR_REDIRECTION_SHIFT 3 | ||
43 | #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) | ||
44 | #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) | ||
45 | |||
46 | |||
47 | static void | ||
48 | msi_target_apic(unsigned int vector, | ||
49 | unsigned int dest_cpu, | ||
50 | u32 *address_hi, /* in/out */ | ||
51 | u32 *address_lo) /* in/out */ | ||
52 | { | ||
53 | u32 addr = *address_lo; | ||
54 | |||
55 | addr &= MSI_ADDR_DESTID_MASK; | ||
56 | addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu)); | ||
57 | |||
58 | *address_lo = addr; | ||
59 | } | ||
60 | |||
61 | static int | ||
62 | msi_setup_apic(struct pci_dev *pdev, /* unused in generic */ | ||
63 | unsigned int vector, | ||
64 | u32 *address_hi, | ||
65 | u32 *address_lo, | ||
66 | u32 *data) | ||
67 | { | ||
68 | unsigned long dest_phys_id; | ||
69 | |||
70 | dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); | ||
71 | |||
72 | *address_hi = 0; | ||
73 | *address_lo = MSI_ADDR_HEADER | | ||
74 | MSI_ADDR_DESTMODE_PHYS | | ||
75 | MSI_ADDR_REDIRECTION_CPU | | ||
76 | MSI_ADDR_DESTID_CPU(dest_phys_id); | ||
77 | |||
78 | *data = MSI_DATA_TRIGGER_EDGE | | ||
79 | MSI_DATA_LEVEL_ASSERT | | ||
80 | MSI_DATA_DELIVERY_FIXED | | ||
81 | MSI_DATA_VECTOR(vector); | ||
82 | |||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static void | ||
87 | msi_teardown_apic(unsigned int vector) | ||
88 | { | ||
89 | return; /* no-op */ | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Generic ops used on most IA archs/platforms. Set with msi_register() | ||
94 | */ | ||
95 | |||
96 | struct msi_ops msi_apic_ops = { | ||
97 | .setup = msi_setup_apic, | ||
98 | .teardown = msi_teardown_apic, | ||
99 | .target = msi_target_apic, | ||
100 | }; | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 9855c4c920b8..7f8429284fab 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -23,8 +23,6 @@ | |||
23 | #include "pci.h" | 23 | #include "pci.h" |
24 | #include "msi.h" | 24 | #include "msi.h" |
25 | 25 | ||
26 | #define MSI_TARGET_CPU first_cpu(cpu_online_map) | ||
27 | |||
28 | static DEFINE_SPINLOCK(msi_lock); | 26 | static DEFINE_SPINLOCK(msi_lock); |
29 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; | 27 | static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL }; |
30 | static kmem_cache_t* msi_cachep; | 28 | static kmem_cache_t* msi_cachep; |
@@ -37,9 +35,17 @@ static int nr_msix_devices; | |||
37 | 35 | ||
38 | #ifndef CONFIG_X86_IO_APIC | 36 | #ifndef CONFIG_X86_IO_APIC |
39 | int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; | 37 | int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1}; |
40 | u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 }; | ||
41 | #endif | 38 | #endif |
42 | 39 | ||
40 | static struct msi_ops *msi_ops; | ||
41 | |||
42 | int | ||
43 | msi_register(struct msi_ops *ops) | ||
44 | { | ||
45 | msi_ops = ops; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
43 | static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags) | 49 | static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags) |
44 | { | 50 | { |
45 | memset(p, 0, NR_IRQS * sizeof(struct msi_desc)); | 51 | memset(p, 0, NR_IRQS * sizeof(struct msi_desc)); |
@@ -92,7 +98,7 @@ static void msi_set_mask_bit(unsigned int vector, int flag) | |||
92 | static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | 98 | static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) |
93 | { | 99 | { |
94 | struct msi_desc *entry; | 100 | struct msi_desc *entry; |
95 | struct msg_address address; | 101 | u32 address_hi, address_lo; |
96 | unsigned int irq = vector; | 102 | unsigned int irq = vector; |
97 | unsigned int dest_cpu = first_cpu(cpu_mask); | 103 | unsigned int dest_cpu = first_cpu(cpu_mask); |
98 | 104 | ||
@@ -108,28 +114,36 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask) | |||
108 | if (!pos) | 114 | if (!pos) |
109 | return; | 115 | return; |
110 | 116 | ||
117 | pci_read_config_dword(entry->dev, msi_upper_address_reg(pos), | ||
118 | &address_hi); | ||
111 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), | 119 | pci_read_config_dword(entry->dev, msi_lower_address_reg(pos), |
112 | &address.lo_address.value); | 120 | &address_lo); |
113 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | 121 | |
114 | address.lo_address.value |= (cpu_physical_id(dest_cpu) << | 122 | msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); |
115 | MSI_TARGET_CPU_SHIFT); | 123 | |
116 | entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); | 124 | pci_write_config_dword(entry->dev, msi_upper_address_reg(pos), |
125 | address_hi); | ||
117 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), | 126 | pci_write_config_dword(entry->dev, msi_lower_address_reg(pos), |
118 | address.lo_address.value); | 127 | address_lo); |
119 | set_native_irq_info(irq, cpu_mask); | 128 | set_native_irq_info(irq, cpu_mask); |
120 | break; | 129 | break; |
121 | } | 130 | } |
122 | case PCI_CAP_ID_MSIX: | 131 | case PCI_CAP_ID_MSIX: |
123 | { | 132 | { |
124 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 133 | int offset_hi = |
125 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET; | 134 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
126 | 135 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET; | |
127 | address.lo_address.value = readl(entry->mask_base + offset); | 136 | int offset_lo = |
128 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | 137 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
129 | address.lo_address.value |= (cpu_physical_id(dest_cpu) << | 138 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET; |
130 | MSI_TARGET_CPU_SHIFT); | 139 | |
131 | entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu); | 140 | address_hi = readl(entry->mask_base + offset_hi); |
132 | writel(address.lo_address.value, entry->mask_base + offset); | 141 | address_lo = readl(entry->mask_base + offset_lo); |
142 | |||
143 | msi_ops->target(vector, dest_cpu, &address_hi, &address_lo); | ||
144 | |||
145 | writel(address_hi, entry->mask_base + offset_hi); | ||
146 | writel(address_lo, entry->mask_base + offset_lo); | ||
133 | set_native_irq_info(irq, cpu_mask); | 147 | set_native_irq_info(irq, cpu_mask); |
134 | break; | 148 | break; |
135 | } | 149 | } |
@@ -251,30 +265,6 @@ static struct hw_interrupt_type msi_irq_wo_maskbit_type = { | |||
251 | .set_affinity = set_msi_affinity | 265 | .set_affinity = set_msi_affinity |
252 | }; | 266 | }; |
253 | 267 | ||
254 | static void msi_data_init(struct msg_data *msi_data, | ||
255 | unsigned int vector) | ||
256 | { | ||
257 | memset(msi_data, 0, sizeof(struct msg_data)); | ||
258 | msi_data->vector = (u8)vector; | ||
259 | msi_data->delivery_mode = MSI_DELIVERY_MODE; | ||
260 | msi_data->level = MSI_LEVEL_MODE; | ||
261 | msi_data->trigger = MSI_TRIGGER_MODE; | ||
262 | } | ||
263 | |||
264 | static void msi_address_init(struct msg_address *msi_address) | ||
265 | { | ||
266 | unsigned int dest_id; | ||
267 | unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU); | ||
268 | |||
269 | memset(msi_address, 0, sizeof(struct msg_address)); | ||
270 | msi_address->hi_address = (u32)0; | ||
271 | dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT); | ||
272 | msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE; | ||
273 | msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE; | ||
274 | msi_address->lo_address.u.dest_id = dest_id; | ||
275 | msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT); | ||
276 | } | ||
277 | |||
278 | static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); | 268 | static int msi_free_vector(struct pci_dev* dev, int vector, int reassign); |
279 | static int assign_msi_vector(void) | 269 | static int assign_msi_vector(void) |
280 | { | 270 | { |
@@ -369,13 +359,29 @@ static int msi_init(void) | |||
369 | return status; | 359 | return status; |
370 | } | 360 | } |
371 | 361 | ||
362 | status = msi_arch_init(); | ||
363 | if (status < 0) { | ||
364 | pci_msi_enable = 0; | ||
365 | printk(KERN_WARNING | ||
366 | "PCI: MSI arch init failed. MSI disabled.\n"); | ||
367 | return status; | ||
368 | } | ||
369 | |||
370 | if (! msi_ops) { | ||
371 | printk(KERN_WARNING | ||
372 | "PCI: MSI ops not registered. MSI disabled.\n"); | ||
373 | status = -EINVAL; | ||
374 | return status; | ||
375 | } | ||
376 | |||
377 | last_alloc_vector = assign_irq_vector(AUTO_ASSIGN); | ||
372 | status = msi_cache_init(); | 378 | status = msi_cache_init(); |
373 | if (status < 0) { | 379 | if (status < 0) { |
374 | pci_msi_enable = 0; | 380 | pci_msi_enable = 0; |
375 | printk(KERN_WARNING "PCI: MSI cache init failed\n"); | 381 | printk(KERN_WARNING "PCI: MSI cache init failed\n"); |
376 | return status; | 382 | return status; |
377 | } | 383 | } |
378 | last_alloc_vector = assign_irq_vector(AUTO_ASSIGN); | 384 | |
379 | if (last_alloc_vector < 0) { | 385 | if (last_alloc_vector < 0) { |
380 | pci_msi_enable = 0; | 386 | pci_msi_enable = 0; |
381 | printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n"); | 387 | printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n"); |
@@ -442,9 +448,11 @@ static void enable_msi_mode(struct pci_dev *dev, int pos, int type) | |||
442 | /* Set enabled bits to single MSI & enable MSI_enable bit */ | 448 | /* Set enabled bits to single MSI & enable MSI_enable bit */ |
443 | msi_enable(control, 1); | 449 | msi_enable(control, 1); |
444 | pci_write_config_word(dev, msi_control_reg(pos), control); | 450 | pci_write_config_word(dev, msi_control_reg(pos), control); |
451 | dev->msi_enabled = 1; | ||
445 | } else { | 452 | } else { |
446 | msix_enable(control); | 453 | msix_enable(control); |
447 | pci_write_config_word(dev, msi_control_reg(pos), control); | 454 | pci_write_config_word(dev, msi_control_reg(pos), control); |
455 | dev->msix_enabled = 1; | ||
448 | } | 456 | } |
449 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { | 457 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { |
450 | /* PCI Express Endpoint device detected */ | 458 | /* PCI Express Endpoint device detected */ |
@@ -461,9 +469,11 @@ void disable_msi_mode(struct pci_dev *dev, int pos, int type) | |||
461 | /* Set enabled bits to single MSI & enable MSI_enable bit */ | 469 | /* Set enabled bits to single MSI & enable MSI_enable bit */ |
462 | msi_disable(control); | 470 | msi_disable(control); |
463 | pci_write_config_word(dev, msi_control_reg(pos), control); | 471 | pci_write_config_word(dev, msi_control_reg(pos), control); |
472 | dev->msi_enabled = 0; | ||
464 | } else { | 473 | } else { |
465 | msix_disable(control); | 474 | msix_disable(control); |
466 | pci_write_config_word(dev, msi_control_reg(pos), control); | 475 | pci_write_config_word(dev, msi_control_reg(pos), control); |
476 | dev->msix_enabled = 0; | ||
467 | } | 477 | } |
468 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { | 478 | if (pci_find_capability(dev, PCI_CAP_ID_EXP)) { |
469 | /* PCI Express Endpoint device detected */ | 479 | /* PCI Express Endpoint device detected */ |
@@ -538,7 +548,6 @@ int pci_save_msi_state(struct pci_dev *dev) | |||
538 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); | 548 | pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]); |
539 | if (control & PCI_MSI_FLAGS_MASKBIT) | 549 | if (control & PCI_MSI_FLAGS_MASKBIT) |
540 | pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); | 550 | pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]); |
541 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | ||
542 | save_state->cap_nr = PCI_CAP_ID_MSI; | 551 | save_state->cap_nr = PCI_CAP_ID_MSI; |
543 | pci_add_saved_cap(dev, save_state); | 552 | pci_add_saved_cap(dev, save_state); |
544 | return 0; | 553 | return 0; |
@@ -575,6 +584,8 @@ void pci_restore_msi_state(struct pci_dev *dev) | |||
575 | int pci_save_msix_state(struct pci_dev *dev) | 584 | int pci_save_msix_state(struct pci_dev *dev) |
576 | { | 585 | { |
577 | int pos; | 586 | int pos; |
587 | int temp; | ||
588 | int vector, head, tail = 0; | ||
578 | u16 control; | 589 | u16 control; |
579 | struct pci_cap_saved_state *save_state; | 590 | struct pci_cap_saved_state *save_state; |
580 | 591 | ||
@@ -582,6 +593,7 @@ int pci_save_msix_state(struct pci_dev *dev) | |||
582 | if (pos <= 0 || dev->no_msi) | 593 | if (pos <= 0 || dev->no_msi) |
583 | return 0; | 594 | return 0; |
584 | 595 | ||
596 | /* save the capability */ | ||
585 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 597 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
586 | if (!(control & PCI_MSIX_FLAGS_ENABLE)) | 598 | if (!(control & PCI_MSIX_FLAGS_ENABLE)) |
587 | return 0; | 599 | return 0; |
@@ -593,7 +605,38 @@ int pci_save_msix_state(struct pci_dev *dev) | |||
593 | } | 605 | } |
594 | *((u16 *)&save_state->data[0]) = control; | 606 | *((u16 *)&save_state->data[0]) = control; |
595 | 607 | ||
596 | disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX); | 608 | /* save the table */ |
609 | temp = dev->irq; | ||
610 | if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) { | ||
611 | kfree(save_state); | ||
612 | return -EINVAL; | ||
613 | } | ||
614 | |||
615 | vector = head = dev->irq; | ||
616 | while (head != tail) { | ||
617 | int j; | ||
618 | void __iomem *base; | ||
619 | struct msi_desc *entry; | ||
620 | |||
621 | entry = msi_desc[vector]; | ||
622 | base = entry->mask_base; | ||
623 | j = entry->msi_attrib.entry_nr; | ||
624 | |||
625 | entry->address_lo_save = | ||
626 | readl(base + j * PCI_MSIX_ENTRY_SIZE + | ||
627 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
628 | entry->address_hi_save = | ||
629 | readl(base + j * PCI_MSIX_ENTRY_SIZE + | ||
630 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
631 | entry->data_save = | ||
632 | readl(base + j * PCI_MSIX_ENTRY_SIZE + | ||
633 | PCI_MSIX_ENTRY_DATA_OFFSET); | ||
634 | |||
635 | tail = msi_desc[vector]->link.tail; | ||
636 | vector = tail; | ||
637 | } | ||
638 | dev->irq = temp; | ||
639 | |||
597 | save_state->cap_nr = PCI_CAP_ID_MSIX; | 640 | save_state->cap_nr = PCI_CAP_ID_MSIX; |
598 | pci_add_saved_cap(dev, save_state); | 641 | pci_add_saved_cap(dev, save_state); |
599 | return 0; | 642 | return 0; |
@@ -606,8 +649,6 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
606 | int vector, head, tail = 0; | 649 | int vector, head, tail = 0; |
607 | void __iomem *base; | 650 | void __iomem *base; |
608 | int j; | 651 | int j; |
609 | struct msg_address address; | ||
610 | struct msg_data data; | ||
611 | struct msi_desc *entry; | 652 | struct msi_desc *entry; |
612 | int temp; | 653 | int temp; |
613 | struct pci_cap_saved_state *save_state; | 654 | struct pci_cap_saved_state *save_state; |
@@ -633,20 +674,13 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
633 | base = entry->mask_base; | 674 | base = entry->mask_base; |
634 | j = entry->msi_attrib.entry_nr; | 675 | j = entry->msi_attrib.entry_nr; |
635 | 676 | ||
636 | msi_address_init(&address); | 677 | writel(entry->address_lo_save, |
637 | msi_data_init(&data, vector); | ||
638 | |||
639 | address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK; | ||
640 | address.lo_address.value |= entry->msi_attrib.current_cpu << | ||
641 | MSI_TARGET_CPU_SHIFT; | ||
642 | |||
643 | writel(address.lo_address.value, | ||
644 | base + j * PCI_MSIX_ENTRY_SIZE + | 678 | base + j * PCI_MSIX_ENTRY_SIZE + |
645 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | 679 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); |
646 | writel(address.hi_address, | 680 | writel(entry->address_hi_save, |
647 | base + j * PCI_MSIX_ENTRY_SIZE + | 681 | base + j * PCI_MSIX_ENTRY_SIZE + |
648 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | 682 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); |
649 | writel(*(u32*)&data, | 683 | writel(entry->data_save, |
650 | base + j * PCI_MSIX_ENTRY_SIZE + | 684 | base + j * PCI_MSIX_ENTRY_SIZE + |
651 | PCI_MSIX_ENTRY_DATA_OFFSET); | 685 | PCI_MSIX_ENTRY_DATA_OFFSET); |
652 | 686 | ||
@@ -660,30 +694,32 @@ void pci_restore_msix_state(struct pci_dev *dev) | |||
660 | } | 694 | } |
661 | #endif | 695 | #endif |
662 | 696 | ||
663 | static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) | 697 | static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry) |
664 | { | 698 | { |
665 | struct msg_address address; | 699 | int status; |
666 | struct msg_data data; | 700 | u32 address_hi; |
701 | u32 address_lo; | ||
702 | u32 data; | ||
667 | int pos, vector = dev->irq; | 703 | int pos, vector = dev->irq; |
668 | u16 control; | 704 | u16 control; |
669 | 705 | ||
670 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 706 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
671 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 707 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
708 | |||
672 | /* Configure MSI capability structure */ | 709 | /* Configure MSI capability structure */ |
673 | msi_address_init(&address); | 710 | status = msi_ops->setup(dev, vector, &address_hi, &address_lo, &data); |
674 | msi_data_init(&data, vector); | 711 | if (status < 0) |
675 | entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >> | 712 | return status; |
676 | MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); | 713 | |
677 | pci_write_config_dword(dev, msi_lower_address_reg(pos), | 714 | pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo); |
678 | address.lo_address.value); | ||
679 | if (is_64bit_address(control)) { | 715 | if (is_64bit_address(control)) { |
680 | pci_write_config_dword(dev, | 716 | pci_write_config_dword(dev, |
681 | msi_upper_address_reg(pos), address.hi_address); | 717 | msi_upper_address_reg(pos), address_hi); |
682 | pci_write_config_word(dev, | 718 | pci_write_config_word(dev, |
683 | msi_data_reg(pos, 1), *((u32*)&data)); | 719 | msi_data_reg(pos, 1), data); |
684 | } else | 720 | } else |
685 | pci_write_config_word(dev, | 721 | pci_write_config_word(dev, |
686 | msi_data_reg(pos, 0), *((u32*)&data)); | 722 | msi_data_reg(pos, 0), data); |
687 | if (entry->msi_attrib.maskbit) { | 723 | if (entry->msi_attrib.maskbit) { |
688 | unsigned int maskbits, temp; | 724 | unsigned int maskbits, temp; |
689 | /* All MSIs are unmasked by default, Mask them all */ | 725 | /* All MSIs are unmasked by default, Mask them all */ |
@@ -697,6 +733,8 @@ static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) | |||
697 | msi_mask_bits_reg(pos, is_64bit_address(control)), | 733 | msi_mask_bits_reg(pos, is_64bit_address(control)), |
698 | maskbits); | 734 | maskbits); |
699 | } | 735 | } |
736 | |||
737 | return 0; | ||
700 | } | 738 | } |
701 | 739 | ||
702 | /** | 740 | /** |
@@ -710,6 +748,7 @@ static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry) | |||
710 | **/ | 748 | **/ |
711 | static int msi_capability_init(struct pci_dev *dev) | 749 | static int msi_capability_init(struct pci_dev *dev) |
712 | { | 750 | { |
751 | int status; | ||
713 | struct msi_desc *entry; | 752 | struct msi_desc *entry; |
714 | int pos, vector; | 753 | int pos, vector; |
715 | u16 control; | 754 | u16 control; |
@@ -742,7 +781,12 @@ static int msi_capability_init(struct pci_dev *dev) | |||
742 | /* Replace with MSI handler */ | 781 | /* Replace with MSI handler */ |
743 | irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit); | 782 | irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit); |
744 | /* Configure MSI capability structure */ | 783 | /* Configure MSI capability structure */ |
745 | msi_register_init(dev, entry); | 784 | status = msi_register_init(dev, entry); |
785 | if (status != 0) { | ||
786 | dev->irq = entry->msi_attrib.default_vector; | ||
787 | kmem_cache_free(msi_cachep, entry); | ||
788 | return status; | ||
789 | } | ||
746 | 790 | ||
747 | attach_msi_entry(entry, vector); | 791 | attach_msi_entry(entry, vector); |
748 | /* Set MSI enabled bits */ | 792 | /* Set MSI enabled bits */ |
@@ -765,8 +809,10 @@ static int msix_capability_init(struct pci_dev *dev, | |||
765 | struct msix_entry *entries, int nvec) | 809 | struct msix_entry *entries, int nvec) |
766 | { | 810 | { |
767 | struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; | 811 | struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; |
768 | struct msg_address address; | 812 | u32 address_hi; |
769 | struct msg_data data; | 813 | u32 address_lo; |
814 | u32 data; | ||
815 | int status; | ||
770 | int vector, pos, i, j, nr_entries, temp = 0; | 816 | int vector, pos, i, j, nr_entries, temp = 0; |
771 | unsigned long phys_addr; | 817 | unsigned long phys_addr; |
772 | u32 table_offset; | 818 | u32 table_offset; |
@@ -822,18 +868,20 @@ static int msix_capability_init(struct pci_dev *dev, | |||
822 | /* Replace with MSI-X handler */ | 868 | /* Replace with MSI-X handler */ |
823 | irq_handler_init(PCI_CAP_ID_MSIX, vector, 1); | 869 | irq_handler_init(PCI_CAP_ID_MSIX, vector, 1); |
824 | /* Configure MSI-X capability structure */ | 870 | /* Configure MSI-X capability structure */ |
825 | msi_address_init(&address); | 871 | status = msi_ops->setup(dev, vector, |
826 | msi_data_init(&data, vector); | 872 | &address_hi, |
827 | entry->msi_attrib.current_cpu = | 873 | &address_lo, |
828 | ((address.lo_address.u.dest_id >> | 874 | &data); |
829 | MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK); | 875 | if (status < 0) |
830 | writel(address.lo_address.value, | 876 | break; |
877 | |||
878 | writel(address_lo, | ||
831 | base + j * PCI_MSIX_ENTRY_SIZE + | 879 | base + j * PCI_MSIX_ENTRY_SIZE + |
832 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | 880 | PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); |
833 | writel(address.hi_address, | 881 | writel(address_hi, |
834 | base + j * PCI_MSIX_ENTRY_SIZE + | 882 | base + j * PCI_MSIX_ENTRY_SIZE + |
835 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | 883 | PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); |
836 | writel(*(u32*)&data, | 884 | writel(data, |
837 | base + j * PCI_MSIX_ENTRY_SIZE + | 885 | base + j * PCI_MSIX_ENTRY_SIZE + |
838 | PCI_MSIX_ENTRY_DATA_OFFSET); | 886 | PCI_MSIX_ENTRY_DATA_OFFSET); |
839 | attach_msi_entry(entry, vector); | 887 | attach_msi_entry(entry, vector); |
@@ -865,6 +913,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
865 | **/ | 913 | **/ |
866 | int pci_enable_msi(struct pci_dev* dev) | 914 | int pci_enable_msi(struct pci_dev* dev) |
867 | { | 915 | { |
916 | struct pci_bus *bus; | ||
868 | int pos, temp, status = -EINVAL; | 917 | int pos, temp, status = -EINVAL; |
869 | u16 control; | 918 | u16 control; |
870 | 919 | ||
@@ -874,8 +923,9 @@ int pci_enable_msi(struct pci_dev* dev) | |||
874 | if (dev->no_msi) | 923 | if (dev->no_msi) |
875 | return status; | 924 | return status; |
876 | 925 | ||
877 | if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) | 926 | for (bus = dev->bus; bus; bus = bus->parent) |
878 | return -EINVAL; | 927 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) |
928 | return -EINVAL; | ||
879 | 929 | ||
880 | temp = dev->irq; | 930 | temp = dev->irq; |
881 | 931 | ||
@@ -887,23 +937,23 @@ int pci_enable_msi(struct pci_dev* dev) | |||
887 | if (!pos) | 937 | if (!pos) |
888 | return -EINVAL; | 938 | return -EINVAL; |
889 | 939 | ||
890 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
891 | if (control & PCI_MSI_FLAGS_ENABLE) | ||
892 | return 0; /* Already in MSI mode */ | ||
893 | |||
894 | if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { | 940 | if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) { |
895 | /* Lookup Sucess */ | 941 | /* Lookup Sucess */ |
896 | unsigned long flags; | 942 | unsigned long flags; |
897 | 943 | ||
944 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
945 | if (control & PCI_MSI_FLAGS_ENABLE) | ||
946 | return 0; /* Already in MSI mode */ | ||
898 | spin_lock_irqsave(&msi_lock, flags); | 947 | spin_lock_irqsave(&msi_lock, flags); |
899 | if (!vector_irq[dev->irq]) { | 948 | if (!vector_irq[dev->irq]) { |
900 | msi_desc[dev->irq]->msi_attrib.state = 0; | 949 | msi_desc[dev->irq]->msi_attrib.state = 0; |
901 | vector_irq[dev->irq] = -1; | 950 | vector_irq[dev->irq] = -1; |
902 | nr_released_vectors--; | 951 | nr_released_vectors--; |
903 | spin_unlock_irqrestore(&msi_lock, flags); | 952 | spin_unlock_irqrestore(&msi_lock, flags); |
904 | msi_register_init(dev, msi_desc[dev->irq]); | 953 | status = msi_register_init(dev, msi_desc[dev->irq]); |
905 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); | 954 | if (status == 0) |
906 | return 0; | 955 | enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); |
956 | return status; | ||
907 | } | 957 | } |
908 | spin_unlock_irqrestore(&msi_lock, flags); | 958 | spin_unlock_irqrestore(&msi_lock, flags); |
909 | dev->irq = temp; | 959 | dev->irq = temp; |
@@ -980,6 +1030,8 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) | |||
980 | void __iomem *base; | 1030 | void __iomem *base; |
981 | unsigned long flags; | 1031 | unsigned long flags; |
982 | 1032 | ||
1033 | msi_ops->teardown(vector); | ||
1034 | |||
983 | spin_lock_irqsave(&msi_lock, flags); | 1035 | spin_lock_irqsave(&msi_lock, flags); |
984 | entry = msi_desc[vector]; | 1036 | entry = msi_desc[vector]; |
985 | if (!entry || entry->dev != dev) { | 1037 | if (!entry || entry->dev != dev) { |
@@ -1008,33 +1060,8 @@ static int msi_free_vector(struct pci_dev* dev, int vector, int reassign) | |||
1008 | entry_nr * PCI_MSIX_ENTRY_SIZE + | 1060 | entry_nr * PCI_MSIX_ENTRY_SIZE + |
1009 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); | 1061 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); |
1010 | 1062 | ||
1011 | if (head == vector) { | 1063 | if (head == vector) |
1012 | /* | ||
1013 | * Detect last MSI-X vector to be released. | ||
1014 | * Release the MSI-X memory-mapped table. | ||
1015 | */ | ||
1016 | #if 0 | ||
1017 | int pos, nr_entries; | ||
1018 | unsigned long phys_addr; | ||
1019 | u32 table_offset; | ||
1020 | u16 control; | ||
1021 | u8 bir; | ||
1022 | |||
1023 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
1024 | pci_read_config_word(dev, msi_control_reg(pos), | ||
1025 | &control); | ||
1026 | nr_entries = multi_msix_capable(control); | ||
1027 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | ||
1028 | &table_offset); | ||
1029 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
1030 | table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; | ||
1031 | phys_addr = pci_resource_start(dev, bir) + table_offset; | ||
1032 | /* | ||
1033 | * FIXME! and what did you want to do with phys_addr? | ||
1034 | */ | ||
1035 | #endif | ||
1036 | iounmap(base); | 1064 | iounmap(base); |
1037 | } | ||
1038 | } | 1065 | } |
1039 | 1066 | ||
1040 | return 0; | 1067 | return 0; |
@@ -1108,6 +1135,7 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec) | |||
1108 | **/ | 1135 | **/ |
1109 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | 1136 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) |
1110 | { | 1137 | { |
1138 | struct pci_bus *bus; | ||
1111 | int status, pos, nr_entries, free_vectors; | 1139 | int status, pos, nr_entries, free_vectors; |
1112 | int i, j, temp; | 1140 | int i, j, temp; |
1113 | u16 control; | 1141 | u16 control; |
@@ -1116,6 +1144,13 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
1116 | if (!pci_msi_enable || !dev || !entries) | 1144 | if (!pci_msi_enable || !dev || !entries) |
1117 | return -EINVAL; | 1145 | return -EINVAL; |
1118 | 1146 | ||
1147 | if (dev->no_msi) | ||
1148 | return -EINVAL; | ||
1149 | |||
1150 | for (bus = dev->bus; bus; bus = bus->parent) | ||
1151 | if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) | ||
1152 | return -EINVAL; | ||
1153 | |||
1119 | status = msi_init(); | 1154 | status = msi_init(); |
1120 | if (status < 0) | 1155 | if (status < 0) |
1121 | return status; | 1156 | return status; |
@@ -1300,24 +1335,6 @@ void msi_remove_pci_irq_vectors(struct pci_dev* dev) | |||
1300 | } | 1335 | } |
1301 | msi_free_vector(dev, vector, 0); | 1336 | msi_free_vector(dev, vector, 0); |
1302 | if (warning) { | 1337 | if (warning) { |
1303 | /* Force to release the MSI-X memory-mapped table */ | ||
1304 | #if 0 | ||
1305 | unsigned long phys_addr; | ||
1306 | u32 table_offset; | ||
1307 | u16 control; | ||
1308 | u8 bir; | ||
1309 | |||
1310 | pci_read_config_word(dev, msi_control_reg(pos), | ||
1311 | &control); | ||
1312 | pci_read_config_dword(dev, msix_table_offset_reg(pos), | ||
1313 | &table_offset); | ||
1314 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | ||
1315 | table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; | ||
1316 | phys_addr = pci_resource_start(dev, bir) + table_offset; | ||
1317 | /* | ||
1318 | * FIXME! and what did you want to do with phys_addr? | ||
1319 | */ | ||
1320 | #endif | ||
1321 | iounmap(base); | 1338 | iounmap(base); |
1322 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " | 1339 | printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() " |
1323 | "called without free_irq() on all MSI-X vectors\n", | 1340 | "called without free_irq() on all MSI-X vectors\n", |
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 4ac52d441e47..56951c39d3a3 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -6,6 +6,68 @@ | |||
6 | #ifndef MSI_H | 6 | #ifndef MSI_H |
7 | #define MSI_H | 7 | #define MSI_H |
8 | 8 | ||
9 | /* | ||
10 | * MSI operation vector. Used by the msi core code (drivers/pci/msi.c) | ||
11 | * to abstract platform-specific tasks relating to MSI address generation | ||
12 | * and resource management. | ||
13 | */ | ||
14 | struct msi_ops { | ||
15 | /** | ||
16 | * setup - generate an MSI bus address and data for a given vector | ||
17 | * @pdev: PCI device context (in) | ||
18 | * @vector: vector allocated by the msi core (in) | ||
19 | * @addr_hi: upper 32 bits of PCI bus MSI address (out) | ||
20 | * @addr_lo: lower 32 bits of PCI bus MSI address (out) | ||
21 | * @data: MSI data payload (out) | ||
22 | * | ||
23 | * Description: The setup op is used to generate a PCI bus addres and | ||
24 | * data which the msi core will program into the card MSI capability | ||
25 | * registers. The setup routine is responsible for picking an initial | ||
26 | * cpu to target the MSI at. The setup routine is responsible for | ||
27 | * examining pdev to determine the MSI capabilities of the card and | ||
28 | * generating a suitable address/data. The setup routine is | ||
29 | * responsible for allocating and tracking any system resources it | ||
30 | * needs to route the MSI to the cpu it picks, and for associating | ||
31 | * those resources with the passed in vector. | ||
32 | * | ||
33 | * Returns 0 if the MSI address/data was successfully setup. | ||
34 | **/ | ||
35 | |||
36 | int (*setup) (struct pci_dev *pdev, unsigned int vector, | ||
37 | u32 *addr_hi, u32 *addr_lo, u32 *data); | ||
38 | |||
39 | /** | ||
40 | * teardown - release resources allocated by setup | ||
41 | * @vector: vector context for resources (in) | ||
42 | * | ||
43 | * Description: The teardown op is used to release any resources | ||
44 | * that were allocated in the setup routine associated with the passed | ||
45 | * in vector. | ||
46 | **/ | ||
47 | |||
48 | void (*teardown) (unsigned int vector); | ||
49 | |||
50 | /** | ||
51 | * target - retarget an MSI at a different cpu | ||
52 | * @vector: vector context for resources (in) | ||
53 | * @cpu: new cpu to direct vector at (in) | ||
54 | * @addr_hi: new value of PCI bus upper 32 bits (in/out) | ||
55 | * @addr_lo: new value of PCI bus lower 32 bits (in/out) | ||
56 | * | ||
57 | * Description: The target op is used to redirect an MSI vector | ||
58 | * at a different cpu. addr_hi/addr_lo coming in are the existing | ||
59 | * values that the MSI core has programmed into the card. The | ||
60 | * target code is responsible for freeing any resources (if any) | ||
61 | * associated with the old address, and generating a new PCI bus | ||
62 | * addr_hi/addr_lo that will redirect the vector at the indicated cpu. | ||
63 | **/ | ||
64 | |||
65 | void (*target) (unsigned int vector, unsigned int cpu, | ||
66 | u32 *addr_hi, u32 *addr_lo); | ||
67 | }; | ||
68 | |||
69 | extern int msi_register(struct msi_ops *ops); | ||
70 | |||
9 | #include <asm/msi.h> | 71 | #include <asm/msi.h> |
10 | 72 | ||
11 | /* | 73 | /* |
@@ -63,67 +125,6 @@ extern int pci_vector_resources(int last, int nr_released); | |||
63 | #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) | 125 | #define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) |
64 | #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) | 126 | #define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) |
65 | 127 | ||
66 | /* | ||
67 | * MSI Defined Data Structures | ||
68 | */ | ||
69 | #define MSI_ADDRESS_HEADER 0xfee | ||
70 | #define MSI_ADDRESS_HEADER_SHIFT 12 | ||
71 | #define MSI_ADDRESS_HEADER_MASK 0xfff000 | ||
72 | #define MSI_ADDRESS_DEST_ID_MASK 0xfff0000f | ||
73 | #define MSI_TARGET_CPU_MASK 0xff | ||
74 | #define MSI_DELIVERY_MODE 0 | ||
75 | #define MSI_LEVEL_MODE 1 /* Edge always assert */ | ||
76 | #define MSI_TRIGGER_MODE 0 /* MSI is edge sensitive */ | ||
77 | #define MSI_PHYSICAL_MODE 0 | ||
78 | #define MSI_LOGICAL_MODE 1 | ||
79 | #define MSI_REDIRECTION_HINT_MODE 0 | ||
80 | |||
81 | struct msg_data { | ||
82 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
83 | __u32 vector : 8; | ||
84 | __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ | ||
85 | __u32 reserved_1 : 3; | ||
86 | __u32 level : 1; /* 0: deassert | 1: assert */ | ||
87 | __u32 trigger : 1; /* 0: edge | 1: level */ | ||
88 | __u32 reserved_2 : 16; | ||
89 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
90 | __u32 reserved_2 : 16; | ||
91 | __u32 trigger : 1; /* 0: edge | 1: level */ | ||
92 | __u32 level : 1; /* 0: deassert | 1: assert */ | ||
93 | __u32 reserved_1 : 3; | ||
94 | __u32 delivery_mode : 3; /* 000b: FIXED | 001b: lowest prior */ | ||
95 | __u32 vector : 8; | ||
96 | #else | ||
97 | #error "Bitfield endianness not defined! Check your byteorder.h" | ||
98 | #endif | ||
99 | } __attribute__ ((packed)); | ||
100 | |||
101 | struct msg_address { | ||
102 | union { | ||
103 | struct { | ||
104 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
105 | __u32 reserved_1 : 2; | ||
106 | __u32 dest_mode : 1; /*0:physic | 1:logic */ | ||
107 | __u32 redirection_hint: 1; /*0: dedicated CPU | ||
108 | 1: lowest priority */ | ||
109 | __u32 reserved_2 : 4; | ||
110 | __u32 dest_id : 24; /* Destination ID */ | ||
111 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
112 | __u32 dest_id : 24; /* Destination ID */ | ||
113 | __u32 reserved_2 : 4; | ||
114 | __u32 redirection_hint: 1; /*0: dedicated CPU | ||
115 | 1: lowest priority */ | ||
116 | __u32 dest_mode : 1; /*0:physic | 1:logic */ | ||
117 | __u32 reserved_1 : 2; | ||
118 | #else | ||
119 | #error "Bitfield endianness not defined! Check your byteorder.h" | ||
120 | #endif | ||
121 | }u; | ||
122 | __u32 value; | ||
123 | }lo_address; | ||
124 | __u32 hi_address; | ||
125 | } __attribute__ ((packed)); | ||
126 | |||
127 | struct msi_desc { | 128 | struct msi_desc { |
128 | struct { | 129 | struct { |
129 | __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ | 130 | __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */ |
@@ -132,7 +133,7 @@ struct msi_desc { | |||
132 | __u8 reserved: 1; /* reserved */ | 133 | __u8 reserved: 1; /* reserved */ |
133 | __u8 entry_nr; /* specific enabled entry */ | 134 | __u8 entry_nr; /* specific enabled entry */ |
134 | __u8 default_vector; /* default pre-assigned vector */ | 135 | __u8 default_vector; /* default pre-assigned vector */ |
135 | __u8 current_cpu; /* current destination cpu */ | 136 | __u8 unused; /* formerly unused destination cpu*/ |
136 | }msi_attrib; | 137 | }msi_attrib; |
137 | 138 | ||
138 | struct { | 139 | struct { |
@@ -142,6 +143,14 @@ struct msi_desc { | |||
142 | 143 | ||
143 | void __iomem *mask_base; | 144 | void __iomem *mask_base; |
144 | struct pci_dev *dev; | 145 | struct pci_dev *dev; |
146 | |||
147 | #ifdef CONFIG_PM | ||
148 | /* PM save area for MSIX address/data */ | ||
149 | |||
150 | u32 address_hi_save; | ||
151 | u32 address_lo_save; | ||
152 | u32 data_save; | ||
153 | #endif | ||
145 | }; | 154 | }; |
146 | 155 | ||
147 | #endif /* MSI_H */ | 156 | #endif /* MSI_H */ |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index c2ecae5ff0c1..bb7456c1dbac 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -267,7 +267,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
267 | 267 | ||
268 | 268 | ||
269 | /* ACPI bus type */ | 269 | /* ACPI bus type */ |
270 | static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) | 270 | static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) |
271 | { | 271 | { |
272 | struct pci_dev * pci_dev; | 272 | struct pci_dev * pci_dev; |
273 | acpi_integer addr; | 273 | acpi_integer addr; |
@@ -281,7 +281,7 @@ static int pci_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | ||
284 | static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle) | 284 | static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) |
285 | { | 285 | { |
286 | int num; | 286 | int num; |
287 | unsigned int seg, bus; | 287 | unsigned int seg, bus; |
@@ -299,21 +299,21 @@ static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle) | |||
299 | return 0; | 299 | return 0; |
300 | } | 300 | } |
301 | 301 | ||
302 | static struct acpi_bus_type pci_acpi_bus = { | 302 | static struct acpi_bus_type acpi_pci_bus = { |
303 | .bus = &pci_bus_type, | 303 | .bus = &pci_bus_type, |
304 | .find_device = pci_acpi_find_device, | 304 | .find_device = acpi_pci_find_device, |
305 | .find_bridge = pci_acpi_find_root_bridge, | 305 | .find_bridge = acpi_pci_find_root_bridge, |
306 | }; | 306 | }; |
307 | 307 | ||
308 | static int __init pci_acpi_init(void) | 308 | static int __init acpi_pci_init(void) |
309 | { | 309 | { |
310 | int ret; | 310 | int ret; |
311 | 311 | ||
312 | ret = register_acpi_bus_type(&pci_acpi_bus); | 312 | ret = register_acpi_bus_type(&acpi_pci_bus); |
313 | if (ret) | 313 | if (ret) |
314 | return 0; | 314 | return 0; |
315 | platform_pci_choose_state = acpi_pci_choose_state; | 315 | platform_pci_choose_state = acpi_pci_choose_state; |
316 | platform_pci_set_power_state = acpi_pci_set_power_state; | 316 | platform_pci_set_power_state = acpi_pci_set_power_state; |
317 | return 0; | 317 | return 0; |
318 | } | 318 | } |
319 | arch_initcall(pci_acpi_init); | 319 | arch_initcall(acpi_pci_init); |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 56ac2bc003c7..bc405c035ce3 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -43,6 +43,29 @@ pci_config_attr(subsystem_vendor, "0x%04x\n"); | |||
43 | pci_config_attr(subsystem_device, "0x%04x\n"); | 43 | pci_config_attr(subsystem_device, "0x%04x\n"); |
44 | pci_config_attr(class, "0x%06x\n"); | 44 | pci_config_attr(class, "0x%06x\n"); |
45 | pci_config_attr(irq, "%u\n"); | 45 | pci_config_attr(irq, "%u\n"); |
46 | pci_config_attr(is_enabled, "%u\n"); | ||
47 | |||
48 | static ssize_t broken_parity_status_show(struct device *dev, | ||
49 | struct device_attribute *attr, | ||
50 | char *buf) | ||
51 | { | ||
52 | struct pci_dev *pdev = to_pci_dev(dev); | ||
53 | return sprintf (buf, "%u\n", pdev->broken_parity_status); | ||
54 | } | ||
55 | |||
56 | static ssize_t broken_parity_status_store(struct device *dev, | ||
57 | struct device_attribute *attr, | ||
58 | const char *buf, size_t count) | ||
59 | { | ||
60 | struct pci_dev *pdev = to_pci_dev(dev); | ||
61 | ssize_t consumed = -EINVAL; | ||
62 | |||
63 | if ((count > 0) && (*buf == '0' || *buf == '1')) { | ||
64 | pdev->broken_parity_status = *buf == '1' ? 1 : 0; | ||
65 | consumed = count; | ||
66 | } | ||
67 | return consumed; | ||
68 | } | ||
46 | 69 | ||
47 | static ssize_t local_cpus_show(struct device *dev, | 70 | static ssize_t local_cpus_show(struct device *dev, |
48 | struct device_attribute *attr, char *buf) | 71 | struct device_attribute *attr, char *buf) |
@@ -90,6 +113,25 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | |||
90 | (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), | 113 | (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), |
91 | (u8)(pci_dev->class)); | 114 | (u8)(pci_dev->class)); |
92 | } | 115 | } |
116 | static ssize_t | ||
117 | is_enabled_store(struct device *dev, struct device_attribute *attr, | ||
118 | const char *buf, size_t count) | ||
119 | { | ||
120 | struct pci_dev *pdev = to_pci_dev(dev); | ||
121 | |||
122 | /* this can crash the machine when done on the "wrong" device */ | ||
123 | if (!capable(CAP_SYS_ADMIN)) | ||
124 | return count; | ||
125 | |||
126 | if (*buf == '0') | ||
127 | pci_disable_device(pdev); | ||
128 | |||
129 | if (*buf == '1') | ||
130 | pci_enable_device(pdev); | ||
131 | |||
132 | return count; | ||
133 | } | ||
134 | |||
93 | 135 | ||
94 | struct device_attribute pci_dev_attrs[] = { | 136 | struct device_attribute pci_dev_attrs[] = { |
95 | __ATTR_RO(resource), | 137 | __ATTR_RO(resource), |
@@ -101,6 +143,9 @@ struct device_attribute pci_dev_attrs[] = { | |||
101 | __ATTR_RO(irq), | 143 | __ATTR_RO(irq), |
102 | __ATTR_RO(local_cpus), | 144 | __ATTR_RO(local_cpus), |
103 | __ATTR_RO(modalias), | 145 | __ATTR_RO(modalias), |
146 | __ATTR(enable, 0600, is_enabled_show, is_enabled_store), | ||
147 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), | ||
148 | broken_parity_status_show,broken_parity_status_store), | ||
104 | __ATTR_NULL, | 149 | __ATTR_NULL, |
105 | }; | 150 | }; |
106 | 151 | ||
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index fde41cc14734..d408a3c30426 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -517,7 +517,12 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) | |||
517 | int | 517 | int |
518 | pci_enable_device(struct pci_dev *dev) | 518 | pci_enable_device(struct pci_dev *dev) |
519 | { | 519 | { |
520 | int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); | 520 | int err; |
521 | |||
522 | if (dev->is_enabled) | ||
523 | return 0; | ||
524 | |||
525 | err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); | ||
521 | if (err) | 526 | if (err) |
522 | return err; | 527 | return err; |
523 | pci_fixup_device(pci_fixup_enable, dev); | 528 | pci_fixup_device(pci_fixup_enable, dev); |
@@ -546,7 +551,14 @@ void | |||
546 | pci_disable_device(struct pci_dev *dev) | 551 | pci_disable_device(struct pci_dev *dev) |
547 | { | 552 | { |
548 | u16 pci_command; | 553 | u16 pci_command; |
549 | 554 | ||
555 | if (dev->msi_enabled) | ||
556 | disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), | ||
557 | PCI_CAP_ID_MSI); | ||
558 | if (dev->msix_enabled) | ||
559 | disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), | ||
560 | PCI_CAP_ID_MSIX); | ||
561 | |||
550 | pci_read_config_word(dev, PCI_COMMAND, &pci_command); | 562 | pci_read_config_word(dev, PCI_COMMAND, &pci_command); |
551 | if (pci_command & PCI_COMMAND_MASTER) { | 563 | if (pci_command & PCI_COMMAND_MASTER) { |
552 | pci_command &= ~PCI_COMMAND_MASTER; | 564 | pci_command &= ~PCI_COMMAND_MASTER; |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 30630cbe2fe3..29bdeca031a8 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -40,7 +40,7 @@ extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int | |||
40 | extern void pci_remove_legacy_files(struct pci_bus *bus); | 40 | extern void pci_remove_legacy_files(struct pci_bus *bus); |
41 | 41 | ||
42 | /* Lock for read/write access to pci device and bus lists */ | 42 | /* Lock for read/write access to pci device and bus lists */ |
43 | extern spinlock_t pci_bus_lock; | 43 | extern struct rw_semaphore pci_bus_sem; |
44 | 44 | ||
45 | #ifdef CONFIG_X86_IO_APIC | 45 | #ifdef CONFIG_X86_IO_APIC |
46 | extern int pci_msi_quirk; | 46 | extern int pci_msi_quirk; |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a10ed9dab2c2..f89dbc3738b7 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -180,25 +180,31 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) | |||
180 | res->flags |= pci_calc_resource_flags(l); | 180 | res->flags |= pci_calc_resource_flags(l); |
181 | if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) | 181 | if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) |
182 | == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { | 182 | == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) { |
183 | pci_read_config_dword(dev, reg+4, &l); | 183 | u32 szhi, lhi; |
184 | pci_read_config_dword(dev, reg+4, &lhi); | ||
185 | pci_write_config_dword(dev, reg+4, ~0); | ||
186 | pci_read_config_dword(dev, reg+4, &szhi); | ||
187 | pci_write_config_dword(dev, reg+4, lhi); | ||
188 | szhi = pci_size(lhi, szhi, 0xffffffff); | ||
184 | next++; | 189 | next++; |
185 | #if BITS_PER_LONG == 64 | 190 | #if BITS_PER_LONG == 64 |
186 | res->start |= ((unsigned long) l) << 32; | 191 | res->start |= ((unsigned long) lhi) << 32; |
187 | res->end = res->start + sz; | 192 | res->end = res->start + sz; |
188 | pci_write_config_dword(dev, reg+4, ~0); | 193 | if (szhi) { |
189 | pci_read_config_dword(dev, reg+4, &sz); | ||
190 | pci_write_config_dword(dev, reg+4, l); | ||
191 | sz = pci_size(l, sz, 0xffffffff); | ||
192 | if (sz) { | ||
193 | /* This BAR needs > 4GB? Wow. */ | 194 | /* This BAR needs > 4GB? Wow. */ |
194 | res->end |= (unsigned long)sz<<32; | 195 | res->end |= (unsigned long)szhi<<32; |
195 | } | 196 | } |
196 | #else | 197 | #else |
197 | if (l) { | 198 | if (szhi) { |
198 | printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev)); | 199 | printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev)); |
199 | res->start = 0; | 200 | res->start = 0; |
200 | res->flags = 0; | 201 | res->flags = 0; |
201 | continue; | 202 | } else if (lhi) { |
203 | /* 64-bit wide address, treat as disabled */ | ||
204 | pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK); | ||
205 | pci_write_config_dword(dev, reg+4, 0); | ||
206 | res->start = 0; | ||
207 | res->end = sz; | ||
202 | } | 208 | } |
203 | #endif | 209 | #endif |
204 | } | 210 | } |
@@ -377,9 +383,9 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de | |||
377 | 383 | ||
378 | child = pci_alloc_child_bus(parent, dev, busnr); | 384 | child = pci_alloc_child_bus(parent, dev, busnr); |
379 | if (child) { | 385 | if (child) { |
380 | spin_lock(&pci_bus_lock); | 386 | down_write(&pci_bus_sem); |
381 | list_add_tail(&child->node, &parent->children); | 387 | list_add_tail(&child->node, &parent->children); |
382 | spin_unlock(&pci_bus_lock); | 388 | up_write(&pci_bus_sem); |
383 | } | 389 | } |
384 | return child; | 390 | return child; |
385 | } | 391 | } |
@@ -838,9 +844,9 @@ void __devinit pci_device_add(struct pci_dev *dev, struct pci_bus *bus) | |||
838 | * and the bus list for fixup functions, etc. | 844 | * and the bus list for fixup functions, etc. |
839 | */ | 845 | */ |
840 | INIT_LIST_HEAD(&dev->global_list); | 846 | INIT_LIST_HEAD(&dev->global_list); |
841 | spin_lock(&pci_bus_lock); | 847 | down_write(&pci_bus_sem); |
842 | list_add_tail(&dev->bus_list, &bus->devices); | 848 | list_add_tail(&dev->bus_list, &bus->devices); |
843 | spin_unlock(&pci_bus_lock); | 849 | up_write(&pci_bus_sem); |
844 | } | 850 | } |
845 | 851 | ||
846 | struct pci_dev * __devinit | 852 | struct pci_dev * __devinit |
@@ -975,9 +981,10 @@ struct pci_bus * __devinit pci_create_bus(struct device *parent, | |||
975 | pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); | 981 | pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus); |
976 | goto err_out; | 982 | goto err_out; |
977 | } | 983 | } |
978 | spin_lock(&pci_bus_lock); | 984 | |
985 | down_write(&pci_bus_sem); | ||
979 | list_add_tail(&b->node, &pci_root_buses); | 986 | list_add_tail(&b->node, &pci_root_buses); |
980 | spin_unlock(&pci_bus_lock); | 987 | up_write(&pci_bus_sem); |
981 | 988 | ||
982 | memset(dev, 0, sizeof(*dev)); | 989 | memset(dev, 0, sizeof(*dev)); |
983 | dev->parent = parent; | 990 | dev->parent = parent; |
@@ -1017,9 +1024,9 @@ class_dev_create_file_err: | |||
1017 | class_dev_reg_err: | 1024 | class_dev_reg_err: |
1018 | device_unregister(dev); | 1025 | device_unregister(dev); |
1019 | dev_reg_err: | 1026 | dev_reg_err: |
1020 | spin_lock(&pci_bus_lock); | 1027 | down_write(&pci_bus_sem); |
1021 | list_del(&b->node); | 1028 | list_del(&b->node); |
1022 | spin_unlock(&pci_bus_lock); | 1029 | up_write(&pci_bus_sem); |
1023 | err_out: | 1030 | err_out: |
1024 | kfree(dev); | 1031 | kfree(dev); |
1025 | kfree(b); | 1032 | kfree(b); |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index d378478612fb..4364d793f73b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -24,6 +24,17 @@ | |||
24 | #include <linux/acpi.h> | 24 | #include <linux/acpi.h> |
25 | #include "pci.h" | 25 | #include "pci.h" |
26 | 26 | ||
27 | /* The Mellanox Tavor device gives false positive parity errors | ||
28 | * Mark this device with a broken_parity_status, to allow | ||
29 | * PCI scanning code to "skip" this now blacklisted device. | ||
30 | */ | ||
31 | static void __devinit quirk_mellanox_tavor(struct pci_dev *dev) | ||
32 | { | ||
33 | dev->broken_parity_status = 1; /* This device gives false positives */ | ||
34 | } | ||
35 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor); | ||
36 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor); | ||
37 | |||
27 | /* Deal with broken BIOS'es that neglect to enable passive release, | 38 | /* Deal with broken BIOS'es that neglect to enable passive release, |
28 | which can cause problems in combination with the 82441FX/PPro MTRRs */ | 39 | which can cause problems in combination with the 82441FX/PPro MTRRs */ |
29 | static void __devinit quirk_passive_release(struct pci_dev *dev) | 40 | static void __devinit quirk_passive_release(struct pci_dev *dev) |
@@ -878,27 +889,30 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e | |||
878 | * when a PCI-Soundcard is added. The BIOS only gives Options | 889 | * when a PCI-Soundcard is added. The BIOS only gives Options |
879 | * "Disabled" and "AUTO". This Quirk Sets the corresponding | 890 | * "Disabled" and "AUTO". This Quirk Sets the corresponding |
880 | * Register-Value to enable the Soundcard. | 891 | * Register-Value to enable the Soundcard. |
892 | * | ||
893 | * FIXME: Presently this quirk will run on anything that has an 8237 | ||
894 | * which isn't correct, we need to check DMI tables or something in | ||
895 | * order to make sure it only runs on the MSI-K8T-Neo2Fir. Because it | ||
896 | * runs everywhere at present we suppress the printk output in most | ||
897 | * irrelevant cases. | ||
881 | */ | 898 | */ |
882 | static void __init k8t_sound_hostbridge(struct pci_dev *dev) | 899 | static void __init k8t_sound_hostbridge(struct pci_dev *dev) |
883 | { | 900 | { |
884 | unsigned char val; | 901 | unsigned char val; |
885 | 902 | ||
886 | printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n"); | ||
887 | pci_read_config_byte(dev, 0x50, &val); | 903 | pci_read_config_byte(dev, 0x50, &val); |
888 | if (val == 0x88 || val == 0xc8) { | 904 | if (val == 0x88 || val == 0xc8) { |
905 | /* Assume it's probably a MSI-K8T-Neo2Fir */ | ||
906 | printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, attempting to turn soundcard ON\n"); | ||
889 | pci_write_config_byte(dev, 0x50, val & (~0x40)); | 907 | pci_write_config_byte(dev, 0x50, val & (~0x40)); |
890 | 908 | ||
891 | /* Verify the Change for Status output */ | 909 | /* Verify the Change for Status output */ |
892 | pci_read_config_byte(dev, 0x50, &val); | 910 | pci_read_config_byte(dev, 0x50, &val); |
893 | if (val & 0x40) | 911 | if (val & 0x40) |
894 | printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n"); | 912 | printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard still off\n"); |
895 | else | 913 | else |
896 | printk(KERN_INFO "PCI: MSI-K8T soundcard on\n"); | 914 | printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard on\n"); |
897 | } else { | ||
898 | printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: " | ||
899 | "no Change!\n"); | ||
900 | } | 915 | } |
901 | |||
902 | } | 916 | } |
903 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge); | 917 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge); |
904 | 918 | ||
@@ -1485,6 +1499,25 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) | |||
1485 | } | 1499 | } |
1486 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); | 1500 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io); |
1487 | 1501 | ||
1502 | /* Under some circumstances, AER is not linked with extended capabilities. | ||
1503 | * Force it to be linked by setting the corresponding control bit in the | ||
1504 | * config space. | ||
1505 | */ | ||
1506 | static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev) | ||
1507 | { | ||
1508 | uint8_t b; | ||
1509 | if (pci_read_config_byte(dev, 0xf41, &b) == 0) { | ||
1510 | if (!(b & 0x20)) { | ||
1511 | pci_write_config_byte(dev, 0xf41, b | 0x20); | ||
1512 | printk(KERN_INFO | ||
1513 | "PCI: Linking AER extended capability on %s\n", | ||
1514 | pci_name(dev)); | ||
1515 | } | ||
1516 | } | ||
1517 | } | ||
1518 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, | ||
1519 | quirk_nvidia_ck804_pcie_aer_ext_cap); | ||
1520 | |||
1488 | EXPORT_SYMBOL(pcie_mch_quirk); | 1521 | EXPORT_SYMBOL(pcie_mch_quirk); |
1489 | #ifdef CONFIG_HOTPLUG | 1522 | #ifdef CONFIG_HOTPLUG |
1490 | EXPORT_SYMBOL(pci_fixup_device); | 1523 | EXPORT_SYMBOL(pci_fixup_device); |
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 1a6bf9de166f..99ffbd478b29 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
@@ -22,18 +22,18 @@ static void pci_destroy_dev(struct pci_dev *dev) | |||
22 | pci_proc_detach_device(dev); | 22 | pci_proc_detach_device(dev); |
23 | pci_remove_sysfs_dev_files(dev); | 23 | pci_remove_sysfs_dev_files(dev); |
24 | device_unregister(&dev->dev); | 24 | device_unregister(&dev->dev); |
25 | spin_lock(&pci_bus_lock); | 25 | down_write(&pci_bus_sem); |
26 | list_del(&dev->global_list); | 26 | list_del(&dev->global_list); |
27 | dev->global_list.next = dev->global_list.prev = NULL; | 27 | dev->global_list.next = dev->global_list.prev = NULL; |
28 | spin_unlock(&pci_bus_lock); | 28 | up_write(&pci_bus_sem); |
29 | } | 29 | } |
30 | 30 | ||
31 | /* Remove the device from the device lists, and prevent any further | 31 | /* Remove the device from the device lists, and prevent any further |
32 | * list accesses from this device */ | 32 | * list accesses from this device */ |
33 | spin_lock(&pci_bus_lock); | 33 | down_write(&pci_bus_sem); |
34 | list_del(&dev->bus_list); | 34 | list_del(&dev->bus_list); |
35 | dev->bus_list.next = dev->bus_list.prev = NULL; | 35 | dev->bus_list.next = dev->bus_list.prev = NULL; |
36 | spin_unlock(&pci_bus_lock); | 36 | up_write(&pci_bus_sem); |
37 | 37 | ||
38 | pci_free_resources(dev); | 38 | pci_free_resources(dev); |
39 | pci_dev_put(dev); | 39 | pci_dev_put(dev); |
@@ -62,9 +62,9 @@ void pci_remove_bus(struct pci_bus *pci_bus) | |||
62 | { | 62 | { |
63 | pci_proc_detach_bus(pci_bus); | 63 | pci_proc_detach_bus(pci_bus); |
64 | 64 | ||
65 | spin_lock(&pci_bus_lock); | 65 | down_write(&pci_bus_sem); |
66 | list_del(&pci_bus->node); | 66 | list_del(&pci_bus->node); |
67 | spin_unlock(&pci_bus_lock); | 67 | up_write(&pci_bus_sem); |
68 | pci_remove_legacy_files(pci_bus); | 68 | pci_remove_legacy_files(pci_bus); |
69 | class_device_remove_file(&pci_bus->class_dev, | 69 | class_device_remove_file(&pci_bus->class_dev, |
70 | &class_device_attr_cpuaffinity); | 70 | &class_device_attr_cpuaffinity); |
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index ce7dd6e7be60..622b3f8ba820 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include "pci.h" | 14 | #include "pci.h" |
15 | 15 | ||
16 | DEFINE_SPINLOCK(pci_bus_lock); | 16 | DECLARE_RWSEM(pci_bus_sem); |
17 | 17 | ||
18 | static struct pci_bus * __devinit | 18 | static struct pci_bus * __devinit |
19 | pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) | 19 | pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) |
@@ -72,11 +72,11 @@ pci_find_next_bus(const struct pci_bus *from) | |||
72 | struct pci_bus *b = NULL; | 72 | struct pci_bus *b = NULL; |
73 | 73 | ||
74 | WARN_ON(in_interrupt()); | 74 | WARN_ON(in_interrupt()); |
75 | spin_lock(&pci_bus_lock); | 75 | down_read(&pci_bus_sem); |
76 | n = from ? from->node.next : pci_root_buses.next; | 76 | n = from ? from->node.next : pci_root_buses.next; |
77 | if (n != &pci_root_buses) | 77 | if (n != &pci_root_buses) |
78 | b = pci_bus_b(n); | 78 | b = pci_bus_b(n); |
79 | spin_unlock(&pci_bus_lock); | 79 | up_read(&pci_bus_sem); |
80 | return b; | 80 | return b; |
81 | } | 81 | } |
82 | 82 | ||
@@ -124,7 +124,7 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) | |||
124 | struct pci_dev *dev; | 124 | struct pci_dev *dev; |
125 | 125 | ||
126 | WARN_ON(in_interrupt()); | 126 | WARN_ON(in_interrupt()); |
127 | spin_lock(&pci_bus_lock); | 127 | down_read(&pci_bus_sem); |
128 | 128 | ||
129 | list_for_each(tmp, &bus->devices) { | 129 | list_for_each(tmp, &bus->devices) { |
130 | dev = pci_dev_b(tmp); | 130 | dev = pci_dev_b(tmp); |
@@ -135,7 +135,7 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) | |||
135 | dev = NULL; | 135 | dev = NULL; |
136 | out: | 136 | out: |
137 | pci_dev_get(dev); | 137 | pci_dev_get(dev); |
138 | spin_unlock(&pci_bus_lock); | 138 | up_read(&pci_bus_sem); |
139 | return dev; | 139 | return dev; |
140 | } | 140 | } |
141 | 141 | ||
@@ -167,7 +167,7 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor, | |||
167 | struct pci_dev *dev; | 167 | struct pci_dev *dev; |
168 | 168 | ||
169 | WARN_ON(in_interrupt()); | 169 | WARN_ON(in_interrupt()); |
170 | spin_lock(&pci_bus_lock); | 170 | down_read(&pci_bus_sem); |
171 | n = from ? from->global_list.next : pci_devices.next; | 171 | n = from ? from->global_list.next : pci_devices.next; |
172 | 172 | ||
173 | while (n && (n != &pci_devices)) { | 173 | while (n && (n != &pci_devices)) { |
@@ -181,7 +181,7 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor, | |||
181 | } | 181 | } |
182 | dev = NULL; | 182 | dev = NULL; |
183 | exit: | 183 | exit: |
184 | spin_unlock(&pci_bus_lock); | 184 | up_read(&pci_bus_sem); |
185 | return dev; | 185 | return dev; |
186 | } | 186 | } |
187 | 187 | ||
@@ -232,7 +232,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device, | |||
232 | struct pci_dev *dev; | 232 | struct pci_dev *dev; |
233 | 233 | ||
234 | WARN_ON(in_interrupt()); | 234 | WARN_ON(in_interrupt()); |
235 | spin_lock(&pci_bus_lock); | 235 | down_read(&pci_bus_sem); |
236 | n = from ? from->global_list.next : pci_devices.next; | 236 | n = from ? from->global_list.next : pci_devices.next; |
237 | 237 | ||
238 | while (n && (n != &pci_devices)) { | 238 | while (n && (n != &pci_devices)) { |
@@ -247,7 +247,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device, | |||
247 | dev = NULL; | 247 | dev = NULL; |
248 | exit: | 248 | exit: |
249 | dev = pci_dev_get(dev); | 249 | dev = pci_dev_get(dev); |
250 | spin_unlock(&pci_bus_lock); | 250 | up_read(&pci_bus_sem); |
251 | pci_dev_put(from); | 251 | pci_dev_put(from); |
252 | return dev; | 252 | return dev; |
253 | } | 253 | } |
@@ -292,7 +292,7 @@ pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct p | |||
292 | struct pci_dev *dev; | 292 | struct pci_dev *dev; |
293 | 293 | ||
294 | WARN_ON(in_interrupt()); | 294 | WARN_ON(in_interrupt()); |
295 | spin_lock(&pci_bus_lock); | 295 | down_read(&pci_bus_sem); |
296 | n = from ? from->global_list.prev : pci_devices.prev; | 296 | n = from ? from->global_list.prev : pci_devices.prev; |
297 | 297 | ||
298 | while (n && (n != &pci_devices)) { | 298 | while (n && (n != &pci_devices)) { |
@@ -304,7 +304,7 @@ pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct p | |||
304 | } | 304 | } |
305 | dev = NULL; | 305 | dev = NULL; |
306 | exit: | 306 | exit: |
307 | spin_unlock(&pci_bus_lock); | 307 | up_read(&pci_bus_sem); |
308 | return dev; | 308 | return dev; |
309 | } | 309 | } |
310 | 310 | ||
@@ -328,7 +328,7 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) | |||
328 | struct pci_dev *dev; | 328 | struct pci_dev *dev; |
329 | 329 | ||
330 | WARN_ON(in_interrupt()); | 330 | WARN_ON(in_interrupt()); |
331 | spin_lock(&pci_bus_lock); | 331 | down_read(&pci_bus_sem); |
332 | n = from ? from->global_list.next : pci_devices.next; | 332 | n = from ? from->global_list.next : pci_devices.next; |
333 | 333 | ||
334 | while (n && (n != &pci_devices)) { | 334 | while (n && (n != &pci_devices)) { |
@@ -340,7 +340,7 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from) | |||
340 | dev = NULL; | 340 | dev = NULL; |
341 | exit: | 341 | exit: |
342 | dev = pci_dev_get(dev); | 342 | dev = pci_dev_get(dev); |
343 | spin_unlock(&pci_bus_lock); | 343 | up_read(&pci_bus_sem); |
344 | pci_dev_put(from); | 344 | pci_dev_put(from); |
345 | return dev; | 345 | return dev; |
346 | } | 346 | } |
@@ -362,7 +362,7 @@ int pci_dev_present(const struct pci_device_id *ids) | |||
362 | int found = 0; | 362 | int found = 0; |
363 | 363 | ||
364 | WARN_ON(in_interrupt()); | 364 | WARN_ON(in_interrupt()); |
365 | spin_lock(&pci_bus_lock); | 365 | down_read(&pci_bus_sem); |
366 | while (ids->vendor || ids->subvendor || ids->class_mask) { | 366 | while (ids->vendor || ids->subvendor || ids->class_mask) { |
367 | list_for_each_entry(dev, &pci_devices, global_list) { | 367 | list_for_each_entry(dev, &pci_devices, global_list) { |
368 | if (pci_match_one_device(ids, dev)) { | 368 | if (pci_match_one_device(ids, dev)) { |
@@ -372,8 +372,8 @@ int pci_dev_present(const struct pci_device_id *ids) | |||
372 | } | 372 | } |
373 | ids++; | 373 | ids++; |
374 | } | 374 | } |
375 | exit: | 375 | exit: |
376 | spin_unlock(&pci_bus_lock); | 376 | up_read(&pci_bus_sem); |
377 | return found; | 377 | return found; |
378 | } | 378 | } |
379 | EXPORT_SYMBOL(pci_dev_present); | 379 | EXPORT_SYMBOL(pci_dev_present); |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 28ce3a7ee434..35086e80faa9 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -55,9 +55,10 @@ pbus_assign_resources_sorted(struct pci_bus *bus) | |||
55 | list_for_each_entry(dev, &bus->devices, bus_list) { | 55 | list_for_each_entry(dev, &bus->devices, bus_list) { |
56 | u16 class = dev->class >> 8; | 56 | u16 class = dev->class >> 8; |
57 | 57 | ||
58 | /* Don't touch classless devices and host bridges. */ | 58 | /* Don't touch classless devices or host bridges or ioapics. */ |
59 | if (class == PCI_CLASS_NOT_DEFINED || | 59 | if (class == PCI_CLASS_NOT_DEFINED || |
60 | class == PCI_CLASS_BRIDGE_HOST) | 60 | class == PCI_CLASS_BRIDGE_HOST || |
61 | class == PCI_CLASS_SYSTEM_PIC) | ||
61 | continue; | 62 | continue; |
62 | 63 | ||
63 | pdev_sort_resources(dev, &head); | 64 | pdev_sort_resources(dev, &head); |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index ea9277b7f899..577f4b55c46d 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
@@ -155,6 +155,46 @@ int pci_assign_resource(struct pci_dev *dev, int resno) | |||
155 | return ret; | 155 | return ret; |
156 | } | 156 | } |
157 | 157 | ||
158 | #ifdef CONFIG_EMBEDDED | ||
159 | int pci_assign_resource_fixed(struct pci_dev *dev, int resno) | ||
160 | { | ||
161 | struct pci_bus *bus = dev->bus; | ||
162 | struct resource *res = dev->resource + resno; | ||
163 | unsigned int type_mask; | ||
164 | int i, ret = -EBUSY; | ||
165 | |||
166 | type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; | ||
167 | |||
168 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { | ||
169 | struct resource *r = bus->resource[i]; | ||
170 | if (!r) | ||
171 | continue; | ||
172 | |||
173 | /* type_mask must match */ | ||
174 | if ((res->flags ^ r->flags) & type_mask) | ||
175 | continue; | ||
176 | |||
177 | ret = request_resource(r, res); | ||
178 | |||
179 | if (ret == 0) | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | if (ret) { | ||
184 | printk(KERN_ERR "PCI: Failed to allocate %s resource " | ||
185 | "#%d:%llx@%llx for %s\n", | ||
186 | res->flags & IORESOURCE_IO ? "I/O" : "mem", | ||
187 | resno, (unsigned long long)(res->end - res->start + 1), | ||
188 | (unsigned long long)res->start, pci_name(dev)); | ||
189 | } else if (resno < PCI_BRIDGE_RESOURCES) { | ||
190 | pci_update_resource(dev, res, resno); | ||
191 | } | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | EXPORT_SYMBOL_GPL(pci_assign_resource_fixed); | ||
196 | #endif | ||
197 | |||
158 | /* Sort resources by alignment */ | 198 | /* Sort resources by alignment */ |
159 | void __devinit | 199 | void __devinit |
160 | pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) | 200 | pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) |
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 77bb2351500c..680f6063954b 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c | |||
@@ -397,30 +397,6 @@ | |||
397 | #include "ql1280_fw.h" | 397 | #include "ql1280_fw.h" |
398 | #include "ql1040_fw.h" | 398 | #include "ql1040_fw.h" |
399 | 399 | ||
400 | |||
401 | /* | ||
402 | * Missing PCI ID's | ||
403 | */ | ||
404 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP1080 | ||
405 | #define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 | ||
406 | #endif | ||
407 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP1240 | ||
408 | #define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 | ||
409 | #endif | ||
410 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP1280 | ||
411 | #define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 | ||
412 | #endif | ||
413 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP10160 | ||
414 | #define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 | ||
415 | #endif | ||
416 | #ifndef PCI_DEVICE_ID_QLOGIC_ISP12160 | ||
417 | #define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 | ||
418 | #endif | ||
419 | |||
420 | #ifndef PCI_VENDOR_ID_AMI | ||
421 | #define PCI_VENDOR_ID_AMI 0x101e | ||
422 | #endif | ||
423 | |||
424 | #ifndef BITS_PER_LONG | 400 | #ifndef BITS_PER_LONG |
425 | #error "BITS_PER_LONG not defined!" | 401 | #error "BITS_PER_LONG not defined!" |
426 | #endif | 402 | #endif |
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index 8a29ce340b47..27d658704cf9 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c | |||
@@ -433,13 +433,14 @@ err_out: | |||
433 | 433 | ||
434 | 434 | ||
435 | /* | 435 | /* |
436 | * 0x1725/0x7174 is the Vitesse VSC-7174 | 436 | * Intel 31244 is supposed to be identical. |
437 | * 0x8086/0x3200 is the Intel 31244, which is supposed to be identical | 437 | * Compatibility is untested as of yet. |
438 | * compatibility is untested as of yet | ||
439 | */ | 438 | */ |
440 | static const struct pci_device_id vsc_sata_pci_tbl[] = { | 439 | static const struct pci_device_id vsc_sata_pci_tbl[] = { |
441 | { 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, | 440 | { PCI_VENDOR_ID_VITESSE, PCI_DEVICE_ID_VITESSE_VSC7174, |
442 | { 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, | 441 | PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, |
442 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GD31244, | ||
443 | PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, | ||
443 | { } | 444 | { } |
444 | }; | 445 | }; |
445 | 446 | ||
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 989e4d49e5bb..7f939d066a5a 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c | |||
@@ -313,8 +313,8 @@ static const char __init *mdacon_startup(void) | |||
313 | mda_num_columns = 80; | 313 | mda_num_columns = 80; |
314 | mda_num_lines = 25; | 314 | mda_num_lines = 25; |
315 | 315 | ||
316 | mda_vram_base = VGA_MAP_MEM(0xb0000); | ||
317 | mda_vram_len = 0x01000; | 316 | mda_vram_len = 0x01000; |
317 | mda_vram_base = VGA_MAP_MEM(0xb0000, mda_vram_len); | ||
318 | 318 | ||
319 | mda_index_port = 0x3b4; | 319 | mda_index_port = 0x3b4; |
320 | mda_value_port = 0x3b5; | 320 | mda_value_port = 0x3b5; |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d5a04b68c4d4..e64d42e2449e 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -391,7 +391,7 @@ static const char __init *vgacon_startup(void) | |||
391 | static struct resource ega_console_resource = | 391 | static struct resource ega_console_resource = |
392 | { "ega", 0x3B0, 0x3BF }; | 392 | { "ega", 0x3B0, 0x3BF }; |
393 | vga_video_type = VIDEO_TYPE_EGAM; | 393 | vga_video_type = VIDEO_TYPE_EGAM; |
394 | vga_vram_end = 0xb8000; | 394 | vga_vram_size = 0x8000; |
395 | display_desc = "EGA+"; | 395 | display_desc = "EGA+"; |
396 | request_resource(&ioport_resource, | 396 | request_resource(&ioport_resource, |
397 | &ega_console_resource); | 397 | &ega_console_resource); |
@@ -401,7 +401,7 @@ static const char __init *vgacon_startup(void) | |||
401 | static struct resource mda2_console_resource = | 401 | static struct resource mda2_console_resource = |
402 | { "mda", 0x3BF, 0x3BF }; | 402 | { "mda", 0x3BF, 0x3BF }; |
403 | vga_video_type = VIDEO_TYPE_MDA; | 403 | vga_video_type = VIDEO_TYPE_MDA; |
404 | vga_vram_end = 0xb2000; | 404 | vga_vram_size = 0x2000; |
405 | display_desc = "*MDA"; | 405 | display_desc = "*MDA"; |
406 | request_resource(&ioport_resource, | 406 | request_resource(&ioport_resource, |
407 | &mda1_console_resource); | 407 | &mda1_console_resource); |
@@ -418,7 +418,7 @@ static const char __init *vgacon_startup(void) | |||
418 | if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { | 418 | if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) { |
419 | int i; | 419 | int i; |
420 | 420 | ||
421 | vga_vram_end = 0xc0000; | 421 | vga_vram_size = 0x8000; |
422 | 422 | ||
423 | if (!ORIG_VIDEO_ISVGA) { | 423 | if (!ORIG_VIDEO_ISVGA) { |
424 | static struct resource ega_console_resource | 424 | static struct resource ega_console_resource |
@@ -443,7 +443,7 @@ static const char __init *vgacon_startup(void) | |||
443 | * and COE=1 isn't necessarily a good idea) | 443 | * and COE=1 isn't necessarily a good idea) |
444 | */ | 444 | */ |
445 | vga_vram_base = 0xa0000; | 445 | vga_vram_base = 0xa0000; |
446 | vga_vram_end = 0xb0000; | 446 | vga_vram_size = 0x10000; |
447 | outb_p(6, VGA_GFX_I); | 447 | outb_p(6, VGA_GFX_I); |
448 | outb_p(6, VGA_GFX_D); | 448 | outb_p(6, VGA_GFX_D); |
449 | #endif | 449 | #endif |
@@ -475,7 +475,7 @@ static const char __init *vgacon_startup(void) | |||
475 | static struct resource cga_console_resource = | 475 | static struct resource cga_console_resource = |
476 | { "cga", 0x3D4, 0x3D5 }; | 476 | { "cga", 0x3D4, 0x3D5 }; |
477 | vga_video_type = VIDEO_TYPE_CGA; | 477 | vga_video_type = VIDEO_TYPE_CGA; |
478 | vga_vram_end = 0xba000; | 478 | vga_vram_size = 0x2000; |
479 | display_desc = "*CGA"; | 479 | display_desc = "*CGA"; |
480 | request_resource(&ioport_resource, | 480 | request_resource(&ioport_resource, |
481 | &cga_console_resource); | 481 | &cga_console_resource); |
@@ -483,9 +483,8 @@ static const char __init *vgacon_startup(void) | |||
483 | } | 483 | } |
484 | } | 484 | } |
485 | 485 | ||
486 | vga_vram_base = VGA_MAP_MEM(vga_vram_base); | 486 | vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size); |
487 | vga_vram_end = VGA_MAP_MEM(vga_vram_end); | 487 | vga_vram_end = vga_vram_base + vga_vram_size; |
488 | vga_vram_size = vga_vram_end - vga_vram_base; | ||
489 | 488 | ||
490 | /* | 489 | /* |
491 | * Find out if there is a graphics card present. | 490 | * Find out if there is a graphics card present. |
@@ -1020,14 +1019,14 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1020 | char *charmap; | 1019 | char *charmap; |
1021 | 1020 | ||
1022 | if (vga_video_type != VIDEO_TYPE_EGAM) { | 1021 | if (vga_video_type != VIDEO_TYPE_EGAM) { |
1023 | charmap = (char *) VGA_MAP_MEM(colourmap); | 1022 | charmap = (char *) VGA_MAP_MEM(colourmap, 0); |
1024 | beg = 0x0e; | 1023 | beg = 0x0e; |
1025 | #ifdef VGA_CAN_DO_64KB | 1024 | #ifdef VGA_CAN_DO_64KB |
1026 | if (vga_video_type == VIDEO_TYPE_VGAC) | 1025 | if (vga_video_type == VIDEO_TYPE_VGAC) |
1027 | beg = 0x06; | 1026 | beg = 0x06; |
1028 | #endif | 1027 | #endif |
1029 | } else { | 1028 | } else { |
1030 | charmap = (char *) VGA_MAP_MEM(blackwmap); | 1029 | charmap = (char *) VGA_MAP_MEM(blackwmap, 0); |
1031 | beg = 0x0a; | 1030 | beg = 0x0a; |
1032 | } | 1031 | } |
1033 | 1032 | ||
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index f3f16fd9f231..4fd2a272e03d 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c | |||
@@ -1351,7 +1351,7 @@ static int __init vga16fb_probe(struct device *device) | |||
1351 | } | 1351 | } |
1352 | 1352 | ||
1353 | /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ | 1353 | /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ |
1354 | info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS); | 1354 | info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0); |
1355 | 1355 | ||
1356 | if (!info->screen_base) { | 1356 | if (!info->screen_base) { |
1357 | printk(KERN_ERR "vga16fb: unable to map device\n"); | 1357 | printk(KERN_ERR "vga16fb: unable to map device\n"); |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 537893a16014..8a04216e8b4d 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -759,7 +759,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
759 | 759 | ||
760 | /* Discard our unneeded old files struct */ | 760 | /* Discard our unneeded old files struct */ |
761 | if (files) { | 761 | if (files) { |
762 | steal_locks(files); | ||
763 | put_files_struct(files); | 762 | put_files_struct(files); |
764 | files = NULL; | 763 | files = NULL; |
765 | } | 764 | } |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index d73d75591a39..599f36fd0f67 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -203,7 +203,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
203 | goto _error; | 203 | goto _error; |
204 | 204 | ||
205 | if (files) { | 205 | if (files) { |
206 | steal_locks(files); | ||
207 | put_files_struct(files); | 206 | put_files_struct(files); |
208 | files = NULL; | 207 | files = NULL; |
209 | } | 208 | } |
diff --git a/fs/block_dev.c b/fs/block_dev.c index f5958f413bd1..44aaba202f78 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -414,21 +414,31 @@ EXPORT_SYMBOL(bdput); | |||
414 | static struct block_device *bd_acquire(struct inode *inode) | 414 | static struct block_device *bd_acquire(struct inode *inode) |
415 | { | 415 | { |
416 | struct block_device *bdev; | 416 | struct block_device *bdev; |
417 | |||
417 | spin_lock(&bdev_lock); | 418 | spin_lock(&bdev_lock); |
418 | bdev = inode->i_bdev; | 419 | bdev = inode->i_bdev; |
419 | if (bdev && igrab(bdev->bd_inode)) { | 420 | if (bdev) { |
421 | atomic_inc(&bdev->bd_inode->i_count); | ||
420 | spin_unlock(&bdev_lock); | 422 | spin_unlock(&bdev_lock); |
421 | return bdev; | 423 | return bdev; |
422 | } | 424 | } |
423 | spin_unlock(&bdev_lock); | 425 | spin_unlock(&bdev_lock); |
426 | |||
424 | bdev = bdget(inode->i_rdev); | 427 | bdev = bdget(inode->i_rdev); |
425 | if (bdev) { | 428 | if (bdev) { |
426 | spin_lock(&bdev_lock); | 429 | spin_lock(&bdev_lock); |
427 | if (inode->i_bdev) | 430 | if (!inode->i_bdev) { |
428 | __bd_forget(inode); | 431 | /* |
429 | inode->i_bdev = bdev; | 432 | * We take an additional bd_inode->i_count for inode, |
430 | inode->i_mapping = bdev->bd_inode->i_mapping; | 433 | * and it's released in clear_inode() of inode. |
431 | list_add(&inode->i_devices, &bdev->bd_inodes); | 434 | * So, we can access it via ->i_mapping always |
435 | * without igrab(). | ||
436 | */ | ||
437 | atomic_inc(&bdev->bd_inode->i_count); | ||
438 | inode->i_bdev = bdev; | ||
439 | inode->i_mapping = bdev->bd_inode->i_mapping; | ||
440 | list_add(&inode->i_devices, &bdev->bd_inodes); | ||
441 | } | ||
432 | spin_unlock(&bdev_lock); | 442 | spin_unlock(&bdev_lock); |
433 | } | 443 | } |
434 | return bdev; | 444 | return bdev; |
@@ -438,10 +448,18 @@ static struct block_device *bd_acquire(struct inode *inode) | |||
438 | 448 | ||
439 | void bd_forget(struct inode *inode) | 449 | void bd_forget(struct inode *inode) |
440 | { | 450 | { |
451 | struct block_device *bdev = NULL; | ||
452 | |||
441 | spin_lock(&bdev_lock); | 453 | spin_lock(&bdev_lock); |
442 | if (inode->i_bdev) | 454 | if (inode->i_bdev) { |
455 | if (inode->i_sb != blockdev_superblock) | ||
456 | bdev = inode->i_bdev; | ||
443 | __bd_forget(inode); | 457 | __bd_forget(inode); |
458 | } | ||
444 | spin_unlock(&bdev_lock); | 459 | spin_unlock(&bdev_lock); |
460 | |||
461 | if (bdev) | ||
462 | iput(bdev->bd_inode); | ||
445 | } | 463 | } |
446 | 464 | ||
447 | int bd_claim(struct block_device *bdev, void *holder) | 465 | int bd_claim(struct block_device *bdev, void *holder) |
diff --git a/fs/dcache.c b/fs/dcache.c index 940d188e5d14..59dbc92c2079 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -359,12 +359,13 @@ restart: | |||
359 | } | 359 | } |
360 | 360 | ||
361 | /* | 361 | /* |
362 | * Throw away a dentry - free the inode, dput the parent. | 362 | * Throw away a dentry - free the inode, dput the parent. This requires that |
363 | * This requires that the LRU list has already been | 363 | * the LRU list has already been removed. |
364 | * removed. | 364 | * |
365 | * Called with dcache_lock, drops it and then regains. | 365 | * Called with dcache_lock, drops it and then regains. |
366 | * Called with dentry->d_lock held, drops it. | ||
366 | */ | 367 | */ |
367 | static inline void prune_one_dentry(struct dentry * dentry) | 368 | static void prune_one_dentry(struct dentry * dentry) |
368 | { | 369 | { |
369 | struct dentry * parent; | 370 | struct dentry * parent; |
370 | 371 | ||
@@ -382,6 +383,8 @@ static inline void prune_one_dentry(struct dentry * dentry) | |||
382 | /** | 383 | /** |
383 | * prune_dcache - shrink the dcache | 384 | * prune_dcache - shrink the dcache |
384 | * @count: number of entries to try and free | 385 | * @count: number of entries to try and free |
386 | * @sb: if given, ignore dentries for other superblocks | ||
387 | * which are being unmounted. | ||
385 | * | 388 | * |
386 | * Shrink the dcache. This is done when we need | 389 | * Shrink the dcache. This is done when we need |
387 | * more memory, or simply when we need to unmount | 390 | * more memory, or simply when we need to unmount |
@@ -392,16 +395,29 @@ static inline void prune_one_dentry(struct dentry * dentry) | |||
392 | * all the dentries are in use. | 395 | * all the dentries are in use. |
393 | */ | 396 | */ |
394 | 397 | ||
395 | static void prune_dcache(int count) | 398 | static void prune_dcache(int count, struct super_block *sb) |
396 | { | 399 | { |
397 | spin_lock(&dcache_lock); | 400 | spin_lock(&dcache_lock); |
398 | for (; count ; count--) { | 401 | for (; count ; count--) { |
399 | struct dentry *dentry; | 402 | struct dentry *dentry; |
400 | struct list_head *tmp; | 403 | struct list_head *tmp; |
404 | struct rw_semaphore *s_umount; | ||
401 | 405 | ||
402 | cond_resched_lock(&dcache_lock); | 406 | cond_resched_lock(&dcache_lock); |
403 | 407 | ||
404 | tmp = dentry_unused.prev; | 408 | tmp = dentry_unused.prev; |
409 | if (unlikely(sb)) { | ||
410 | /* Try to find a dentry for this sb, but don't try | ||
411 | * too hard, if they aren't near the tail they will | ||
412 | * be moved down again soon | ||
413 | */ | ||
414 | int skip = count; | ||
415 | while (skip && tmp != &dentry_unused && | ||
416 | list_entry(tmp, struct dentry, d_lru)->d_sb != sb) { | ||
417 | skip--; | ||
418 | tmp = tmp->prev; | ||
419 | } | ||
420 | } | ||
405 | if (tmp == &dentry_unused) | 421 | if (tmp == &dentry_unused) |
406 | break; | 422 | break; |
407 | list_del_init(tmp); | 423 | list_del_init(tmp); |
@@ -427,7 +443,45 @@ static void prune_dcache(int count) | |||
427 | spin_unlock(&dentry->d_lock); | 443 | spin_unlock(&dentry->d_lock); |
428 | continue; | 444 | continue; |
429 | } | 445 | } |
430 | prune_one_dentry(dentry); | 446 | /* |
447 | * If the dentry is not DCACHED_REFERENCED, it is time | ||
448 | * to remove it from the dcache, provided the super block is | ||
449 | * NULL (which means we are trying to reclaim memory) | ||
450 | * or this dentry belongs to the same super block that | ||
451 | * we want to shrink. | ||
452 | */ | ||
453 | /* | ||
454 | * If this dentry is for "my" filesystem, then I can prune it | ||
455 | * without taking the s_umount lock (I already hold it). | ||
456 | */ | ||
457 | if (sb && dentry->d_sb == sb) { | ||
458 | prune_one_dentry(dentry); | ||
459 | continue; | ||
460 | } | ||
461 | /* | ||
462 | * ...otherwise we need to be sure this filesystem isn't being | ||
463 | * unmounted, otherwise we could race with | ||
464 | * generic_shutdown_super(), and end up holding a reference to | ||
465 | * an inode while the filesystem is unmounted. | ||
466 | * So we try to get s_umount, and make sure s_root isn't NULL. | ||
467 | * (Take a local copy of s_umount to avoid a use-after-free of | ||
468 | * `dentry'). | ||
469 | */ | ||
470 | s_umount = &dentry->d_sb->s_umount; | ||
471 | if (down_read_trylock(s_umount)) { | ||
472 | if (dentry->d_sb->s_root != NULL) { | ||
473 | prune_one_dentry(dentry); | ||
474 | up_read(s_umount); | ||
475 | continue; | ||
476 | } | ||
477 | up_read(s_umount); | ||
478 | } | ||
479 | spin_unlock(&dentry->d_lock); | ||
480 | /* Cannot remove the first dentry, and it isn't appropriate | ||
481 | * to move it to the head of the list, so give up, and try | ||
482 | * later | ||
483 | */ | ||
484 | break; | ||
431 | } | 485 | } |
432 | spin_unlock(&dcache_lock); | 486 | spin_unlock(&dcache_lock); |
433 | } | 487 | } |
@@ -630,7 +684,7 @@ void shrink_dcache_parent(struct dentry * parent) | |||
630 | int found; | 684 | int found; |
631 | 685 | ||
632 | while ((found = select_parent(parent)) != 0) | 686 | while ((found = select_parent(parent)) != 0) |
633 | prune_dcache(found); | 687 | prune_dcache(found, parent->d_sb); |
634 | } | 688 | } |
635 | 689 | ||
636 | /** | 690 | /** |
@@ -643,9 +697,10 @@ void shrink_dcache_parent(struct dentry * parent) | |||
643 | * done under dcache_lock. | 697 | * done under dcache_lock. |
644 | * | 698 | * |
645 | */ | 699 | */ |
646 | void shrink_dcache_anon(struct hlist_head *head) | 700 | void shrink_dcache_anon(struct super_block *sb) |
647 | { | 701 | { |
648 | struct hlist_node *lp; | 702 | struct hlist_node *lp; |
703 | struct hlist_head *head = &sb->s_anon; | ||
649 | int found; | 704 | int found; |
650 | do { | 705 | do { |
651 | found = 0; | 706 | found = 0; |
@@ -668,7 +723,7 @@ void shrink_dcache_anon(struct hlist_head *head) | |||
668 | } | 723 | } |
669 | } | 724 | } |
670 | spin_unlock(&dcache_lock); | 725 | spin_unlock(&dcache_lock); |
671 | prune_dcache(found); | 726 | prune_dcache(found, sb); |
672 | } while(found); | 727 | } while(found); |
673 | } | 728 | } |
674 | 729 | ||
@@ -689,7 +744,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask) | |||
689 | if (nr) { | 744 | if (nr) { |
690 | if (!(gfp_mask & __GFP_FS)) | 745 | if (!(gfp_mask & __GFP_FS)) |
691 | return -1; | 746 | return -1; |
692 | prune_dcache(nr); | 747 | prune_dcache(nr, NULL); |
693 | } | 748 | } |
694 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; | 749 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; |
695 | } | 750 | } |
@@ -866,7 +866,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
866 | bprm->mm = NULL; /* We're using it now */ | 866 | bprm->mm = NULL; /* We're using it now */ |
867 | 867 | ||
868 | /* This is the point of no return */ | 868 | /* This is the point of no return */ |
869 | steal_locks(files); | ||
870 | put_files_struct(files); | 869 | put_files_struct(files); |
871 | 870 | ||
872 | current->sas_ss_sp = current->sas_ss_size = 0; | 871 | current->sas_ss_sp = current->sas_ss_size = 0; |
diff --git a/fs/locks.c b/fs/locks.c index ab61a8b54829..69435c68c1ed 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -2206,63 +2206,6 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len) | |||
2206 | 2206 | ||
2207 | EXPORT_SYMBOL(lock_may_write); | 2207 | EXPORT_SYMBOL(lock_may_write); |
2208 | 2208 | ||
2209 | static inline void __steal_locks(struct file *file, fl_owner_t from) | ||
2210 | { | ||
2211 | struct inode *inode = file->f_dentry->d_inode; | ||
2212 | struct file_lock *fl = inode->i_flock; | ||
2213 | |||
2214 | while (fl) { | ||
2215 | if (fl->fl_file == file && fl->fl_owner == from) | ||
2216 | fl->fl_owner = current->files; | ||
2217 | fl = fl->fl_next; | ||
2218 | } | ||
2219 | } | ||
2220 | |||
2221 | /* When getting ready for executing a binary, we make sure that current | ||
2222 | * has a files_struct on its own. Before dropping the old files_struct, | ||
2223 | * we take over ownership of all locks for all file descriptors we own. | ||
2224 | * Note that we may accidentally steal a lock for a file that a sibling | ||
2225 | * has created since the unshare_files() call. | ||
2226 | */ | ||
2227 | void steal_locks(fl_owner_t from) | ||
2228 | { | ||
2229 | struct files_struct *files = current->files; | ||
2230 | int i, j; | ||
2231 | struct fdtable *fdt; | ||
2232 | |||
2233 | if (from == files) | ||
2234 | return; | ||
2235 | |||
2236 | lock_kernel(); | ||
2237 | j = 0; | ||
2238 | |||
2239 | /* | ||
2240 | * We are not taking a ref to the file structures, so | ||
2241 | * we need to acquire ->file_lock. | ||
2242 | */ | ||
2243 | spin_lock(&files->file_lock); | ||
2244 | fdt = files_fdtable(files); | ||
2245 | for (;;) { | ||
2246 | unsigned long set; | ||
2247 | i = j * __NFDBITS; | ||
2248 | if (i >= fdt->max_fdset || i >= fdt->max_fds) | ||
2249 | break; | ||
2250 | set = fdt->open_fds->fds_bits[j++]; | ||
2251 | while (set) { | ||
2252 | if (set & 1) { | ||
2253 | struct file *file = fdt->fd[i]; | ||
2254 | if (file) | ||
2255 | __steal_locks(file, from); | ||
2256 | } | ||
2257 | i++; | ||
2258 | set >>= 1; | ||
2259 | } | ||
2260 | } | ||
2261 | spin_unlock(&files->file_lock); | ||
2262 | unlock_kernel(); | ||
2263 | } | ||
2264 | EXPORT_SYMBOL(steal_locks); | ||
2265 | |||
2266 | static int __init filelock_init(void) | 2209 | static int __init filelock_init(void) |
2267 | { | 2210 | { |
2268 | filelock_cache = kmem_cache_create("file_lock_cache", | 2211 | filelock_cache = kmem_cache_create("file_lock_cache", |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index c63a83e8da98..36e1e136bb0c 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -1484,14 +1484,15 @@ static inline void ntfs_flush_dcache_pages(struct page **pages, | |||
1484 | unsigned nr_pages) | 1484 | unsigned nr_pages) |
1485 | { | 1485 | { |
1486 | BUG_ON(!nr_pages); | 1486 | BUG_ON(!nr_pages); |
1487 | /* | ||
1488 | * Warning: Do not do the decrement at the same time as the call to | ||
1489 | * flush_dcache_page() because it is a NULL macro on i386 and hence the | ||
1490 | * decrement never happens so the loop never terminates. | ||
1491 | */ | ||
1487 | do { | 1492 | do { |
1488 | /* | 1493 | --nr_pages; |
1489 | * Warning: Do not do the decrement at the same time as the | ||
1490 | * call because flush_dcache_page() is a NULL macro on i386 | ||
1491 | * and hence the decrement never happens. | ||
1492 | */ | ||
1493 | flush_dcache_page(pages[nr_pages]); | 1494 | flush_dcache_page(pages[nr_pages]); |
1494 | } while (--nr_pages > 0); | 1495 | } while (nr_pages > 0); |
1495 | } | 1496 | } |
1496 | 1497 | ||
1497 | /** | 1498 | /** |
diff --git a/fs/super.c b/fs/super.c index a66f66bb8049..9d5c2add7228 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb) | |||
231 | if (root) { | 231 | if (root) { |
232 | sb->s_root = NULL; | 232 | sb->s_root = NULL; |
233 | shrink_dcache_parent(root); | 233 | shrink_dcache_parent(root); |
234 | shrink_dcache_anon(&sb->s_anon); | 234 | shrink_dcache_anon(sb); |
235 | dput(root); | 235 | dput(root); |
236 | fsync_super(sb); | 236 | fsync_super(sb); |
237 | lock_super(sb); | 237 | lock_super(sb); |
diff --git a/include/asm-alpha/vga.h b/include/asm-alpha/vga.h index 8ca4f6b2da19..ed06f59b544d 100644 --- a/include/asm-alpha/vga.h +++ b/include/asm-alpha/vga.h | |||
@@ -46,6 +46,6 @@ extern void scr_memcpyw(u16 *d, const u16 *s, unsigned int count); | |||
46 | #define vga_readb(a) readb((u8 __iomem *)(a)) | 46 | #define vga_readb(a) readb((u8 __iomem *)(a)) |
47 | #define vga_writeb(v,a) writeb(v, (u8 __iomem *)(a)) | 47 | #define vga_writeb(v,a) writeb(v, (u8 __iomem *)(a)) |
48 | 48 | ||
49 | #define VGA_MAP_MEM(x) ((unsigned long) ioremap(x, 0)) | 49 | #define VGA_MAP_MEM(x,s) ((unsigned long) ioremap(x, s)) |
50 | 50 | ||
51 | #endif | 51 | #endif |
diff --git a/include/asm-arm/vga.h b/include/asm-arm/vga.h index 926e5ee128e9..1e0b913c3d71 100644 --- a/include/asm-arm/vga.h +++ b/include/asm-arm/vga.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <asm/hardware.h> | 4 | #include <asm/hardware.h> |
5 | #include <asm/io.h> | 5 | #include <asm/io.h> |
6 | 6 | ||
7 | #define VGA_MAP_MEM(x) (PCIMEM_BASE + (x)) | 7 | #define VGA_MAP_MEM(x,s) (PCIMEM_BASE + (x)) |
8 | 8 | ||
9 | #define vga_readb(x) (*((volatile unsigned char *)x)) | 9 | #define vga_readb(x) (*((volatile unsigned char *)x)) |
10 | #define vga_writeb(x,y) (*((volatile unsigned char *)y) = (x)) | 10 | #define vga_writeb(x,y) (*((volatile unsigned char *)y) = (x)) |
diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h index f041d4495faf..b11c4b7dfaef 100644 --- a/include/asm-i386/msi.h +++ b/include/asm-i386/msi.h | |||
@@ -9,7 +9,15 @@ | |||
9 | #include <asm/desc.h> | 9 | #include <asm/desc.h> |
10 | #include <mach_apic.h> | 10 | #include <mach_apic.h> |
11 | 11 | ||
12 | #define LAST_DEVICE_VECTOR 232 | 12 | #define LAST_DEVICE_VECTOR (FIRST_SYSTEM_VECTOR - 1) |
13 | #define MSI_TARGET_CPU_SHIFT 12 | 13 | #define MSI_TARGET_CPU_SHIFT 12 |
14 | 14 | ||
15 | extern struct msi_ops msi_apic_ops; | ||
16 | |||
17 | static inline int msi_arch_init(void) | ||
18 | { | ||
19 | msi_register(&msi_apic_ops); | ||
20 | return 0; | ||
21 | } | ||
22 | |||
15 | #endif /* ASM_MSI_H */ | 23 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-i386/vga.h b/include/asm-i386/vga.h index ef0c0e50cc95..0ecf68ac03aa 100644 --- a/include/asm-i386/vga.h +++ b/include/asm-i386/vga.h | |||
@@ -12,7 +12,7 @@ | |||
12 | * access the videoram directly without any black magic. | 12 | * access the videoram directly without any black magic. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) | 15 | #define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) |
16 | 16 | ||
17 | #define vga_readb(x) (*(x)) | 17 | #define vga_readb(x) (*(x)) |
18 | #define vga_writeb(x,y) (*(y) = (x)) | 18 | #define vga_writeb(x,y) (*(y) = (x)) |
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h index 0cf119b42f7d..ea8b8c407ab4 100644 --- a/include/asm-ia64/hw_irq.h +++ b/include/asm-ia64/hw_irq.h | |||
@@ -47,9 +47,19 @@ typedef u8 ia64_vector; | |||
47 | #define IA64_CMC_VECTOR 0x1f /* corrected machine-check interrupt vector */ | 47 | #define IA64_CMC_VECTOR 0x1f /* corrected machine-check interrupt vector */ |
48 | /* | 48 | /* |
49 | * Vectors 0x20-0x2f are reserved for legacy ISA IRQs. | 49 | * Vectors 0x20-0x2f are reserved for legacy ISA IRQs. |
50 | * Use vectors 0x30-0xe7 as the default device vector range for ia64. | ||
51 | * Platforms may choose to reduce this range in platform_irq_setup, but the | ||
52 | * platform range must fall within | ||
53 | * [IA64_DEF_FIRST_DEVICE_VECTOR..IA64_DEF_LAST_DEVICE_VECTOR] | ||
50 | */ | 54 | */ |
51 | #define IA64_FIRST_DEVICE_VECTOR 0x30 | 55 | extern int ia64_first_device_vector; |
52 | #define IA64_LAST_DEVICE_VECTOR 0xe7 | 56 | extern int ia64_last_device_vector; |
57 | |||
58 | #define IA64_DEF_FIRST_DEVICE_VECTOR 0x30 | ||
59 | #define IA64_DEF_LAST_DEVICE_VECTOR 0xe7 | ||
60 | #define IA64_FIRST_DEVICE_VECTOR ia64_first_device_vector | ||
61 | #define IA64_LAST_DEVICE_VECTOR ia64_last_device_vector | ||
62 | #define IA64_MAX_DEVICE_VECTORS (IA64_DEF_LAST_DEVICE_VECTOR - IA64_DEF_FIRST_DEVICE_VECTOR + 1) | ||
53 | #define IA64_NUM_DEVICE_VECTORS (IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1) | 63 | #define IA64_NUM_DEVICE_VECTORS (IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1) |
54 | 64 | ||
55 | #define IA64_MCA_RENDEZ_VECTOR 0xe8 /* MCA rendez interrupt */ | 65 | #define IA64_MCA_RENDEZ_VECTOR 0xe8 /* MCA rendez interrupt */ |
@@ -83,6 +93,7 @@ extern struct hw_interrupt_type irq_type_ia64_lsapic; /* CPU-internal interrupt | |||
83 | 93 | ||
84 | extern int assign_irq_vector (int irq); /* allocate a free vector */ | 94 | extern int assign_irq_vector (int irq); /* allocate a free vector */ |
85 | extern void free_irq_vector (int vector); | 95 | extern void free_irq_vector (int vector); |
96 | extern int reserve_irq_vector (int vector); | ||
86 | extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); | 97 | extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect); |
87 | extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); | 98 | extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); |
88 | 99 | ||
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index 0df72a134c8b..15b545a897a4 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h | |||
@@ -75,6 +75,7 @@ typedef unsigned char ia64_mv_readb_relaxed_t (const volatile void __iomem *); | |||
75 | typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *); | 75 | typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *); |
76 | typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); | 76 | typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); |
77 | typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); | 77 | typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); |
78 | typedef int ia64_mv_msi_init_t (void); | ||
78 | 79 | ||
79 | static inline void | 80 | static inline void |
80 | machvec_noop (void) | 81 | machvec_noop (void) |
@@ -153,6 +154,7 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); | |||
153 | # define platform_readl_relaxed ia64_mv.readl_relaxed | 154 | # define platform_readl_relaxed ia64_mv.readl_relaxed |
154 | # define platform_readq_relaxed ia64_mv.readq_relaxed | 155 | # define platform_readq_relaxed ia64_mv.readq_relaxed |
155 | # define platform_migrate ia64_mv.migrate | 156 | # define platform_migrate ia64_mv.migrate |
157 | # define platform_msi_init ia64_mv.msi_init | ||
156 | # endif | 158 | # endif |
157 | 159 | ||
158 | /* __attribute__((__aligned__(16))) is required to make size of the | 160 | /* __attribute__((__aligned__(16))) is required to make size of the |
@@ -202,6 +204,7 @@ struct ia64_machine_vector { | |||
202 | ia64_mv_readl_relaxed_t *readl_relaxed; | 204 | ia64_mv_readl_relaxed_t *readl_relaxed; |
203 | ia64_mv_readq_relaxed_t *readq_relaxed; | 205 | ia64_mv_readq_relaxed_t *readq_relaxed; |
204 | ia64_mv_migrate_t *migrate; | 206 | ia64_mv_migrate_t *migrate; |
207 | ia64_mv_msi_init_t *msi_init; | ||
205 | } __attribute__((__aligned__(16))); /* align attrib? see above comment */ | 208 | } __attribute__((__aligned__(16))); /* align attrib? see above comment */ |
206 | 209 | ||
207 | #define MACHVEC_INIT(name) \ | 210 | #define MACHVEC_INIT(name) \ |
@@ -247,6 +250,7 @@ struct ia64_machine_vector { | |||
247 | platform_readl_relaxed, \ | 250 | platform_readl_relaxed, \ |
248 | platform_readq_relaxed, \ | 251 | platform_readq_relaxed, \ |
249 | platform_migrate, \ | 252 | platform_migrate, \ |
253 | platform_msi_init, \ | ||
250 | } | 254 | } |
251 | 255 | ||
252 | extern struct ia64_machine_vector ia64_mv; | 256 | extern struct ia64_machine_vector ia64_mv; |
@@ -400,5 +404,8 @@ extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size | |||
400 | #ifndef platform_migrate | 404 | #ifndef platform_migrate |
401 | # define platform_migrate machvec_noop_task | 405 | # define platform_migrate machvec_noop_task |
402 | #endif | 406 | #endif |
407 | #ifndef platform_msi_init | ||
408 | # define platform_msi_init ((ia64_mv_msi_init_t*)NULL) | ||
409 | #endif | ||
403 | 410 | ||
404 | #endif /* _ASM_IA64_MACHVEC_H */ | 411 | #endif /* _ASM_IA64_MACHVEC_H */ |
diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h index da1d43755afe..cf724dc79d8c 100644 --- a/include/asm-ia64/machvec_sn2.h +++ b/include/asm-ia64/machvec_sn2.h | |||
@@ -67,6 +67,8 @@ extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device; | |||
67 | extern ia64_mv_dma_mapping_error sn_dma_mapping_error; | 67 | extern ia64_mv_dma_mapping_error sn_dma_mapping_error; |
68 | extern ia64_mv_dma_supported sn_dma_supported; | 68 | extern ia64_mv_dma_supported sn_dma_supported; |
69 | extern ia64_mv_migrate_t sn_migrate; | 69 | extern ia64_mv_migrate_t sn_migrate; |
70 | extern ia64_mv_msi_init_t sn_msi_init; | ||
71 | |||
70 | 72 | ||
71 | /* | 73 | /* |
72 | * This stuff has dual use! | 74 | * This stuff has dual use! |
@@ -117,6 +119,11 @@ extern ia64_mv_migrate_t sn_migrate; | |||
117 | #define platform_dma_mapping_error sn_dma_mapping_error | 119 | #define platform_dma_mapping_error sn_dma_mapping_error |
118 | #define platform_dma_supported sn_dma_supported | 120 | #define platform_dma_supported sn_dma_supported |
119 | #define platform_migrate sn_migrate | 121 | #define platform_migrate sn_migrate |
122 | #ifdef CONFIG_PCI_MSI | ||
123 | #define platform_msi_init sn_msi_init | ||
124 | #else | ||
125 | #define platform_msi_init ((ia64_mv_msi_init_t*)NULL) | ||
126 | #endif | ||
120 | 127 | ||
121 | #include <asm/sn/io.h> | 128 | #include <asm/sn/io.h> |
122 | 129 | ||
diff --git a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h index 97890f7762b3..bb92b0dbde2f 100644 --- a/include/asm-ia64/msi.h +++ b/include/asm-ia64/msi.h | |||
@@ -14,4 +14,16 @@ static inline void set_intr_gate (int nr, void *func) {} | |||
14 | #define ack_APIC_irq ia64_eoi | 14 | #define ack_APIC_irq ia64_eoi |
15 | #define MSI_TARGET_CPU_SHIFT 4 | 15 | #define MSI_TARGET_CPU_SHIFT 4 |
16 | 16 | ||
17 | extern struct msi_ops msi_apic_ops; | ||
18 | |||
19 | static inline int msi_arch_init(void) | ||
20 | { | ||
21 | if (platform_msi_init) | ||
22 | return platform_msi_init(); | ||
23 | |||
24 | /* default ops for most ia64 platforms */ | ||
25 | msi_register(&msi_apic_ops); | ||
26 | return 0; | ||
27 | } | ||
28 | |||
17 | #endif /* ASM_MSI_H */ | 29 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h index 60a51a406eec..12b54ddb06be 100644 --- a/include/asm-ia64/sn/intr.h +++ b/include/asm-ia64/sn/intr.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #define _ASM_IA64_SN_INTR_H | 10 | #define _ASM_IA64_SN_INTR_H |
11 | 11 | ||
12 | #include <linux/rcupdate.h> | 12 | #include <linux/rcupdate.h> |
13 | #include <asm/sn/types.h> | ||
13 | 14 | ||
14 | #define SGI_UART_VECTOR 0xe9 | 15 | #define SGI_UART_VECTOR 0xe9 |
15 | 16 | ||
@@ -40,6 +41,7 @@ struct sn_irq_info { | |||
40 | int irq_cpuid; /* kernel logical cpuid */ | 41 | int irq_cpuid; /* kernel logical cpuid */ |
41 | int irq_irq; /* the IRQ number */ | 42 | int irq_irq; /* the IRQ number */ |
42 | int irq_int_bit; /* Bridge interrupt pin */ | 43 | int irq_int_bit; /* Bridge interrupt pin */ |
44 | /* <0 means MSI */ | ||
43 | u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */ | 45 | u64 irq_xtalkaddr; /* xtalkaddr IRQ is sent to */ |
44 | int irq_bridge_type;/* pciio asic type (pciio.h) */ | 46 | int irq_bridge_type;/* pciio asic type (pciio.h) */ |
45 | void *irq_bridge; /* bridge generating irq */ | 47 | void *irq_bridge; /* bridge generating irq */ |
@@ -53,6 +55,12 @@ struct sn_irq_info { | |||
53 | }; | 55 | }; |
54 | 56 | ||
55 | extern void sn_send_IPI_phys(int, long, int, int); | 57 | extern void sn_send_IPI_phys(int, long, int, int); |
58 | extern u64 sn_intr_alloc(nasid_t, int, | ||
59 | struct sn_irq_info *, | ||
60 | int, nasid_t, int); | ||
61 | extern void sn_intr_free(nasid_t, int, struct sn_irq_info *); | ||
62 | extern struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *, nasid_t, int); | ||
63 | extern struct list_head **sn_irq_lh; | ||
56 | 64 | ||
57 | #define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector) | 65 | #define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector) |
58 | 66 | ||
diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h index 51260ab70d91..e3b0c3fe5eed 100644 --- a/include/asm-ia64/sn/pcibr_provider.h +++ b/include/asm-ia64/sn/pcibr_provider.h | |||
@@ -55,6 +55,7 @@ | |||
55 | #define PCI32_ATE_V (0x1 << 0) | 55 | #define PCI32_ATE_V (0x1 << 0) |
56 | #define PCI32_ATE_CO (0x1 << 1) | 56 | #define PCI32_ATE_CO (0x1 << 1) |
57 | #define PCI32_ATE_PREC (0x1 << 2) | 57 | #define PCI32_ATE_PREC (0x1 << 2) |
58 | #define PCI32_ATE_MSI (0x1 << 2) | ||
58 | #define PCI32_ATE_PREF (0x1 << 3) | 59 | #define PCI32_ATE_PREF (0x1 << 3) |
59 | #define PCI32_ATE_BAR (0x1 << 4) | 60 | #define PCI32_ATE_BAR (0x1 << 4) |
60 | #define PCI32_ATE_ADDR_SHFT 12 | 61 | #define PCI32_ATE_ADDR_SHFT 12 |
@@ -117,8 +118,8 @@ struct pcibus_info { | |||
117 | 118 | ||
118 | extern int pcibr_init_provider(void); | 119 | extern int pcibr_init_provider(void); |
119 | extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *); | 120 | extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *); |
120 | extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t); | 121 | extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t, int type); |
121 | extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t); | 122 | extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t, int type); |
122 | extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int); | 123 | extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int); |
123 | 124 | ||
124 | /* | 125 | /* |
diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h index ce3f6c328241..8f7c83d0f6d3 100644 --- a/include/asm-ia64/sn/pcibus_provider_defs.h +++ b/include/asm-ia64/sn/pcibus_provider_defs.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | #ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H | 8 | #ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H |
9 | #define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H | 9 | #define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H |
@@ -45,13 +45,24 @@ struct pci_controller; | |||
45 | */ | 45 | */ |
46 | 46 | ||
47 | struct sn_pcibus_provider { | 47 | struct sn_pcibus_provider { |
48 | dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t); | 48 | dma_addr_t (*dma_map)(struct pci_dev *, unsigned long, size_t, int flags); |
49 | dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t); | 49 | dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t, int flags); |
50 | void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); | 50 | void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); |
51 | void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *); | 51 | void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *); |
52 | void (*force_interrupt)(struct sn_irq_info *); | 52 | void (*force_interrupt)(struct sn_irq_info *); |
53 | void (*target_interrupt)(struct sn_irq_info *); | 53 | void (*target_interrupt)(struct sn_irq_info *); |
54 | }; | 54 | }; |
55 | 55 | ||
56 | /* | ||
57 | * Flags used by the map interfaces | ||
58 | * bits 3:0 specifies format of passed in address | ||
59 | * bit 4 specifies that address is to be used for MSI | ||
60 | */ | ||
61 | |||
62 | #define SN_DMA_ADDRTYPE(x) ((x) & 0xf) | ||
63 | #define SN_DMA_ADDR_PHYS 1 /* address is an xio address. */ | ||
64 | #define SN_DMA_ADDR_XIO 2 /* address is phys memory */ | ||
65 | #define SN_DMA_MSI 0x10 /* Bus address is to be used for MSI */ | ||
66 | |||
56 | extern struct sn_pcibus_provider *sn_pci_provider[]; | 67 | extern struct sn_pcibus_provider *sn_pci_provider[]; |
57 | #endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */ | 68 | #endif /* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */ |
diff --git a/include/asm-ia64/sn/tiocp.h b/include/asm-ia64/sn/tiocp.h index f47c08ab483c..e8ad0bb5b6c5 100644 --- a/include/asm-ia64/sn/tiocp.h +++ b/include/asm-ia64/sn/tiocp.h | |||
@@ -3,13 +3,14 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved. | 6 | * Copyright (C) 2003-2005 Silicon Graphics, Inc. All rights reserved. |
7 | */ | 7 | */ |
8 | #ifndef _ASM_IA64_SN_PCI_TIOCP_H | 8 | #ifndef _ASM_IA64_SN_PCI_TIOCP_H |
9 | #define _ASM_IA64_SN_PCI_TIOCP_H | 9 | #define _ASM_IA64_SN_PCI_TIOCP_H |
10 | 10 | ||
11 | #define TIOCP_HOST_INTR_ADDR 0x003FFFFFFFFFFFFFUL | 11 | #define TIOCP_HOST_INTR_ADDR 0x003FFFFFFFFFFFFFUL |
12 | #define TIOCP_PCI64_CMDTYPE_MEM (0x1ull << 60) | 12 | #define TIOCP_PCI64_CMDTYPE_MEM (0x1ull << 60) |
13 | #define TIOCP_PCI64_CMDTYPE_MSI (0x3ull << 60) | ||
13 | 14 | ||
14 | 15 | ||
15 | /***************************************************************************** | 16 | /***************************************************************************** |
diff --git a/include/asm-ia64/vga.h b/include/asm-ia64/vga.h index 091177cda223..02184ecd8208 100644 --- a/include/asm-ia64/vga.h +++ b/include/asm-ia64/vga.h | |||
@@ -17,7 +17,7 @@ | |||
17 | extern unsigned long vga_console_iobase; | 17 | extern unsigned long vga_console_iobase; |
18 | extern unsigned long vga_console_membase; | 18 | extern unsigned long vga_console_membase; |
19 | 19 | ||
20 | #define VGA_MAP_MEM(x) ((unsigned long) ioremap_nocache(vga_console_membase + (x), 0)) | 20 | #define VGA_MAP_MEM(x,s) ((unsigned long) ioremap_nocache(vga_console_membase + (x), s)) |
21 | 21 | ||
22 | #define vga_readb(x) (*(x)) | 22 | #define vga_readb(x) (*(x)) |
23 | #define vga_writeb(x,y) (*(y) = (x)) | 23 | #define vga_writeb(x,y) (*(y) = (x)) |
diff --git a/include/asm-m32r/vga.h b/include/asm-m32r/vga.h index d0f4b6eed7a3..533163447cc9 100644 --- a/include/asm-m32r/vga.h +++ b/include/asm-m32r/vga.h | |||
@@ -14,7 +14,7 @@ | |||
14 | * access the videoram directly without any black magic. | 14 | * access the videoram directly without any black magic. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) | 17 | #define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) |
18 | 18 | ||
19 | #define vga_readb(x) (*(x)) | 19 | #define vga_readb(x) (*(x)) |
20 | #define vga_writeb(x,y) (*(y) = (x)) | 20 | #define vga_writeb(x,y) (*(y) = (x)) |
diff --git a/include/asm-mips/vga.h b/include/asm-mips/vga.h index 34755c0a6398..c1dd0b10bc27 100644 --- a/include/asm-mips/vga.h +++ b/include/asm-mips/vga.h | |||
@@ -13,7 +13,7 @@ | |||
13 | * access the videoram directly without any black magic. | 13 | * access the videoram directly without any black magic. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #define VGA_MAP_MEM(x) (0xb0000000L + (unsigned long)(x)) | 16 | #define VGA_MAP_MEM(x,s) (0xb0000000L + (unsigned long)(x)) |
17 | 17 | ||
18 | #define vga_readb(x) (*(x)) | 18 | #define vga_readb(x) (*(x)) |
19 | #define vga_writeb(x,y) (*(y) = (x)) | 19 | #define vga_writeb(x,y) (*(y) = (x)) |
diff --git a/include/asm-powerpc/vga.h b/include/asm-powerpc/vga.h index eadaf2f3d032..a2eac409c1ec 100644 --- a/include/asm-powerpc/vga.h +++ b/include/asm-powerpc/vga.h | |||
@@ -41,9 +41,9 @@ static inline u16 scr_readw(volatile const u16 *addr) | |||
41 | extern unsigned long vgacon_remap_base; | 41 | extern unsigned long vgacon_remap_base; |
42 | 42 | ||
43 | #ifdef __powerpc64__ | 43 | #ifdef __powerpc64__ |
44 | #define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0)) | 44 | #define VGA_MAP_MEM(x,s) ((unsigned long) ioremap((x), s)) |
45 | #else | 45 | #else |
46 | #define VGA_MAP_MEM(x) (x + vgacon_remap_base) | 46 | #define VGA_MAP_MEM(x,s) (x + vgacon_remap_base) |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define vga_readb(x) (*(x)) | 49 | #define vga_readb(x) (*(x)) |
diff --git a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h index 9c57eb363b40..c69d5b2ba19a 100644 --- a/include/asm-sparc64/vga.h +++ b/include/asm-sparc64/vga.h | |||
@@ -28,6 +28,6 @@ static inline u16 scr_readw(const u16 *addr) | |||
28 | return *addr; | 28 | return *addr; |
29 | } | 29 | } |
30 | 30 | ||
31 | #define VGA_MAP_MEM(x) (x) | 31 | #define VGA_MAP_MEM(x,s) (x) |
32 | 32 | ||
33 | #endif | 33 | #endif |
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h index 356e0e82f50b..3ad2346624b2 100644 --- a/include/asm-x86_64/msi.h +++ b/include/asm-x86_64/msi.h | |||
@@ -10,7 +10,15 @@ | |||
10 | #include <asm/mach_apic.h> | 10 | #include <asm/mach_apic.h> |
11 | #include <asm/smp.h> | 11 | #include <asm/smp.h> |
12 | 12 | ||
13 | #define LAST_DEVICE_VECTOR 232 | 13 | #define LAST_DEVICE_VECTOR (FIRST_SYSTEM_VECTOR - 1) |
14 | #define MSI_TARGET_CPU_SHIFT 12 | 14 | #define MSI_TARGET_CPU_SHIFT 12 |
15 | 15 | ||
16 | extern struct msi_ops msi_apic_ops; | ||
17 | |||
18 | static inline int msi_arch_init(void) | ||
19 | { | ||
20 | msi_register(&msi_apic_ops); | ||
21 | return 0; | ||
22 | } | ||
23 | |||
16 | #endif /* ASM_MSI_H */ | 24 | #endif /* ASM_MSI_H */ |
diff --git a/include/asm-x86_64/vga.h b/include/asm-x86_64/vga.h index ef0c0e50cc95..0ecf68ac03aa 100644 --- a/include/asm-x86_64/vga.h +++ b/include/asm-x86_64/vga.h | |||
@@ -12,7 +12,7 @@ | |||
12 | * access the videoram directly without any black magic. | 12 | * access the videoram directly without any black magic. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) | 15 | #define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) |
16 | 16 | ||
17 | #define vga_readb(x) (*(x)) | 17 | #define vga_readb(x) (*(x)) |
18 | #define vga_writeb(x,y) (*(y) = (x)) | 18 | #define vga_writeb(x,y) (*(y) = (x)) |
diff --git a/include/asm-xtensa/vga.h b/include/asm-xtensa/vga.h index 23d82f6acb57..1fd8cab3a297 100644 --- a/include/asm-xtensa/vga.h +++ b/include/asm-xtensa/vga.h | |||
@@ -11,7 +11,7 @@ | |||
11 | #ifndef _XTENSA_VGA_H | 11 | #ifndef _XTENSA_VGA_H |
12 | #define _XTENSA_VGA_H | 12 | #define _XTENSA_VGA_H |
13 | 13 | ||
14 | #define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x) | 14 | #define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x) |
15 | 15 | ||
16 | #define vga_readb(x) (*(x)) | 16 | #define vga_readb(x) (*(x)) |
17 | #define vga_writeb(x,y) (*(y) = (x)) | 17 | #define vga_writeb(x,y) (*(y) = (x)) |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 836325ee0931..46d0e079735d 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -217,7 +217,7 @@ extern struct dentry * d_alloc_anon(struct inode *); | |||
217 | extern struct dentry * d_splice_alias(struct inode *, struct dentry *); | 217 | extern struct dentry * d_splice_alias(struct inode *, struct dentry *); |
218 | extern void shrink_dcache_sb(struct super_block *); | 218 | extern void shrink_dcache_sb(struct super_block *); |
219 | extern void shrink_dcache_parent(struct dentry *); | 219 | extern void shrink_dcache_parent(struct dentry *); |
220 | extern void shrink_dcache_anon(struct hlist_head *); | 220 | extern void shrink_dcache_anon(struct super_block *); |
221 | extern int d_invalidate(struct dentry *); | 221 | extern int d_invalidate(struct dentry *); |
222 | 222 | ||
223 | /* only used at mount-time */ | 223 | /* only used at mount-time */ |
diff --git a/include/linux/fs.h b/include/linux/fs.h index ecc8c2c3d8ca..73c7d6f04b31 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -782,7 +782,6 @@ extern int setlease(struct file *, long, struct file_lock **); | |||
782 | extern int lease_modify(struct file_lock **, int); | 782 | extern int lease_modify(struct file_lock **, int); |
783 | extern int lock_may_read(struct inode *, loff_t start, unsigned long count); | 783 | extern int lock_may_read(struct inode *, loff_t start, unsigned long count); |
784 | extern int lock_may_write(struct inode *, loff_t start, unsigned long count); | 784 | extern int lock_may_write(struct inode *, loff_t start, unsigned long count); |
785 | extern void steal_locks(fl_owner_t from); | ||
786 | 785 | ||
787 | struct fasync_struct { | 786 | struct fasync_struct { |
788 | int magic; | 787 | int magic; |
diff --git a/include/linux/key.h b/include/linux/key.h index cbf464ad9589..e81ebf910d0b 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -205,6 +205,11 @@ struct key_type { | |||
205 | /* match a key against a description */ | 205 | /* match a key against a description */ |
206 | int (*match)(const struct key *key, const void *desc); | 206 | int (*match)(const struct key *key, const void *desc); |
207 | 207 | ||
208 | /* clear some of the data from a key on revokation (optional) | ||
209 | * - the key's semaphore will be write-locked by the caller | ||
210 | */ | ||
211 | void (*revoke)(struct key *key); | ||
212 | |||
208 | /* clear the data from a key (optional) */ | 213 | /* clear the data from a key (optional) */ |
209 | void (*destroy)(struct key *key); | 214 | void (*destroy)(struct key *key); |
210 | 215 | ||
@@ -241,8 +246,9 @@ extern void unregister_key_type(struct key_type *ktype); | |||
241 | 246 | ||
242 | extern struct key *key_alloc(struct key_type *type, | 247 | extern struct key *key_alloc(struct key_type *type, |
243 | const char *desc, | 248 | const char *desc, |
244 | uid_t uid, gid_t gid, key_perm_t perm, | 249 | uid_t uid, gid_t gid, |
245 | int not_in_quota); | 250 | struct task_struct *ctx, |
251 | key_perm_t perm, int not_in_quota); | ||
246 | extern int key_payload_reserve(struct key *key, size_t datalen); | 252 | extern int key_payload_reserve(struct key *key, size_t datalen); |
247 | extern int key_instantiate_and_link(struct key *key, | 253 | extern int key_instantiate_and_link(struct key *key, |
248 | const void *data, | 254 | const void *data, |
@@ -292,7 +298,9 @@ extern int key_unlink(struct key *keyring, | |||
292 | struct key *key); | 298 | struct key *key); |
293 | 299 | ||
294 | extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 300 | extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
295 | int not_in_quota, struct key *dest); | 301 | struct task_struct *ctx, |
302 | int not_in_quota, | ||
303 | struct key *dest); | ||
296 | 304 | ||
297 | extern int keyring_clear(struct key *keyring); | 305 | extern int keyring_clear(struct key *keyring); |
298 | 306 | ||
@@ -313,7 +321,8 @@ extern void keyring_replace_payload(struct key *key, void *replacement); | |||
313 | * the userspace interface | 321 | * the userspace interface |
314 | */ | 322 | */ |
315 | extern struct key root_user_keyring, root_session_keyring; | 323 | extern struct key root_user_keyring, root_session_keyring; |
316 | extern int alloc_uid_keyring(struct user_struct *user); | 324 | extern int alloc_uid_keyring(struct user_struct *user, |
325 | struct task_struct *ctx); | ||
317 | extern void switch_uid_keyring(struct user_struct *new_user); | 326 | extern void switch_uid_keyring(struct user_struct *new_user); |
318 | extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk); | 327 | extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk); |
319 | extern int copy_thread_group_keys(struct task_struct *tsk); | 328 | extern int copy_thread_group_keys(struct task_struct *tsk); |
@@ -342,7 +351,7 @@ extern void key_init(void); | |||
342 | #define make_key_ref(k) ({ NULL; }) | 351 | #define make_key_ref(k) ({ NULL; }) |
343 | #define key_ref_to_ptr(k) ({ NULL; }) | 352 | #define key_ref_to_ptr(k) ({ NULL; }) |
344 | #define is_key_possessed(k) 0 | 353 | #define is_key_possessed(k) 0 |
345 | #define alloc_uid_keyring(u) 0 | 354 | #define alloc_uid_keyring(u,c) 0 |
346 | #define switch_uid_keyring(u) do { } while(0) | 355 | #define switch_uid_keyring(u) do { } while(0) |
347 | #define __install_session_keyring(t, k) ({ NULL; }) | 356 | #define __install_session_keyring(t, k) ({ NULL; }) |
348 | #define copy_keys(f,t) 0 | 357 | #define copy_keys(f,t) 0 |
@@ -355,6 +364,10 @@ extern void key_init(void); | |||
355 | #define key_fsgid_changed(t) do { } while(0) | 364 | #define key_fsgid_changed(t) do { } while(0) |
356 | #define key_init() do { } while(0) | 365 | #define key_init() do { } while(0) |
357 | 366 | ||
367 | /* Initial keyrings */ | ||
368 | extern struct key root_user_keyring; | ||
369 | extern struct key root_session_keyring; | ||
370 | |||
358 | #endif /* CONFIG_KEYS */ | 371 | #endif /* CONFIG_KEYS */ |
359 | #endif /* __KERNEL__ */ | 372 | #endif /* __KERNEL__ */ |
360 | #endif /* _LINUX_KEY_H */ | 373 | #endif /* _LINUX_KEY_H */ |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 6c4bc773f7b7..62a8c22f5f60 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -162,6 +162,9 @@ struct pci_dev { | |||
162 | unsigned int is_busmaster:1; /* device is busmaster */ | 162 | unsigned int is_busmaster:1; /* device is busmaster */ |
163 | unsigned int no_msi:1; /* device may not use msi */ | 163 | unsigned int no_msi:1; /* device may not use msi */ |
164 | unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ | 164 | unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ |
165 | unsigned int broken_parity_status:1; /* Device generates false positive parity */ | ||
166 | unsigned int msi_enabled:1; | ||
167 | unsigned int msix_enabled:1; | ||
165 | 168 | ||
166 | u32 saved_config_space[16]; /* config space saved at suspend time */ | 169 | u32 saved_config_space[16]; /* config space saved at suspend time */ |
167 | struct hlist_head saved_cap_space; | 170 | struct hlist_head saved_cap_space; |
@@ -496,6 +499,7 @@ int pci_set_dma_mask(struct pci_dev *dev, u64 mask); | |||
496 | int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); | 499 | int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); |
497 | void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); | 500 | void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno); |
498 | int pci_assign_resource(struct pci_dev *dev, int i); | 501 | int pci_assign_resource(struct pci_dev *dev, int i); |
502 | int pci_assign_resource_fixed(struct pci_dev *dev, int i); | ||
499 | void pci_restore_bars(struct pci_dev *dev); | 503 | void pci_restore_bars(struct pci_dev *dev); |
500 | 504 | ||
501 | /* ROM control related routines */ | 505 | /* ROM control related routines */ |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bcfe9d4f56ae..fd54a9d4c3d4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -848,7 +848,12 @@ | |||
848 | 848 | ||
849 | 849 | ||
850 | #define PCI_VENDOR_ID_QLOGIC 0x1077 | 850 | #define PCI_VENDOR_ID_QLOGIC 0x1077 |
851 | #define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016 | ||
851 | #define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020 | 852 | #define PCI_DEVICE_ID_QLOGIC_ISP1020 0x1020 |
853 | #define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080 | ||
854 | #define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216 | ||
855 | #define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240 | ||
856 | #define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280 | ||
852 | #define PCI_DEVICE_ID_QLOGIC_ISP2100 0x2100 | 857 | #define PCI_DEVICE_ID_QLOGIC_ISP2100 0x2100 |
853 | #define PCI_DEVICE_ID_QLOGIC_ISP2200 0x2200 | 858 | #define PCI_DEVICE_ID_QLOGIC_ISP2200 0x2200 |
854 | #define PCI_DEVICE_ID_QLOGIC_ISP2300 0x2300 | 859 | #define PCI_DEVICE_ID_QLOGIC_ISP2300 0x2300 |
@@ -1018,6 +1023,7 @@ | |||
1018 | #define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056 | 1023 | #define PCI_DEVICE_ID_NVIDIA_NVENET_8 0x0056 |
1019 | #define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057 | 1024 | #define PCI_DEVICE_ID_NVIDIA_NVENET_9 0x0057 |
1020 | #define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 | 1025 | #define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059 |
1026 | #define PCI_DEVICE_ID_NVIDIA_CK804_PCIE 0x005d | ||
1021 | #define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 | 1027 | #define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS 0x0064 |
1022 | #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 | 1028 | #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE 0x0065 |
1023 | #define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 | 1029 | #define PCI_DEVICE_ID_NVIDIA_NVENET_2 0x0066 |
@@ -1946,6 +1952,7 @@ | |||
1946 | 1952 | ||
1947 | #define PCI_VENDOR_ID_MELLANOX 0x15b3 | 1953 | #define PCI_VENDOR_ID_MELLANOX 0x15b3 |
1948 | #define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 | 1954 | #define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 |
1955 | #define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE 0x5a46 | ||
1949 | #define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 | 1956 | #define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 |
1950 | #define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 | 1957 | #define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 |
1951 | #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c | 1958 | #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c |
@@ -1969,6 +1976,9 @@ | |||
1969 | #define PCI_VENDOR_ID_NETCELL 0x169c | 1976 | #define PCI_VENDOR_ID_NETCELL 0x169c |
1970 | #define PCI_DEVICE_ID_REVOLUTION 0x0044 | 1977 | #define PCI_DEVICE_ID_REVOLUTION 0x0044 |
1971 | 1978 | ||
1979 | #define PCI_VENDOR_ID_VITESSE 0x1725 | ||
1980 | #define PCI_DEVICE_ID_VITESSE_VSC7174 0x7174 | ||
1981 | |||
1972 | #define PCI_VENDOR_ID_LINKSYS 0x1737 | 1982 | #define PCI_VENDOR_ID_LINKSYS 0x1737 |
1973 | #define PCI_DEVICE_ID_LINKSYS_EG1064 0x1064 | 1983 | #define PCI_DEVICE_ID_LINKSYS_EG1064 0x1064 |
1974 | 1984 | ||
@@ -2148,6 +2158,7 @@ | |||
2148 | #define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 | 2158 | #define PCI_DEVICE_ID_INTEL_ICH8_4 0x2815 |
2149 | #define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e | 2159 | #define PCI_DEVICE_ID_INTEL_ICH8_5 0x283e |
2150 | #define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 | 2160 | #define PCI_DEVICE_ID_INTEL_ICH8_6 0x2850 |
2161 | #define PCI_DEVICE_ID_INTEL_GD31244 0x3200 | ||
2151 | #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 | 2162 | #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 |
2152 | #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 | 2163 | #define PCI_DEVICE_ID_INTEL_82830_HB 0x3575 |
2153 | #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 | 2164 | #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 |
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index d27a78b71297..6bce4a240364 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h | |||
@@ -197,6 +197,7 @@ | |||
197 | #define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ | 197 | #define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ |
198 | #define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ | 198 | #define PCI_CAP_ID_PCIX 0x07 /* PCI-X */ |
199 | #define PCI_CAP_ID_HT_IRQCONF 0x08 /* HyperTransport IRQ Configuration */ | 199 | #define PCI_CAP_ID_HT_IRQCONF 0x08 /* HyperTransport IRQ Configuration */ |
200 | #define PCI_CAP_ID_VNDR 0x09 /* Vendor specific capability */ | ||
200 | #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ | 201 | #define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */ |
201 | #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ | 202 | #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ |
202 | #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ | 203 | #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ |
diff --git a/include/linux/security.h b/include/linux/security.h index 4dfb1b84a9b3..47722d355532 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -1313,7 +1313,7 @@ struct security_operations { | |||
1313 | 1313 | ||
1314 | /* key management security hooks */ | 1314 | /* key management security hooks */ |
1315 | #ifdef CONFIG_KEYS | 1315 | #ifdef CONFIG_KEYS |
1316 | int (*key_alloc)(struct key *key); | 1316 | int (*key_alloc)(struct key *key, struct task_struct *tsk); |
1317 | void (*key_free)(struct key *key); | 1317 | void (*key_free)(struct key *key); |
1318 | int (*key_permission)(key_ref_t key_ref, | 1318 | int (*key_permission)(key_ref_t key_ref, |
1319 | struct task_struct *context, | 1319 | struct task_struct *context, |
@@ -3008,9 +3008,10 @@ static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid | |||
3008 | 3008 | ||
3009 | #ifdef CONFIG_KEYS | 3009 | #ifdef CONFIG_KEYS |
3010 | #ifdef CONFIG_SECURITY | 3010 | #ifdef CONFIG_SECURITY |
3011 | static inline int security_key_alloc(struct key *key) | 3011 | static inline int security_key_alloc(struct key *key, |
3012 | struct task_struct *tsk) | ||
3012 | { | 3013 | { |
3013 | return security_ops->key_alloc(key); | 3014 | return security_ops->key_alloc(key, tsk); |
3014 | } | 3015 | } |
3015 | 3016 | ||
3016 | static inline void security_key_free(struct key *key) | 3017 | static inline void security_key_free(struct key *key) |
@@ -3027,7 +3028,8 @@ static inline int security_key_permission(key_ref_t key_ref, | |||
3027 | 3028 | ||
3028 | #else | 3029 | #else |
3029 | 3030 | ||
3030 | static inline int security_key_alloc(struct key *key) | 3031 | static inline int security_key_alloc(struct key *key, |
3032 | struct task_struct *tsk) | ||
3031 | { | 3033 | { |
3032 | return 0; | 3034 | return 0; |
3033 | } | 3035 | } |
diff --git a/include/linux/zconf.h b/include/linux/zconf.h index f1cfd66b9554..0beb75e38caa 100644 --- a/include/linux/zconf.h +++ b/include/linux/zconf.h | |||
@@ -35,6 +35,18 @@ | |||
35 | # define MAX_WBITS 15 /* 32K LZ77 window */ | 35 | # define MAX_WBITS 15 /* 32K LZ77 window */ |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | /* default windowBits for decompression. MAX_WBITS is for compression only */ | ||
39 | #ifndef DEF_WBITS | ||
40 | # define DEF_WBITS MAX_WBITS | ||
41 | #endif | ||
42 | |||
43 | /* default memLevel */ | ||
44 | #if MAX_MEM_LEVEL >= 8 | ||
45 | # define DEF_MEM_LEVEL 8 | ||
46 | #else | ||
47 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL | ||
48 | #endif | ||
49 | |||
38 | /* Type declarations */ | 50 | /* Type declarations */ |
39 | 51 | ||
40 | typedef unsigned char Byte; /* 8 bits */ | 52 | typedef unsigned char Byte; /* 8 bits */ |
diff --git a/include/linux/zlib.h b/include/linux/zlib.h index 4fa32f0d4df8..9e3192a7dc6f 100644 --- a/include/linux/zlib.h +++ b/include/linux/zlib.h | |||
@@ -1,7 +1,6 @@ | |||
1 | /* zlib.h -- interface of the 'zlib' general purpose compression library | 1 | /* zlib.h -- interface of the 'zlib' general purpose compression library |
2 | version 1.1.3, July 9th, 1998 | ||
3 | 2 | ||
4 | Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler | 3 | Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler |
5 | 4 | ||
6 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
7 | warranty. In no event will the authors be held liable for any damages | 6 | warranty. In no event will the authors be held liable for any damages |
@@ -24,7 +23,7 @@ | |||
24 | 23 | ||
25 | 24 | ||
26 | The data format used by the zlib library is described by RFCs (Request for | 25 | The data format used by the zlib library is described by RFCs (Request for |
27 | Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt | 26 | Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt |
28 | (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). | 27 | (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). |
29 | */ | 28 | */ |
30 | 29 | ||
@@ -33,7 +32,22 @@ | |||
33 | 32 | ||
34 | #include <linux/zconf.h> | 33 | #include <linux/zconf.h> |
35 | 34 | ||
36 | #define ZLIB_VERSION "1.1.3" | 35 | /* zlib deflate based on ZLIB_VERSION "1.1.3" */ |
36 | /* zlib inflate based on ZLIB_VERSION "1.2.3" */ | ||
37 | |||
38 | /* | ||
39 | This is a modified version of zlib for use inside the Linux kernel. | ||
40 | The main changes are to perform all memory allocation in advance. | ||
41 | |||
42 | Inflation Changes: | ||
43 | * Z_PACKET_FLUSH is added and used by ppp_deflate. Before returning | ||
44 | this checks there is no more input data available and the next data | ||
45 | is a STORED block. It also resets the mode to be read for the next | ||
46 | data, all as per PPP requirements. | ||
47 | * Addition of zlib_inflateIncomp which copies incompressible data into | ||
48 | the history window and adjusts the accoutning without calling | ||
49 | zlib_inflate itself to inflate the data. | ||
50 | */ | ||
37 | 51 | ||
38 | /* | 52 | /* |
39 | The 'zlib' compression library provides in-memory compression and | 53 | The 'zlib' compression library provides in-memory compression and |
@@ -48,9 +62,18 @@ | |||
48 | application must provide more input and/or consume the output | 62 | application must provide more input and/or consume the output |
49 | (providing more output space) before each call. | 63 | (providing more output space) before each call. |
50 | 64 | ||
65 | The compressed data format used by default by the in-memory functions is | ||
66 | the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped | ||
67 | around a deflate stream, which is itself documented in RFC 1951. | ||
68 | |||
51 | The library also supports reading and writing files in gzip (.gz) format | 69 | The library also supports reading and writing files in gzip (.gz) format |
52 | with an interface similar to that of stdio. | 70 | with an interface similar to that of stdio. |
53 | 71 | ||
72 | The zlib format was designed to be compact and fast for use in memory | ||
73 | and on communications channels. The gzip format was designed for single- | ||
74 | file compression on file systems, has a larger header than zlib to maintain | ||
75 | directory information, and uses a different, slower check method than zlib. | ||
76 | |||
54 | The library does not install any signal handler. The decoder checks | 77 | The library does not install any signal handler. The decoder checks |
55 | the consistency of the compressed data, so the library should never | 78 | the consistency of the compressed data, so the library should never |
56 | crash even in case of corrupted input. | 79 | crash even in case of corrupted input. |
@@ -119,7 +142,8 @@ typedef z_stream *z_streamp; | |||
119 | #define Z_SYNC_FLUSH 3 | 142 | #define Z_SYNC_FLUSH 3 |
120 | #define Z_FULL_FLUSH 4 | 143 | #define Z_FULL_FLUSH 4 |
121 | #define Z_FINISH 5 | 144 | #define Z_FINISH 5 |
122 | /* Allowed flush values; see deflate() below for details */ | 145 | #define Z_BLOCK 6 /* Only for inflate at present */ |
146 | /* Allowed flush values; see deflate() and inflate() below for details */ | ||
123 | 147 | ||
124 | #define Z_OK 0 | 148 | #define Z_OK 0 |
125 | #define Z_STREAM_END 1 | 149 | #define Z_STREAM_END 1 |
@@ -155,13 +179,6 @@ typedef z_stream *z_streamp; | |||
155 | 179 | ||
156 | /* basic functions */ | 180 | /* basic functions */ |
157 | 181 | ||
158 | extern const char * zlib_zlibVersion (void); | ||
159 | /* The application can compare zlibVersion and ZLIB_VERSION for consistency. | ||
160 | If the first character differs, the library code actually used is | ||
161 | not compatible with the zlib.h header file used by the application. | ||
162 | This check is automatically made by deflateInit and inflateInit. | ||
163 | */ | ||
164 | |||
165 | extern int zlib_deflate_workspacesize (void); | 182 | extern int zlib_deflate_workspacesize (void); |
166 | /* | 183 | /* |
167 | Returns the number of bytes that needs to be allocated for a per- | 184 | Returns the number of bytes that needs to be allocated for a per- |
@@ -315,9 +332,9 @@ extern int zlib_inflateInit (z_streamp strm); | |||
315 | extern int zlib_inflate (z_streamp strm, int flush); | 332 | extern int zlib_inflate (z_streamp strm, int flush); |
316 | /* | 333 | /* |
317 | inflate decompresses as much data as possible, and stops when the input | 334 | inflate decompresses as much data as possible, and stops when the input |
318 | buffer becomes empty or the output buffer becomes full. It may some | 335 | buffer becomes empty or the output buffer becomes full. It may introduce |
319 | introduce some output latency (reading input without producing any output) | 336 | some output latency (reading input without producing any output) except when |
320 | except when forced to flush. | 337 | forced to flush. |
321 | 338 | ||
322 | The detailed semantics are as follows. inflate performs one or both of the | 339 | The detailed semantics are as follows. inflate performs one or both of the |
323 | following actions: | 340 | following actions: |
@@ -341,11 +358,26 @@ extern int zlib_inflate (z_streamp strm, int flush); | |||
341 | must be called again after making room in the output buffer because there | 358 | must be called again after making room in the output buffer because there |
342 | might be more output pending. | 359 | might be more output pending. |
343 | 360 | ||
344 | If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much | 361 | The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, |
345 | output as possible to the output buffer. The flushing behavior of inflate is | 362 | Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much |
346 | not specified for values of the flush parameter other than Z_SYNC_FLUSH | 363 | output as possible to the output buffer. Z_BLOCK requests that inflate() stop |
347 | and Z_FINISH, but the current implementation actually flushes as much output | 364 | if and when it gets to the next deflate block boundary. When decoding the |
348 | as possible anyway. | 365 | zlib or gzip format, this will cause inflate() to return immediately after |
366 | the header and before the first block. When doing a raw inflate, inflate() | ||
367 | will go ahead and process the first block, and will return when it gets to | ||
368 | the end of that block, or when it runs out of data. | ||
369 | |||
370 | The Z_BLOCK option assists in appending to or combining deflate streams. | ||
371 | Also to assist in this, on return inflate() will set strm->data_type to the | ||
372 | number of unused bits in the last byte taken from strm->next_in, plus 64 | ||
373 | if inflate() is currently decoding the last block in the deflate stream, | ||
374 | plus 128 if inflate() returned immediately after decoding an end-of-block | ||
375 | code or decoding the complete header up to just before the first byte of the | ||
376 | deflate stream. The end-of-block will not be indicated until all of the | ||
377 | uncompressed data from that block has been written to strm->next_out. The | ||
378 | number of unused bits may in general be greater than seven, except when | ||
379 | bit 7 of data_type is set, in which case the number of unused bits will be | ||
380 | less than eight. | ||
349 | 381 | ||
350 | inflate() should normally be called until it returns Z_STREAM_END or an | 382 | inflate() should normally be called until it returns Z_STREAM_END or an |
351 | error. However if all decompression is to be performed in a single step | 383 | error. However if all decompression is to be performed in a single step |
@@ -355,29 +387,44 @@ extern int zlib_inflate (z_streamp strm, int flush); | |||
355 | uncompressed data. (The size of the uncompressed data may have been saved | 387 | uncompressed data. (The size of the uncompressed data may have been saved |
356 | by the compressor for this purpose.) The next operation on this stream must | 388 | by the compressor for this purpose.) The next operation on this stream must |
357 | be inflateEnd to deallocate the decompression state. The use of Z_FINISH | 389 | be inflateEnd to deallocate the decompression state. The use of Z_FINISH |
358 | is never required, but can be used to inform inflate that a faster routine | 390 | is never required, but can be used to inform inflate that a faster approach |
359 | may be used for the single inflate() call. | 391 | may be used for the single inflate() call. |
360 | 392 | ||
361 | If a preset dictionary is needed at this point (see inflateSetDictionary | 393 | In this implementation, inflate() always flushes as much output as |
362 | below), inflate sets strm-adler to the adler32 checksum of the | 394 | possible to the output buffer, and always uses the faster approach on the |
363 | dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise | 395 | first call. So the only effect of the flush parameter in this implementation |
364 | it sets strm->adler to the adler32 checksum of all output produced | 396 | is on the return value of inflate(), as noted below, or when it returns early |
365 | so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or | 397 | because Z_BLOCK is used. |
366 | an error code as described below. At the end of the stream, inflate() | 398 | |
367 | checks that its computed adler32 checksum is equal to that saved by the | 399 | If a preset dictionary is needed after this call (see inflateSetDictionary |
368 | compressor and returns Z_STREAM_END only if the checksum is correct. | 400 | below), inflate sets strm->adler to the adler32 checksum of the dictionary |
401 | chosen by the compressor and returns Z_NEED_DICT; otherwise it sets | ||
402 | strm->adler to the adler32 checksum of all output produced so far (that is, | ||
403 | total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described | ||
404 | below. At the end of the stream, inflate() checks that its computed adler32 | ||
405 | checksum is equal to that saved by the compressor and returns Z_STREAM_END | ||
406 | only if the checksum is correct. | ||
407 | |||
408 | inflate() will decompress and check either zlib-wrapped or gzip-wrapped | ||
409 | deflate data. The header type is detected automatically. Any information | ||
410 | contained in the gzip header is not retained, so applications that need that | ||
411 | information should instead use raw inflate, see inflateInit2() below, or | ||
412 | inflateBack() and perform their own processing of the gzip header and | ||
413 | trailer. | ||
369 | 414 | ||
370 | inflate() returns Z_OK if some progress has been made (more input processed | 415 | inflate() returns Z_OK if some progress has been made (more input processed |
371 | or more output produced), Z_STREAM_END if the end of the compressed data has | 416 | or more output produced), Z_STREAM_END if the end of the compressed data has |
372 | been reached and all uncompressed output has been produced, Z_NEED_DICT if a | 417 | been reached and all uncompressed output has been produced, Z_NEED_DICT if a |
373 | preset dictionary is needed at this point, Z_DATA_ERROR if the input data was | 418 | preset dictionary is needed at this point, Z_DATA_ERROR if the input data was |
374 | corrupted (input stream not conforming to the zlib format or incorrect | 419 | corrupted (input stream not conforming to the zlib format or incorrect check |
375 | adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent | 420 | value), Z_STREAM_ERROR if the stream structure was inconsistent (for example |
376 | (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not | 421 | if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, |
377 | enough memory, Z_BUF_ERROR if no progress is possible or if there was not | 422 | Z_BUF_ERROR if no progress is possible or if there was not enough room in the |
378 | enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR | 423 | output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and |
379 | case, the application may then call inflateSync to look for a good | 424 | inflate() can be called again with more input and more output space to |
380 | compression block. | 425 | continue decompressing. If Z_DATA_ERROR is returned, the application may then |
426 | call inflateSync() to look for a good compression block if a partial recovery | ||
427 | of the data is desired. | ||
381 | */ | 428 | */ |
382 | 429 | ||
383 | 430 | ||
@@ -547,16 +594,36 @@ extern int inflateInit2 (z_streamp strm, int windowBits); | |||
547 | The windowBits parameter is the base two logarithm of the maximum window | 594 | The windowBits parameter is the base two logarithm of the maximum window |
548 | size (the size of the history buffer). It should be in the range 8..15 for | 595 | size (the size of the history buffer). It should be in the range 8..15 for |
549 | this version of the library. The default value is 15 if inflateInit is used | 596 | this version of the library. The default value is 15 if inflateInit is used |
550 | instead. If a compressed stream with a larger window size is given as | 597 | instead. windowBits must be greater than or equal to the windowBits value |
551 | input, inflate() will return with the error code Z_DATA_ERROR instead of | 598 | provided to deflateInit2() while compressing, or it must be equal to 15 if |
552 | trying to allocate a larger window. | 599 | deflateInit2() was not used. If a compressed stream with a larger window |
553 | 600 | size is given as input, inflate() will return with the error code | |
554 | inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough | 601 | Z_DATA_ERROR instead of trying to allocate a larger window. |
555 | memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative | 602 | |
556 | memLevel). msg is set to null if there is no error message. inflateInit2 | 603 | windowBits can also be -8..-15 for raw inflate. In this case, -windowBits |
557 | does not perform any decompression apart from reading the zlib header if | 604 | determines the window size. inflate() will then process raw deflate data, |
558 | present: this will be done by inflate(). (So next_in and avail_in may be | 605 | not looking for a zlib or gzip header, not generating a check value, and not |
559 | modified, but next_out and avail_out are unchanged.) | 606 | looking for any check values for comparison at the end of the stream. This |
607 | is for use with other formats that use the deflate compressed data format | ||
608 | such as zip. Those formats provide their own check values. If a custom | ||
609 | format is developed using the raw deflate format for compressed data, it is | ||
610 | recommended that a check value such as an adler32 or a crc32 be applied to | ||
611 | the uncompressed data as is done in the zlib, gzip, and zip formats. For | ||
612 | most applications, the zlib format should be used as is. Note that comments | ||
613 | above on the use in deflateInit2() applies to the magnitude of windowBits. | ||
614 | |||
615 | windowBits can also be greater than 15 for optional gzip decoding. Add | ||
616 | 32 to windowBits to enable zlib and gzip decoding with automatic header | ||
617 | detection, or add 16 to decode only the gzip format (the zlib format will | ||
618 | return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is | ||
619 | a crc32 instead of an adler32. | ||
620 | |||
621 | inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough | ||
622 | memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg | ||
623 | is set to null if there is no error message. inflateInit2 does not perform | ||
624 | any decompression apart from reading the zlib header if present: this will | ||
625 | be done by inflate(). (So next_in and avail_in may be modified, but next_out | ||
626 | and avail_out are unchanged.) | ||
560 | */ | 627 | */ |
561 | 628 | ||
562 | extern int zlib_inflateSetDictionary (z_streamp strm, | 629 | extern int zlib_inflateSetDictionary (z_streamp strm, |
@@ -564,16 +631,19 @@ extern int zlib_inflateSetDictionary (z_streamp strm, | |||
564 | uInt dictLength); | 631 | uInt dictLength); |
565 | /* | 632 | /* |
566 | Initializes the decompression dictionary from the given uncompressed byte | 633 | Initializes the decompression dictionary from the given uncompressed byte |
567 | sequence. This function must be called immediately after a call of inflate | 634 | sequence. This function must be called immediately after a call of inflate, |
568 | if this call returned Z_NEED_DICT. The dictionary chosen by the compressor | 635 | if that call returned Z_NEED_DICT. The dictionary chosen by the compressor |
569 | can be determined from the Adler32 value returned by this call of | 636 | can be determined from the adler32 value returned by that call of inflate. |
570 | inflate. The compressor and decompressor must use exactly the same | 637 | The compressor and decompressor must use exactly the same dictionary (see |
571 | dictionary (see deflateSetDictionary). | 638 | deflateSetDictionary). For raw inflate, this function can be called |
639 | immediately after inflateInit2() or inflateReset() and before any call of | ||
640 | inflate() to set the dictionary. The application must insure that the | ||
641 | dictionary that was used for compression is provided. | ||
572 | 642 | ||
573 | inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a | 643 | inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a |
574 | parameter is invalid (such as NULL dictionary) or the stream state is | 644 | parameter is invalid (such as NULL dictionary) or the stream state is |
575 | inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the | 645 | inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the |
576 | expected one (incorrect Adler32 value). inflateSetDictionary does not | 646 | expected one (incorrect adler32 value). inflateSetDictionary does not |
577 | perform any decompression: this will be done by subsequent calls of | 647 | perform any decompression: this will be done by subsequent calls of |
578 | inflate(). | 648 | inflate(). |
579 | */ | 649 | */ |
@@ -614,40 +684,19 @@ extern int zlib_inflateIncomp (z_stream *strm); | |||
614 | containing the data at next_in (except that the data is not output). | 684 | containing the data at next_in (except that the data is not output). |
615 | */ | 685 | */ |
616 | 686 | ||
617 | /* various hacks, don't look :) */ | ||
618 | |||
619 | /* deflateInit and inflateInit are macros to allow checking the zlib version | ||
620 | * and the compiler's view of z_stream: | ||
621 | */ | ||
622 | extern int zlib_deflateInit_ (z_streamp strm, int level, | ||
623 | const char *version, int stream_size); | ||
624 | extern int zlib_inflateInit_ (z_streamp strm, | ||
625 | const char *version, int stream_size); | ||
626 | extern int zlib_deflateInit2_ (z_streamp strm, int level, int method, | ||
627 | int windowBits, int memLevel, | ||
628 | int strategy, const char *version, | ||
629 | int stream_size); | ||
630 | extern int zlib_inflateInit2_ (z_streamp strm, int windowBits, | ||
631 | const char *version, int stream_size); | ||
632 | #define zlib_deflateInit(strm, level) \ | 687 | #define zlib_deflateInit(strm, level) \ |
633 | zlib_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) | 688 | zlib_deflateInit2((strm), (level), Z_DEFLATED, MAX_WBITS, \ |
689 | DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY) | ||
634 | #define zlib_inflateInit(strm) \ | 690 | #define zlib_inflateInit(strm) \ |
635 | zlib_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) | 691 | zlib_inflateInit2((strm), DEF_WBITS) |
636 | #define zlib_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ | ||
637 | zlib_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ | ||
638 | (strategy), ZLIB_VERSION, sizeof(z_stream)) | ||
639 | #define zlib_inflateInit2(strm, windowBits) \ | ||
640 | zlib_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) | ||
641 | 692 | ||
693 | extern int zlib_deflateInit2(z_streamp strm, int level, int method, | ||
694 | int windowBits, int memLevel, | ||
695 | int strategy); | ||
696 | extern int zlib_inflateInit2(z_streamp strm, int windowBits); | ||
642 | 697 | ||
643 | #if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) | 698 | #if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) |
644 | struct internal_state {int dummy;}; /* hack for buggy compilers */ | 699 | struct internal_state {int dummy;}; /* hack for buggy compilers */ |
645 | #endif | 700 | #endif |
646 | 701 | ||
647 | extern const char * zlib_zError (int err); | ||
648 | #if 0 | ||
649 | extern int zlib_inflateSyncPoint (z_streamp z); | ||
650 | #endif | ||
651 | extern const uLong * zlib_get_crc_table (void); | ||
652 | |||
653 | #endif /* _ZLIB_H */ | 702 | #endif /* _ZLIB_H */ |
diff --git a/include/linux/zutil.h b/include/linux/zutil.h index ee0c59cf2136..6adfa9a6ffe9 100644 --- a/include/linux/zutil.h +++ b/include/linux/zutil.h | |||
@@ -23,18 +23,6 @@ typedef unsigned long ulg; | |||
23 | 23 | ||
24 | /* common constants */ | 24 | /* common constants */ |
25 | 25 | ||
26 | #ifndef DEF_WBITS | ||
27 | # define DEF_WBITS MAX_WBITS | ||
28 | #endif | ||
29 | /* default windowBits for decompression. MAX_WBITS is for compression only */ | ||
30 | |||
31 | #if MAX_MEM_LEVEL >= 8 | ||
32 | # define DEF_MEM_LEVEL 8 | ||
33 | #else | ||
34 | # define DEF_MEM_LEVEL MAX_MEM_LEVEL | ||
35 | #endif | ||
36 | /* default memLevel */ | ||
37 | |||
38 | #define STORED_BLOCK 0 | 26 | #define STORED_BLOCK 0 |
39 | #define STATIC_TREES 1 | 27 | #define STATIC_TREES 1 |
40 | #define DYN_TREES 2 | 28 | #define DYN_TREES 2 |
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index b45a73712748..446afc3ea27f 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h | |||
@@ -378,6 +378,7 @@ | |||
378 | #define AC97_HAS_NO_MIC (1<<15) /* no MIC volume */ | 378 | #define AC97_HAS_NO_MIC (1<<15) /* no MIC volume */ |
379 | #define AC97_HAS_NO_TONE (1<<16) /* no Tone volume */ | 379 | #define AC97_HAS_NO_TONE (1<<16) /* no Tone volume */ |
380 | #define AC97_HAS_NO_STD_PCM (1<<17) /* no standard AC97 PCM volume and mute */ | 380 | #define AC97_HAS_NO_STD_PCM (1<<17) /* no standard AC97 PCM volume and mute */ |
381 | #define AC97_HAS_NO_AUX (1<<18) /* no standard AC97 AUX volume and mute */ | ||
381 | 382 | ||
382 | /* rates indexes */ | 383 | /* rates indexes */ |
383 | #define AC97_RATES_FRONT_DAC 0 | 384 | #define AC97_RATES_FRONT_DAC 0 |
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h index 6691e4aa4ea7..3f2f4042a20d 100644 --- a/include/sound/asequencer.h +++ b/include/sound/asequencer.h | |||
@@ -605,6 +605,10 @@ struct snd_seq_remove_events { | |||
605 | #define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */ | 605 | #define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11) /* Sampling device (support sample download) */ |
606 | #define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */ | 606 | #define SNDRV_SEQ_PORT_TYPE_SAMPLE (1<<12) /* Sampling device (sample can be downloaded at any time) */ |
607 | /*...*/ | 607 | /*...*/ |
608 | #define SNDRV_SEQ_PORT_TYPE_HARDWARE (1<<16) /* driver for a hardware device */ | ||
609 | #define SNDRV_SEQ_PORT_TYPE_SOFTWARE (1<<17) /* implemented in software */ | ||
610 | #define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER (1<<18) /* generates sound */ | ||
611 | #define SNDRV_SEQ_PORT_TYPE_PORT (1<<19) /* connects to other device(s) */ | ||
608 | #define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */ | 612 | #define SNDRV_SEQ_PORT_TYPE_APPLICATION (1<<20) /* application (sequencer/editor) */ |
609 | 613 | ||
610 | /* misc. conditioning flags */ | 614 | /* misc. conditioning flags */ |
diff --git a/include/sound/asound.h b/include/sound/asound.h index 9cc021c7ee11..41885f48ad91 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h | |||
@@ -137,7 +137,7 @@ enum { | |||
137 | * * | 137 | * * |
138 | *****************************************************************************/ | 138 | *****************************************************************************/ |
139 | 139 | ||
140 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 7) | 140 | #define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 8) |
141 | 141 | ||
142 | typedef unsigned long snd_pcm_uframes_t; | 142 | typedef unsigned long snd_pcm_uframes_t; |
143 | typedef signed long snd_pcm_sframes_t; | 143 | typedef signed long snd_pcm_sframes_t; |
diff --git a/include/sound/core.h b/include/sound/core.h index 5135147f20e8..5d184be0ff72 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
@@ -233,9 +233,8 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size | |||
233 | 233 | ||
234 | /* init.c */ | 234 | /* init.c */ |
235 | 235 | ||
236 | extern unsigned int snd_cards_lock; | ||
237 | extern struct snd_card *snd_cards[SNDRV_CARDS]; | 236 | extern struct snd_card *snd_cards[SNDRV_CARDS]; |
238 | extern rwlock_t snd_card_rwlock; | 237 | int snd_card_locked(int card); |
239 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 238 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) |
240 | #define SND_MIXER_OSS_NOTIFY_REGISTER 0 | 239 | #define SND_MIXER_OSS_NOTIFY_REGISTER 0 |
241 | #define SND_MIXER_OSS_NOTIFY_DISCONNECT 1 | 240 | #define SND_MIXER_OSS_NOTIFY_DISCONNECT 1 |
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 186e00ad9e79..884bbf54cd36 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h | |||
@@ -245,6 +245,7 @@ | |||
245 | #define A_IOCFG_GPOUT0 0x0044 /* analog/digital */ | 245 | #define A_IOCFG_GPOUT0 0x0044 /* analog/digital */ |
246 | #define A_IOCFG_DISABLE_ANALOG 0x0040 /* = 'enable' for Audigy2 (chiprev=4) */ | 246 | #define A_IOCFG_DISABLE_ANALOG 0x0040 /* = 'enable' for Audigy2 (chiprev=4) */ |
247 | #define A_IOCFG_ENABLE_DIGITAL 0x0004 | 247 | #define A_IOCFG_ENABLE_DIGITAL 0x0004 |
248 | #define A_IOCFG_ENABLE_DIGITAL_AUDIGY4 0x0080 | ||
248 | #define A_IOCFG_UNKNOWN_20 0x0020 | 249 | #define A_IOCFG_UNKNOWN_20 0x0020 |
249 | #define A_IOCFG_DISABLE_AC97_FRONT 0x0080 /* turn off ac97 front -> front (10k2.1) */ | 250 | #define A_IOCFG_DISABLE_AC97_FRONT 0x0080 /* turn off ac97 front -> front (10k2.1) */ |
250 | #define A_IOCFG_GPOUT1 0x0002 /* IR? drive's internal bypass (?) */ | 251 | #define A_IOCFG_GPOUT1 0x0002 /* IR? drive's internal bypass (?) */ |
@@ -1065,6 +1066,7 @@ struct snd_emu_chip_details { | |||
1065 | unsigned char emu1212m; /* EMU 1212m card */ | 1066 | unsigned char emu1212m; /* EMU 1212m card */ |
1066 | unsigned char spi_dac; /* SPI interface for DAC */ | 1067 | unsigned char spi_dac; /* SPI interface for DAC */ |
1067 | unsigned char i2c_adc; /* I2C interface for ADC */ | 1068 | unsigned char i2c_adc; /* I2C interface for ADC */ |
1069 | unsigned char adc_1361t; /* Use Philips 1361T ADC */ | ||
1068 | const char *driver; | 1070 | const char *driver; |
1069 | const char *name; | 1071 | const char *name; |
1070 | const char *id; /* for backward compatibility - can be NULL if not needed */ | 1072 | const char *id; /* for backward compatibility - can be NULL if not needed */ |
diff --git a/include/sound/info.h b/include/sound/info.h index f23d8381c216..74f6996769c7 100644 --- a/include/sound/info.h +++ b/include/sound/info.h | |||
@@ -27,9 +27,9 @@ | |||
27 | /* buffer for information */ | 27 | /* buffer for information */ |
28 | struct snd_info_buffer { | 28 | struct snd_info_buffer { |
29 | char *buffer; /* pointer to begin of buffer */ | 29 | char *buffer; /* pointer to begin of buffer */ |
30 | char *curr; /* current position in buffer */ | 30 | unsigned int curr; /* current position in buffer */ |
31 | unsigned long size; /* current size */ | 31 | unsigned int size; /* current size */ |
32 | unsigned long len; /* total length of buffer */ | 32 | unsigned int len; /* total length of buffer */ |
33 | int stop; /* stop flag */ | 33 | int stop; /* stop flag */ |
34 | int error; /* error code */ | 34 | int error; /* error code */ |
35 | }; | 35 | }; |
@@ -40,8 +40,6 @@ struct snd_info_buffer { | |||
40 | struct snd_info_entry; | 40 | struct snd_info_entry; |
41 | 41 | ||
42 | struct snd_info_entry_text { | 42 | struct snd_info_entry_text { |
43 | unsigned long read_size; | ||
44 | unsigned long write_size; | ||
45 | void (*read) (struct snd_info_entry *entry, struct snd_info_buffer *buffer); | 43 | void (*read) (struct snd_info_entry *entry, struct snd_info_buffer *buffer); |
46 | void (*write) (struct snd_info_entry *entry, struct snd_info_buffer *buffer); | 44 | void (*write) (struct snd_info_entry *entry, struct snd_info_buffer *buffer); |
47 | }; | 45 | }; |
@@ -132,11 +130,9 @@ int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_e | |||
132 | 130 | ||
133 | static inline void snd_info_set_text_ops(struct snd_info_entry *entry, | 131 | static inline void snd_info_set_text_ops(struct snd_info_entry *entry, |
134 | void *private_data, | 132 | void *private_data, |
135 | long read_size, | ||
136 | void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) | 133 | void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) |
137 | { | 134 | { |
138 | entry->private_data = private_data; | 135 | entry->private_data = private_data; |
139 | entry->c.text.read_size = read_size; | ||
140 | entry->c.text.read = read; | 136 | entry->c.text.read = read; |
141 | } | 137 | } |
142 | 138 | ||
@@ -167,7 +163,6 @@ static inline int snd_card_proc_new(struct snd_card *card, const char *name, | |||
167 | struct snd_info_entry **entryp) { return -EINVAL; } | 163 | struct snd_info_entry **entryp) { return -EINVAL; } |
168 | static inline void snd_info_set_text_ops(struct snd_info_entry *entry __attribute__((unused)), | 164 | static inline void snd_info_set_text_ops(struct snd_info_entry *entry __attribute__((unused)), |
169 | void *private_data, | 165 | void *private_data, |
170 | long read_size, | ||
171 | void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) {} | 166 | void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) {} |
172 | 167 | ||
173 | static inline int snd_info_check_reserved_words(const char *str) { return 1; } | 168 | static inline int snd_info_check_reserved_words(const char *str) { return 1; } |
diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h index 8e97ace78f16..ac504321ea56 100644 --- a/include/sound/mpu401.h +++ b/include/sound/mpu401.h | |||
@@ -45,6 +45,12 @@ | |||
45 | #define MPU401_HW_PC98II 18 /* Roland PC98II */ | 45 | #define MPU401_HW_PC98II 18 /* Roland PC98II */ |
46 | #define MPU401_HW_AUREAL 19 /* Aureal Vortex */ | 46 | #define MPU401_HW_AUREAL 19 /* Aureal Vortex */ |
47 | 47 | ||
48 | #define MPU401_INFO_INPUT (1 << 0) /* input stream */ | ||
49 | #define MPU401_INFO_OUTPUT (1 << 1) /* output stream */ | ||
50 | #define MPU401_INFO_INTEGRATED (1 << 2) /* integrated h/w port */ | ||
51 | #define MPU401_INFO_MMIO (1 << 3) /* MMIO access */ | ||
52 | #define MPU401_INFO_TX_IRQ (1 << 4) /* independent TX irq */ | ||
53 | |||
48 | #define MPU401_MODE_BIT_INPUT 0 | 54 | #define MPU401_MODE_BIT_INPUT 0 |
49 | #define MPU401_MODE_BIT_OUTPUT 1 | 55 | #define MPU401_MODE_BIT_OUTPUT 1 |
50 | #define MPU401_MODE_BIT_INPUT_TRIGGER 2 | 56 | #define MPU401_MODE_BIT_INPUT_TRIGGER 2 |
@@ -62,6 +68,7 @@ struct snd_mpu401 { | |||
62 | struct snd_rawmidi *rmidi; | 68 | struct snd_rawmidi *rmidi; |
63 | 69 | ||
64 | unsigned short hardware; /* MPU401_HW_XXXX */ | 70 | unsigned short hardware; /* MPU401_HW_XXXX */ |
71 | unsigned int info_flags; /* MPU401_INFO_XXX */ | ||
65 | unsigned long port; /* base port of MPU-401 chip */ | 72 | unsigned long port; /* base port of MPU-401 chip */ |
66 | unsigned long cport; /* port + 1 (usually) */ | 73 | unsigned long cport; /* port + 1 (usually) */ |
67 | struct resource *res; /* port resource */ | 74 | struct resource *res; /* port resource */ |
@@ -99,13 +106,16 @@ struct snd_mpu401 { | |||
99 | 106 | ||
100 | */ | 107 | */ |
101 | 108 | ||
102 | irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 109 | irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, |
110 | struct pt_regs *regs); | ||
111 | irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id, | ||
112 | struct pt_regs *regs); | ||
103 | 113 | ||
104 | int snd_mpu401_uart_new(struct snd_card *card, | 114 | int snd_mpu401_uart_new(struct snd_card *card, |
105 | int device, | 115 | int device, |
106 | unsigned short hardware, | 116 | unsigned short hardware, |
107 | unsigned long port, | 117 | unsigned long port, |
108 | int integrated, | 118 | unsigned int info_flags, |
109 | int irq, | 119 | int irq, |
110 | int irq_flags, | 120 | int irq_flags, |
111 | struct snd_rawmidi ** rrawmidi); | 121 | struct snd_rawmidi ** rrawmidi); |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 373425895faa..f84d84993a31 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -300,7 +300,6 @@ struct snd_pcm_runtime { | |||
300 | /* -- mmap -- */ | 300 | /* -- mmap -- */ |
301 | volatile struct snd_pcm_mmap_status *status; | 301 | volatile struct snd_pcm_mmap_status *status; |
302 | volatile struct snd_pcm_mmap_control *control; | 302 | volatile struct snd_pcm_mmap_control *control; |
303 | atomic_t mmap_count; | ||
304 | 303 | ||
305 | /* -- locking / scheduling -- */ | 304 | /* -- locking / scheduling -- */ |
306 | wait_queue_head_t sleep; | 305 | wait_queue_head_t sleep; |
@@ -368,7 +367,9 @@ struct snd_pcm_substream { | |||
368 | struct snd_pcm_group *group; /* pointer to current group */ | 367 | struct snd_pcm_group *group; /* pointer to current group */ |
369 | /* -- assigned files -- */ | 368 | /* -- assigned files -- */ |
370 | void *file; | 369 | void *file; |
371 | struct file *ffile; | 370 | int ref_count; |
371 | atomic_t mmap_count; | ||
372 | unsigned int f_flags; | ||
372 | void (*pcm_release)(struct snd_pcm_substream *); | 373 | void (*pcm_release)(struct snd_pcm_substream *); |
373 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 374 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
374 | /* -- OSS things -- */ | 375 | /* -- OSS things -- */ |
@@ -387,7 +388,7 @@ struct snd_pcm_substream { | |||
387 | unsigned int hw_opened: 1; | 388 | unsigned int hw_opened: 1; |
388 | }; | 389 | }; |
389 | 390 | ||
390 | #define SUBSTREAM_BUSY(substream) ((substream)->file != NULL) | 391 | #define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) |
391 | 392 | ||
392 | 393 | ||
393 | struct snd_pcm_str { | 394 | struct snd_pcm_str { |
@@ -825,14 +826,6 @@ int snd_interval_ratnum(struct snd_interval *i, | |||
825 | 826 | ||
826 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); | 827 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params); |
827 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); | 828 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var); |
828 | int snd_pcm_hw_param_near(struct snd_pcm_substream *substream, | ||
829 | struct snd_pcm_hw_params *params, | ||
830 | snd_pcm_hw_param_t var, | ||
831 | unsigned int val, int *dir); | ||
832 | int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, | ||
833 | struct snd_pcm_hw_params *params, | ||
834 | snd_pcm_hw_param_t var, | ||
835 | unsigned int val, int dir); | ||
836 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); | 829 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); |
837 | 830 | ||
838 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); | 831 | int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); |
@@ -979,13 +972,13 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne | |||
979 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) | 972 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) |
980 | { | 973 | { |
981 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; | 974 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; |
982 | atomic_inc(&substream->runtime->mmap_count); | 975 | atomic_inc(&substream->mmap_count); |
983 | } | 976 | } |
984 | 977 | ||
985 | static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) | 978 | static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) |
986 | { | 979 | { |
987 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; | 980 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; |
988 | atomic_dec(&substream->runtime->mmap_count); | 981 | atomic_dec(&substream->mmap_count); |
989 | } | 982 | } |
990 | 983 | ||
991 | /* mmap for io-memory area */ | 984 | /* mmap for io-memory area */ |
diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index fb18aef77341..85cf1cf4f31a 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h | |||
@@ -22,29 +22,21 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | extern int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, | 25 | int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, |
26 | snd_pcm_hw_param_t var, const struct snd_mask *val); | 26 | struct snd_pcm_hw_params *params, |
27 | extern unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, | 27 | snd_pcm_hw_param_t var, int *dir); |
28 | snd_pcm_hw_param_t var, int *dir); | 28 | int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, |
29 | extern unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, | 29 | struct snd_pcm_hw_params *params, |
30 | snd_pcm_hw_param_t var, int *dir); | 30 | snd_pcm_hw_param_t var, int *dir); |
31 | extern int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, | 31 | int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, |
32 | snd_pcm_hw_param_t var, unsigned int val, int dir); | 32 | snd_pcm_hw_param_t var, int *dir); |
33 | extern int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, | ||
34 | snd_pcm_hw_param_t var); | ||
35 | extern int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, | ||
36 | snd_pcm_hw_param_t var, unsigned int val, int dir); | ||
37 | |||
38 | /* To share the same code we have alsa-lib */ | ||
39 | #define INLINE static inline | ||
40 | #define assert(a) (void)(a) | ||
41 | 33 | ||
42 | #define SNDRV_MASK_BITS 64 /* we use so far 64bits only */ | 34 | #define SNDRV_MASK_BITS 64 /* we use so far 64bits only */ |
43 | #define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32) | 35 | #define SNDRV_MASK_SIZE (SNDRV_MASK_BITS / 32) |
44 | #define MASK_OFS(i) ((i) >> 5) | 36 | #define MASK_OFS(i) ((i) >> 5) |
45 | #define MASK_BIT(i) (1U << ((i) & 31)) | 37 | #define MASK_BIT(i) (1U << ((i) & 31)) |
46 | 38 | ||
47 | INLINE unsigned int ld2(u_int32_t v) | 39 | static inline unsigned int ld2(u_int32_t v) |
48 | { | 40 | { |
49 | unsigned r = 0; | 41 | unsigned r = 0; |
50 | 42 | ||
@@ -69,22 +61,22 @@ INLINE unsigned int ld2(u_int32_t v) | |||
69 | return r; | 61 | return r; |
70 | } | 62 | } |
71 | 63 | ||
72 | INLINE size_t snd_mask_sizeof(void) | 64 | static inline size_t snd_mask_sizeof(void) |
73 | { | 65 | { |
74 | return sizeof(struct snd_mask); | 66 | return sizeof(struct snd_mask); |
75 | } | 67 | } |
76 | 68 | ||
77 | INLINE void snd_mask_none(struct snd_mask *mask) | 69 | static inline void snd_mask_none(struct snd_mask *mask) |
78 | { | 70 | { |
79 | memset(mask, 0, sizeof(*mask)); | 71 | memset(mask, 0, sizeof(*mask)); |
80 | } | 72 | } |
81 | 73 | ||
82 | INLINE void snd_mask_any(struct snd_mask *mask) | 74 | static inline void snd_mask_any(struct snd_mask *mask) |
83 | { | 75 | { |
84 | memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t)); | 76 | memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t)); |
85 | } | 77 | } |
86 | 78 | ||
87 | INLINE int snd_mask_empty(const struct snd_mask *mask) | 79 | static inline int snd_mask_empty(const struct snd_mask *mask) |
88 | { | 80 | { |
89 | int i; | 81 | int i; |
90 | for (i = 0; i < SNDRV_MASK_SIZE; i++) | 82 | for (i = 0; i < SNDRV_MASK_SIZE; i++) |
@@ -93,10 +85,9 @@ INLINE int snd_mask_empty(const struct snd_mask *mask) | |||
93 | return 1; | 85 | return 1; |
94 | } | 86 | } |
95 | 87 | ||
96 | INLINE unsigned int snd_mask_min(const struct snd_mask *mask) | 88 | static inline unsigned int snd_mask_min(const struct snd_mask *mask) |
97 | { | 89 | { |
98 | int i; | 90 | int i; |
99 | assert(!snd_mask_empty(mask)); | ||
100 | for (i = 0; i < SNDRV_MASK_SIZE; i++) { | 91 | for (i = 0; i < SNDRV_MASK_SIZE; i++) { |
101 | if (mask->bits[i]) | 92 | if (mask->bits[i]) |
102 | return ffs(mask->bits[i]) - 1 + (i << 5); | 93 | return ffs(mask->bits[i]) - 1 + (i << 5); |
@@ -104,10 +95,9 @@ INLINE unsigned int snd_mask_min(const struct snd_mask *mask) | |||
104 | return 0; | 95 | return 0; |
105 | } | 96 | } |
106 | 97 | ||
107 | INLINE unsigned int snd_mask_max(const struct snd_mask *mask) | 98 | static inline unsigned int snd_mask_max(const struct snd_mask *mask) |
108 | { | 99 | { |
109 | int i; | 100 | int i; |
110 | assert(!snd_mask_empty(mask)); | ||
111 | for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) { | 101 | for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) { |
112 | if (mask->bits[i]) | 102 | if (mask->bits[i]) |
113 | return ld2(mask->bits[i]) + (i << 5); | 103 | return ld2(mask->bits[i]) + (i << 5); |
@@ -115,70 +105,68 @@ INLINE unsigned int snd_mask_max(const struct snd_mask *mask) | |||
115 | return 0; | 105 | return 0; |
116 | } | 106 | } |
117 | 107 | ||
118 | INLINE void snd_mask_set(struct snd_mask *mask, unsigned int val) | 108 | static inline void snd_mask_set(struct snd_mask *mask, unsigned int val) |
119 | { | 109 | { |
120 | assert(val <= SNDRV_MASK_BITS); | ||
121 | mask->bits[MASK_OFS(val)] |= MASK_BIT(val); | 110 | mask->bits[MASK_OFS(val)] |= MASK_BIT(val); |
122 | } | 111 | } |
123 | 112 | ||
124 | INLINE void snd_mask_reset(struct snd_mask *mask, unsigned int val) | 113 | static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val) |
125 | { | 114 | { |
126 | assert(val <= SNDRV_MASK_BITS); | ||
127 | mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val); | 115 | mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val); |
128 | } | 116 | } |
129 | 117 | ||
130 | INLINE void snd_mask_set_range(struct snd_mask *mask, unsigned int from, unsigned int to) | 118 | static inline void snd_mask_set_range(struct snd_mask *mask, |
119 | unsigned int from, unsigned int to) | ||
131 | { | 120 | { |
132 | unsigned int i; | 121 | unsigned int i; |
133 | assert(to <= SNDRV_MASK_BITS && from <= to); | ||
134 | for (i = from; i <= to; i++) | 122 | for (i = from; i <= to; i++) |
135 | mask->bits[MASK_OFS(i)] |= MASK_BIT(i); | 123 | mask->bits[MASK_OFS(i)] |= MASK_BIT(i); |
136 | } | 124 | } |
137 | 125 | ||
138 | INLINE void snd_mask_reset_range(struct snd_mask *mask, unsigned int from, unsigned int to) | 126 | static inline void snd_mask_reset_range(struct snd_mask *mask, |
127 | unsigned int from, unsigned int to) | ||
139 | { | 128 | { |
140 | unsigned int i; | 129 | unsigned int i; |
141 | assert(to <= SNDRV_MASK_BITS && from <= to); | ||
142 | for (i = from; i <= to; i++) | 130 | for (i = from; i <= to; i++) |
143 | mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i); | 131 | mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i); |
144 | } | 132 | } |
145 | 133 | ||
146 | INLINE void snd_mask_leave(struct snd_mask *mask, unsigned int val) | 134 | static inline void snd_mask_leave(struct snd_mask *mask, unsigned int val) |
147 | { | 135 | { |
148 | unsigned int v; | 136 | unsigned int v; |
149 | assert(val <= SNDRV_MASK_BITS); | ||
150 | v = mask->bits[MASK_OFS(val)] & MASK_BIT(val); | 137 | v = mask->bits[MASK_OFS(val)] & MASK_BIT(val); |
151 | snd_mask_none(mask); | 138 | snd_mask_none(mask); |
152 | mask->bits[MASK_OFS(val)] = v; | 139 | mask->bits[MASK_OFS(val)] = v; |
153 | } | 140 | } |
154 | 141 | ||
155 | INLINE void snd_mask_intersect(struct snd_mask *mask, const struct snd_mask *v) | 142 | static inline void snd_mask_intersect(struct snd_mask *mask, |
143 | const struct snd_mask *v) | ||
156 | { | 144 | { |
157 | int i; | 145 | int i; |
158 | for (i = 0; i < SNDRV_MASK_SIZE; i++) | 146 | for (i = 0; i < SNDRV_MASK_SIZE; i++) |
159 | mask->bits[i] &= v->bits[i]; | 147 | mask->bits[i] &= v->bits[i]; |
160 | } | 148 | } |
161 | 149 | ||
162 | INLINE int snd_mask_eq(const struct snd_mask *mask, const struct snd_mask *v) | 150 | static inline int snd_mask_eq(const struct snd_mask *mask, |
151 | const struct snd_mask *v) | ||
163 | { | 152 | { |
164 | return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t)); | 153 | return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t)); |
165 | } | 154 | } |
166 | 155 | ||
167 | INLINE void snd_mask_copy(struct snd_mask *mask, const struct snd_mask *v) | 156 | static inline void snd_mask_copy(struct snd_mask *mask, |
157 | const struct snd_mask *v) | ||
168 | { | 158 | { |
169 | *mask = *v; | 159 | *mask = *v; |
170 | } | 160 | } |
171 | 161 | ||
172 | INLINE int snd_mask_test(const struct snd_mask *mask, unsigned int val) | 162 | static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val) |
173 | { | 163 | { |
174 | assert(val <= SNDRV_MASK_BITS); | ||
175 | return mask->bits[MASK_OFS(val)] & MASK_BIT(val); | 164 | return mask->bits[MASK_OFS(val)] & MASK_BIT(val); |
176 | } | 165 | } |
177 | 166 | ||
178 | INLINE int snd_mask_single(const struct snd_mask *mask) | 167 | static inline int snd_mask_single(const struct snd_mask *mask) |
179 | { | 168 | { |
180 | int i, c = 0; | 169 | int i, c = 0; |
181 | assert(!snd_mask_empty(mask)); | ||
182 | for (i = 0; i < SNDRV_MASK_SIZE; i++) { | 170 | for (i = 0; i < SNDRV_MASK_SIZE; i++) { |
183 | if (! mask->bits[i]) | 171 | if (! mask->bits[i]) |
184 | continue; | 172 | continue; |
@@ -191,10 +179,10 @@ INLINE int snd_mask_single(const struct snd_mask *mask) | |||
191 | return 1; | 179 | return 1; |
192 | } | 180 | } |
193 | 181 | ||
194 | INLINE int snd_mask_refine(struct snd_mask *mask, const struct snd_mask *v) | 182 | static inline int snd_mask_refine(struct snd_mask *mask, |
183 | const struct snd_mask *v) | ||
195 | { | 184 | { |
196 | struct snd_mask old; | 185 | struct snd_mask old; |
197 | assert(!snd_mask_empty(mask)); | ||
198 | snd_mask_copy(&old, mask); | 186 | snd_mask_copy(&old, mask); |
199 | snd_mask_intersect(mask, v); | 187 | snd_mask_intersect(mask, v); |
200 | if (snd_mask_empty(mask)) | 188 | if (snd_mask_empty(mask)) |
@@ -202,27 +190,24 @@ INLINE int snd_mask_refine(struct snd_mask *mask, const struct snd_mask *v) | |||
202 | return !snd_mask_eq(mask, &old); | 190 | return !snd_mask_eq(mask, &old); |
203 | } | 191 | } |
204 | 192 | ||
205 | INLINE int snd_mask_refine_first(struct snd_mask *mask) | 193 | static inline int snd_mask_refine_first(struct snd_mask *mask) |
206 | { | 194 | { |
207 | assert(!snd_mask_empty(mask)); | ||
208 | if (snd_mask_single(mask)) | 195 | if (snd_mask_single(mask)) |
209 | return 0; | 196 | return 0; |
210 | snd_mask_leave(mask, snd_mask_min(mask)); | 197 | snd_mask_leave(mask, snd_mask_min(mask)); |
211 | return 1; | 198 | return 1; |
212 | } | 199 | } |
213 | 200 | ||
214 | INLINE int snd_mask_refine_last(struct snd_mask *mask) | 201 | static inline int snd_mask_refine_last(struct snd_mask *mask) |
215 | { | 202 | { |
216 | assert(!snd_mask_empty(mask)); | ||
217 | if (snd_mask_single(mask)) | 203 | if (snd_mask_single(mask)) |
218 | return 0; | 204 | return 0; |
219 | snd_mask_leave(mask, snd_mask_max(mask)); | 205 | snd_mask_leave(mask, snd_mask_max(mask)); |
220 | return 1; | 206 | return 1; |
221 | } | 207 | } |
222 | 208 | ||
223 | INLINE int snd_mask_refine_min(struct snd_mask *mask, unsigned int val) | 209 | static inline int snd_mask_refine_min(struct snd_mask *mask, unsigned int val) |
224 | { | 210 | { |
225 | assert(!snd_mask_empty(mask)); | ||
226 | if (snd_mask_min(mask) >= val) | 211 | if (snd_mask_min(mask) >= val) |
227 | return 0; | 212 | return 0; |
228 | snd_mask_reset_range(mask, 0, val - 1); | 213 | snd_mask_reset_range(mask, 0, val - 1); |
@@ -231,9 +216,8 @@ INLINE int snd_mask_refine_min(struct snd_mask *mask, unsigned int val) | |||
231 | return 1; | 216 | return 1; |
232 | } | 217 | } |
233 | 218 | ||
234 | INLINE int snd_mask_refine_max(struct snd_mask *mask, unsigned int val) | 219 | static inline int snd_mask_refine_max(struct snd_mask *mask, unsigned int val) |
235 | { | 220 | { |
236 | assert(!snd_mask_empty(mask)); | ||
237 | if (snd_mask_max(mask) <= val) | 221 | if (snd_mask_max(mask) <= val) |
238 | return 0; | 222 | return 0; |
239 | snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS); | 223 | snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS); |
@@ -242,10 +226,9 @@ INLINE int snd_mask_refine_max(struct snd_mask *mask, unsigned int val) | |||
242 | return 1; | 226 | return 1; |
243 | } | 227 | } |
244 | 228 | ||
245 | INLINE int snd_mask_refine_set(struct snd_mask *mask, unsigned int val) | 229 | static inline int snd_mask_refine_set(struct snd_mask *mask, unsigned int val) |
246 | { | 230 | { |
247 | int changed; | 231 | int changed; |
248 | assert(!snd_mask_empty(mask)); | ||
249 | changed = !snd_mask_single(mask); | 232 | changed = !snd_mask_single(mask); |
250 | snd_mask_leave(mask, val); | 233 | snd_mask_leave(mask, val); |
251 | if (snd_mask_empty(mask)) | 234 | if (snd_mask_empty(mask)) |
@@ -253,13 +236,12 @@ INLINE int snd_mask_refine_set(struct snd_mask *mask, unsigned int val) | |||
253 | return changed; | 236 | return changed; |
254 | } | 237 | } |
255 | 238 | ||
256 | INLINE int snd_mask_value(const struct snd_mask *mask) | 239 | static inline int snd_mask_value(const struct snd_mask *mask) |
257 | { | 240 | { |
258 | assert(!snd_mask_empty(mask)); | ||
259 | return snd_mask_min(mask); | 241 | return snd_mask_min(mask); |
260 | } | 242 | } |
261 | 243 | ||
262 | INLINE void snd_interval_any(struct snd_interval *i) | 244 | static inline void snd_interval_any(struct snd_interval *i) |
263 | { | 245 | { |
264 | i->min = 0; | 246 | i->min = 0; |
265 | i->openmin = 0; | 247 | i->openmin = 0; |
@@ -269,63 +251,59 @@ INLINE void snd_interval_any(struct snd_interval *i) | |||
269 | i->empty = 0; | 251 | i->empty = 0; |
270 | } | 252 | } |
271 | 253 | ||
272 | INLINE void snd_interval_none(struct snd_interval *i) | 254 | static inline void snd_interval_none(struct snd_interval *i) |
273 | { | 255 | { |
274 | i->empty = 1; | 256 | i->empty = 1; |
275 | } | 257 | } |
276 | 258 | ||
277 | INLINE int snd_interval_checkempty(const struct snd_interval *i) | 259 | static inline int snd_interval_checkempty(const struct snd_interval *i) |
278 | { | 260 | { |
279 | return (i->min > i->max || | 261 | return (i->min > i->max || |
280 | (i->min == i->max && (i->openmin || i->openmax))); | 262 | (i->min == i->max && (i->openmin || i->openmax))); |
281 | } | 263 | } |
282 | 264 | ||
283 | INLINE int snd_interval_empty(const struct snd_interval *i) | 265 | static inline int snd_interval_empty(const struct snd_interval *i) |
284 | { | 266 | { |
285 | return i->empty; | 267 | return i->empty; |
286 | } | 268 | } |
287 | 269 | ||
288 | INLINE int snd_interval_single(const struct snd_interval *i) | 270 | static inline int snd_interval_single(const struct snd_interval *i) |
289 | { | 271 | { |
290 | assert(!snd_interval_empty(i)); | ||
291 | return (i->min == i->max || | 272 | return (i->min == i->max || |
292 | (i->min + 1 == i->max && i->openmax)); | 273 | (i->min + 1 == i->max && i->openmax)); |
293 | } | 274 | } |
294 | 275 | ||
295 | INLINE int snd_interval_value(const struct snd_interval *i) | 276 | static inline int snd_interval_value(const struct snd_interval *i) |
296 | { | 277 | { |
297 | assert(snd_interval_single(i)); | ||
298 | return i->min; | 278 | return i->min; |
299 | } | 279 | } |
300 | 280 | ||
301 | INLINE int snd_interval_min(const struct snd_interval *i) | 281 | static inline int snd_interval_min(const struct snd_interval *i) |
302 | { | 282 | { |
303 | assert(!snd_interval_empty(i)); | ||
304 | return i->min; | 283 | return i->min; |
305 | } | 284 | } |
306 | 285 | ||
307 | INLINE int snd_interval_max(const struct snd_interval *i) | 286 | static inline int snd_interval_max(const struct snd_interval *i) |
308 | { | 287 | { |
309 | unsigned int v; | 288 | unsigned int v; |
310 | assert(!snd_interval_empty(i)); | ||
311 | v = i->max; | 289 | v = i->max; |
312 | if (i->openmax) | 290 | if (i->openmax) |
313 | v--; | 291 | v--; |
314 | return v; | 292 | return v; |
315 | } | 293 | } |
316 | 294 | ||
317 | INLINE int snd_interval_test(const struct snd_interval *i, unsigned int val) | 295 | static inline int snd_interval_test(const struct snd_interval *i, unsigned int val) |
318 | { | 296 | { |
319 | return !((i->min > val || (i->min == val && i->openmin) || | 297 | return !((i->min > val || (i->min == val && i->openmin) || |
320 | i->max < val || (i->max == val && i->openmax))); | 298 | i->max < val || (i->max == val && i->openmax))); |
321 | } | 299 | } |
322 | 300 | ||
323 | INLINE void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s) | 301 | static inline void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s) |
324 | { | 302 | { |
325 | *d = *s; | 303 | *d = *s; |
326 | } | 304 | } |
327 | 305 | ||
328 | INLINE int snd_interval_setinteger(struct snd_interval *i) | 306 | static inline int snd_interval_setinteger(struct snd_interval *i) |
329 | { | 307 | { |
330 | if (i->integer) | 308 | if (i->integer) |
331 | return 0; | 309 | return 0; |
@@ -335,7 +313,7 @@ INLINE int snd_interval_setinteger(struct snd_interval *i) | |||
335 | return 1; | 313 | return 1; |
336 | } | 314 | } |
337 | 315 | ||
338 | INLINE int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2) | 316 | static inline int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2) |
339 | { | 317 | { |
340 | if (i1->empty) | 318 | if (i1->empty) |
341 | return i2->empty; | 319 | return i2->empty; |
@@ -359,8 +337,5 @@ static inline unsigned int sub(unsigned int a, unsigned int b) | |||
359 | return 0; | 337 | return 0; |
360 | } | 338 | } |
361 | 339 | ||
362 | #undef INLINE | ||
363 | #undef assert | ||
364 | |||
365 | #endif /* __SOUND_PCM_PARAMS_H */ | 340 | #endif /* __SOUND_PCM_PARAMS_H */ |
366 | 341 | ||
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 584e73dd4793..7dbcd10fa215 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h | |||
@@ -46,6 +46,7 @@ | |||
46 | 46 | ||
47 | struct snd_rawmidi; | 47 | struct snd_rawmidi; |
48 | struct snd_rawmidi_substream; | 48 | struct snd_rawmidi_substream; |
49 | struct snd_seq_port_info; | ||
49 | 50 | ||
50 | struct snd_rawmidi_ops { | 51 | struct snd_rawmidi_ops { |
51 | int (*open) (struct snd_rawmidi_substream * substream); | 52 | int (*open) (struct snd_rawmidi_substream * substream); |
@@ -57,6 +58,8 @@ struct snd_rawmidi_ops { | |||
57 | struct snd_rawmidi_global_ops { | 58 | struct snd_rawmidi_global_ops { |
58 | int (*dev_register) (struct snd_rawmidi * rmidi); | 59 | int (*dev_register) (struct snd_rawmidi * rmidi); |
59 | int (*dev_unregister) (struct snd_rawmidi * rmidi); | 60 | int (*dev_unregister) (struct snd_rawmidi * rmidi); |
61 | void (*get_port_info)(struct snd_rawmidi *rmidi, int number, | ||
62 | struct snd_seq_port_info *info); | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | struct snd_rawmidi_runtime { | 65 | struct snd_rawmidi_runtime { |
diff --git a/include/sound/version.h b/include/sound/version.h index 4f0e65808cf1..2ee849d0e198 100644 --- a/include/sound/version.h +++ b/include/sound/version.h | |||
@@ -1,3 +1,3 @@ | |||
1 | /* include/version.h. Generated by configure. */ | 1 | /* include/version.h. Generated by configure. */ |
2 | #define CONFIG_SND_VERSION "1.0.11rc4" | 2 | #define CONFIG_SND_VERSION "1.0.12rc1" |
3 | #define CONFIG_SND_DATE " (Wed Mar 22 10:27:24 2006 UTC)" | 3 | #define CONFIG_SND_DATE " (Thu Jun 22 13:55:50 2006 UTC)" |
diff --git a/kernel/power/main.c b/kernel/power/main.c index 0a907f0dc56b..cdf0f07af92f 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | 18 | #include <linux/console.h> | |
19 | 19 | ||
20 | #include "power.h" | 20 | #include "power.h" |
21 | 21 | ||
diff --git a/kernel/sys.c b/kernel/sys.c index 0b6ec0e7936f..fc9ebbbaba0c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1860,23 +1860,20 @@ out: | |||
1860 | * fields when reaping, so a sample either gets all the additions of a | 1860 | * fields when reaping, so a sample either gets all the additions of a |
1861 | * given child after it's reaped, or none so this sample is before reaping. | 1861 | * given child after it's reaped, or none so this sample is before reaping. |
1862 | * | 1862 | * |
1863 | * tasklist_lock locking optimisation: | 1863 | * Locking: |
1864 | * If we are current and single threaded, we do not need to take the tasklist | 1864 | * We need to take the siglock for CHILDEREN, SELF and BOTH |
1865 | * lock or the siglock. No one else can take our signal_struct away, | 1865 | * for the cases current multithreaded, non-current single threaded |
1866 | * no one else can reap the children to update signal->c* counters, and | 1866 | * non-current multithreaded. Thread traversal is now safe with |
1867 | * no one else can race with the signal-> fields. | 1867 | * the siglock held. |
1868 | * If we do not take the tasklist_lock, the signal-> fields could be read | 1868 | * Strictly speaking, we donot need to take the siglock if we are current and |
1869 | * out of order while another thread was just exiting. So we place a | 1869 | * single threaded, as no one else can take our signal_struct away, no one |
1870 | * read memory barrier when we avoid the lock. On the writer side, | 1870 | * else can reap the children to update signal->c* counters, and no one else |
1871 | * write memory barrier is implied in __exit_signal as __exit_signal releases | 1871 | * can race with the signal-> fields. If we do not take any lock, the |
1872 | * the siglock spinlock after updating the signal-> fields. | 1872 | * signal-> fields could be read out of order while another thread was just |
1873 | * | 1873 | * exiting. So we should place a read memory barrier when we avoid the lock. |
1874 | * We don't really need the siglock when we access the non c* fields | 1874 | * On the writer side, write memory barrier is implied in __exit_signal |
1875 | * of the signal_struct (for RUSAGE_SELF) even in multithreaded | 1875 | * as __exit_signal releases the siglock spinlock after updating the signal-> |
1876 | * case, since we take the tasklist lock for read and the non c* signal-> | 1876 | * fields. But we don't do this yet to keep things simple. |
1877 | * fields are updated only in __exit_signal, which is called with | ||
1878 | * tasklist_lock taken for write, hence these two threads cannot execute | ||
1879 | * concurrently. | ||
1880 | * | 1877 | * |
1881 | */ | 1878 | */ |
1882 | 1879 | ||
@@ -1885,35 +1882,25 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
1885 | struct task_struct *t; | 1882 | struct task_struct *t; |
1886 | unsigned long flags; | 1883 | unsigned long flags; |
1887 | cputime_t utime, stime; | 1884 | cputime_t utime, stime; |
1888 | int need_lock = 0; | ||
1889 | 1885 | ||
1890 | memset((char *) r, 0, sizeof *r); | 1886 | memset((char *) r, 0, sizeof *r); |
1891 | utime = stime = cputime_zero; | 1887 | utime = stime = cputime_zero; |
1892 | 1888 | ||
1893 | if (p != current || !thread_group_empty(p)) | 1889 | rcu_read_lock(); |
1894 | need_lock = 1; | 1890 | if (!lock_task_sighand(p, &flags)) { |
1895 | 1891 | rcu_read_unlock(); | |
1896 | if (need_lock) { | 1892 | return; |
1897 | read_lock(&tasklist_lock); | 1893 | } |
1898 | if (unlikely(!p->signal)) { | ||
1899 | read_unlock(&tasklist_lock); | ||
1900 | return; | ||
1901 | } | ||
1902 | } else | ||
1903 | /* See locking comments above */ | ||
1904 | smp_rmb(); | ||
1905 | 1894 | ||
1906 | switch (who) { | 1895 | switch (who) { |
1907 | case RUSAGE_BOTH: | 1896 | case RUSAGE_BOTH: |
1908 | case RUSAGE_CHILDREN: | 1897 | case RUSAGE_CHILDREN: |
1909 | spin_lock_irqsave(&p->sighand->siglock, flags); | ||
1910 | utime = p->signal->cutime; | 1898 | utime = p->signal->cutime; |
1911 | stime = p->signal->cstime; | 1899 | stime = p->signal->cstime; |
1912 | r->ru_nvcsw = p->signal->cnvcsw; | 1900 | r->ru_nvcsw = p->signal->cnvcsw; |
1913 | r->ru_nivcsw = p->signal->cnivcsw; | 1901 | r->ru_nivcsw = p->signal->cnivcsw; |
1914 | r->ru_minflt = p->signal->cmin_flt; | 1902 | r->ru_minflt = p->signal->cmin_flt; |
1915 | r->ru_majflt = p->signal->cmaj_flt; | 1903 | r->ru_majflt = p->signal->cmaj_flt; |
1916 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | ||
1917 | 1904 | ||
1918 | if (who == RUSAGE_CHILDREN) | 1905 | if (who == RUSAGE_CHILDREN) |
1919 | break; | 1906 | break; |
@@ -1941,8 +1928,9 @@ static void k_getrusage(struct task_struct *p, int who, struct rusage *r) | |||
1941 | BUG(); | 1928 | BUG(); |
1942 | } | 1929 | } |
1943 | 1930 | ||
1944 | if (need_lock) | 1931 | unlock_task_sighand(p, &flags); |
1945 | read_unlock(&tasklist_lock); | 1932 | rcu_read_unlock(); |
1933 | |||
1946 | cputime_to_timeval(utime, &r->ru_utime); | 1934 | cputime_to_timeval(utime, &r->ru_utime); |
1947 | cputime_to_timeval(stime, &r->ru_stime); | 1935 | cputime_to_timeval(stime, &r->ru_stime); |
1948 | } | 1936 | } |
diff --git a/kernel/user.c b/kernel/user.c index 4b1eb745afa1..6408c0424291 100644 --- a/kernel/user.c +++ b/kernel/user.c | |||
@@ -148,7 +148,7 @@ struct user_struct * alloc_uid(uid_t uid) | |||
148 | new->mq_bytes = 0; | 148 | new->mq_bytes = 0; |
149 | new->locked_shm = 0; | 149 | new->locked_shm = 0; |
150 | 150 | ||
151 | if (alloc_uid_keyring(new) < 0) { | 151 | if (alloc_uid_keyring(new, current) < 0) { |
152 | kmem_cache_free(uid_cachep, new); | 152 | kmem_cache_free(uid_cachep, new); |
153 | return NULL; | 153 | return NULL; |
154 | } | 154 | } |
diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c index 1653dd9bb01a..c3e4a2baf835 100644 --- a/lib/zlib_deflate/deflate.c +++ b/lib/zlib_deflate/deflate.c | |||
@@ -164,34 +164,17 @@ static const config configuration_table[10] = { | |||
164 | memset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head)); | 164 | memset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head)); |
165 | 165 | ||
166 | /* ========================================================================= */ | 166 | /* ========================================================================= */ |
167 | int zlib_deflateInit_( | 167 | int zlib_deflateInit2( |
168 | z_streamp strm, | ||
169 | int level, | ||
170 | const char *version, | ||
171 | int stream_size | ||
172 | ) | ||
173 | { | ||
174 | return zlib_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, | ||
175 | DEF_MEM_LEVEL, | ||
176 | Z_DEFAULT_STRATEGY, version, stream_size); | ||
177 | /* To do: ignore strm->next_in if we use it as window */ | ||
178 | } | ||
179 | |||
180 | /* ========================================================================= */ | ||
181 | int zlib_deflateInit2_( | ||
182 | z_streamp strm, | 168 | z_streamp strm, |
183 | int level, | 169 | int level, |
184 | int method, | 170 | int method, |
185 | int windowBits, | 171 | int windowBits, |
186 | int memLevel, | 172 | int memLevel, |
187 | int strategy, | 173 | int strategy |
188 | const char *version, | ||
189 | int stream_size | ||
190 | ) | 174 | ) |
191 | { | 175 | { |
192 | deflate_state *s; | 176 | deflate_state *s; |
193 | int noheader = 0; | 177 | int noheader = 0; |
194 | static char* my_version = ZLIB_VERSION; | ||
195 | deflate_workspace *mem; | 178 | deflate_workspace *mem; |
196 | 179 | ||
197 | ush *overlay; | 180 | ush *overlay; |
@@ -199,10 +182,6 @@ int zlib_deflateInit2_( | |||
199 | * output size for (length,distance) codes is <= 24 bits. | 182 | * output size for (length,distance) codes is <= 24 bits. |
200 | */ | 183 | */ |
201 | 184 | ||
202 | if (version == NULL || version[0] != my_version[0] || | ||
203 | stream_size != sizeof(z_stream)) { | ||
204 | return Z_VERSION_ERROR; | ||
205 | } | ||
206 | if (strm == NULL) return Z_STREAM_ERROR; | 185 | if (strm == NULL) return Z_STREAM_ERROR; |
207 | 186 | ||
208 | strm->msg = NULL; | 187 | strm->msg = NULL; |
diff --git a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c index 767b573d1ef6..ccfe25f3920f 100644 --- a/lib/zlib_deflate/deflate_syms.c +++ b/lib/zlib_deflate/deflate_syms.c | |||
@@ -12,8 +12,7 @@ | |||
12 | 12 | ||
13 | EXPORT_SYMBOL(zlib_deflate_workspacesize); | 13 | EXPORT_SYMBOL(zlib_deflate_workspacesize); |
14 | EXPORT_SYMBOL(zlib_deflate); | 14 | EXPORT_SYMBOL(zlib_deflate); |
15 | EXPORT_SYMBOL(zlib_deflateInit_); | 15 | EXPORT_SYMBOL(zlib_deflateInit2); |
16 | EXPORT_SYMBOL(zlib_deflateInit2_); | ||
17 | EXPORT_SYMBOL(zlib_deflateEnd); | 16 | EXPORT_SYMBOL(zlib_deflateEnd); |
18 | EXPORT_SYMBOL(zlib_deflateReset); | 17 | EXPORT_SYMBOL(zlib_deflateReset); |
19 | MODULE_LICENSE("GPL"); | 18 | MODULE_LICENSE("GPL"); |
diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile index 221c139e0df1..bf065482fa67 100644 --- a/lib/zlib_inflate/Makefile +++ b/lib/zlib_inflate/Makefile | |||
@@ -15,5 +15,5 @@ | |||
15 | 15 | ||
16 | obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o | 16 | obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o |
17 | 17 | ||
18 | zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \ | 18 | zlib_inflate-objs := inffast.o inflate.o \ |
19 | inflate_sync.o inftrees.o infutil.o inflate_syms.o | 19 | inftrees.o inflate_syms.o |
diff --git a/lib/zlib_inflate/infblock.c b/lib/zlib_inflate/infblock.c deleted file mode 100644 index c16cdeff51aa..000000000000 --- a/lib/zlib_inflate/infblock.c +++ /dev/null | |||
@@ -1,365 +0,0 @@ | |||
1 | /* infblock.c -- interpret and process block types to last block | ||
2 | * Copyright (C) 1995-1998 Mark Adler | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | */ | ||
5 | |||
6 | #include <linux/zutil.h> | ||
7 | #include "infblock.h" | ||
8 | #include "inftrees.h" | ||
9 | #include "infcodes.h" | ||
10 | #include "infutil.h" | ||
11 | |||
12 | struct inflate_codes_state; | ||
13 | |||
14 | /* simplify the use of the inflate_huft type with some defines */ | ||
15 | #define exop word.what.Exop | ||
16 | #define bits word.what.Bits | ||
17 | |||
18 | /* Table for deflate from PKZIP's appnote.txt. */ | ||
19 | static const uInt border[] = { /* Order of the bit length code lengths */ | ||
20 | 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | ||
21 | |||
22 | /* | ||
23 | Notes beyond the 1.93a appnote.txt: | ||
24 | |||
25 | 1. Distance pointers never point before the beginning of the output | ||
26 | stream. | ||
27 | 2. Distance pointers can point back across blocks, up to 32k away. | ||
28 | 3. There is an implied maximum of 7 bits for the bit length table and | ||
29 | 15 bits for the actual data. | ||
30 | 4. If only one code exists, then it is encoded using one bit. (Zero | ||
31 | would be more efficient, but perhaps a little confusing.) If two | ||
32 | codes exist, they are coded using one bit each (0 and 1). | ||
33 | 5. There is no way of sending zero distance codes--a dummy must be | ||
34 | sent if there are none. (History: a pre 2.0 version of PKZIP would | ||
35 | store blocks with no distance codes, but this was discovered to be | ||
36 | too harsh a criterion.) Valid only for 1.93a. 2.04c does allow | ||
37 | zero distance codes, which is sent as one code of zero bits in | ||
38 | length. | ||
39 | 6. There are up to 286 literal/length codes. Code 256 represents the | ||
40 | end-of-block. Note however that the static length tree defines | ||
41 | 288 codes just to fill out the Huffman codes. Codes 286 and 287 | ||
42 | cannot be used though, since there is no length base or extra bits | ||
43 | defined for them. Similarily, there are up to 30 distance codes. | ||
44 | However, static trees define 32 codes (all 5 bits) to fill out the | ||
45 | Huffman codes, but the last two had better not show up in the data. | ||
46 | 7. Unzip can check dynamic Huffman blocks for complete code sets. | ||
47 | The exception is that a single code would not be complete (see #4). | ||
48 | 8. The five bits following the block type is really the number of | ||
49 | literal codes sent minus 257. | ||
50 | 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits | ||
51 | (1+6+6). Therefore, to output three times the length, you output | ||
52 | three codes (1+1+1), whereas to output four times the same length, | ||
53 | you only need two codes (1+3). Hmm. | ||
54 | 10. In the tree reconstruction algorithm, Code = Code + Increment | ||
55 | only if BitLength(i) is not zero. (Pretty obvious.) | ||
56 | 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) | ||
57 | 12. Note: length code 284 can represent 227-258, but length code 285 | ||
58 | really is 258. The last length deserves its own, short code | ||
59 | since it gets used a lot in very redundant files. The length | ||
60 | 258 is special since 258 - 3 (the min match length) is 255. | ||
61 | 13. The literal/length and distance code bit lengths are read as a | ||
62 | single stream of lengths. It is possible (and advantageous) for | ||
63 | a repeat code (16, 17, or 18) to go across the boundary between | ||
64 | the two sets of lengths. | ||
65 | */ | ||
66 | |||
67 | |||
68 | void zlib_inflate_blocks_reset( | ||
69 | inflate_blocks_statef *s, | ||
70 | z_streamp z, | ||
71 | uLong *c | ||
72 | ) | ||
73 | { | ||
74 | if (c != NULL) | ||
75 | *c = s->check; | ||
76 | if (s->mode == CODES) | ||
77 | zlib_inflate_codes_free(s->sub.decode.codes, z); | ||
78 | s->mode = TYPE; | ||
79 | s->bitk = 0; | ||
80 | s->bitb = 0; | ||
81 | s->read = s->write = s->window; | ||
82 | if (s->checkfn != NULL) | ||
83 | z->adler = s->check = (*s->checkfn)(0L, NULL, 0); | ||
84 | } | ||
85 | |||
86 | inflate_blocks_statef *zlib_inflate_blocks_new( | ||
87 | z_streamp z, | ||
88 | check_func c, | ||
89 | uInt w | ||
90 | ) | ||
91 | { | ||
92 | inflate_blocks_statef *s; | ||
93 | |||
94 | s = &WS(z)->working_blocks_state; | ||
95 | s->hufts = WS(z)->working_hufts; | ||
96 | s->window = WS(z)->working_window; | ||
97 | s->end = s->window + w; | ||
98 | s->checkfn = c; | ||
99 | s->mode = TYPE; | ||
100 | zlib_inflate_blocks_reset(s, z, NULL); | ||
101 | return s; | ||
102 | } | ||
103 | |||
104 | |||
105 | int zlib_inflate_blocks( | ||
106 | inflate_blocks_statef *s, | ||
107 | z_streamp z, | ||
108 | int r | ||
109 | ) | ||
110 | { | ||
111 | uInt t; /* temporary storage */ | ||
112 | uLong b; /* bit buffer */ | ||
113 | uInt k; /* bits in bit buffer */ | ||
114 | Byte *p; /* input data pointer */ | ||
115 | uInt n; /* bytes available there */ | ||
116 | Byte *q; /* output window write pointer */ | ||
117 | uInt m; /* bytes to end of window or read pointer */ | ||
118 | |||
119 | /* copy input/output information to locals (UPDATE macro restores) */ | ||
120 | LOAD | ||
121 | |||
122 | /* process input based on current state */ | ||
123 | while (1) switch (s->mode) | ||
124 | { | ||
125 | case TYPE: | ||
126 | NEEDBITS(3) | ||
127 | t = (uInt)b & 7; | ||
128 | s->last = t & 1; | ||
129 | switch (t >> 1) | ||
130 | { | ||
131 | case 0: /* stored */ | ||
132 | DUMPBITS(3) | ||
133 | t = k & 7; /* go to byte boundary */ | ||
134 | DUMPBITS(t) | ||
135 | s->mode = LENS; /* get length of stored block */ | ||
136 | break; | ||
137 | case 1: /* fixed */ | ||
138 | { | ||
139 | uInt bl, bd; | ||
140 | inflate_huft *tl, *td; | ||
141 | |||
142 | zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, s->hufts, z); | ||
143 | s->sub.decode.codes = zlib_inflate_codes_new(bl, bd, tl, td, z); | ||
144 | if (s->sub.decode.codes == NULL) | ||
145 | { | ||
146 | r = Z_MEM_ERROR; | ||
147 | LEAVE | ||
148 | } | ||
149 | } | ||
150 | DUMPBITS(3) | ||
151 | s->mode = CODES; | ||
152 | break; | ||
153 | case 2: /* dynamic */ | ||
154 | DUMPBITS(3) | ||
155 | s->mode = TABLE; | ||
156 | break; | ||
157 | case 3: /* illegal */ | ||
158 | DUMPBITS(3) | ||
159 | s->mode = B_BAD; | ||
160 | z->msg = (char*)"invalid block type"; | ||
161 | r = Z_DATA_ERROR; | ||
162 | LEAVE | ||
163 | } | ||
164 | break; | ||
165 | case LENS: | ||
166 | NEEDBITS(32) | ||
167 | if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) | ||
168 | { | ||
169 | s->mode = B_BAD; | ||
170 | z->msg = (char*)"invalid stored block lengths"; | ||
171 | r = Z_DATA_ERROR; | ||
172 | LEAVE | ||
173 | } | ||
174 | s->sub.left = (uInt)b & 0xffff; | ||
175 | b = k = 0; /* dump bits */ | ||
176 | s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); | ||
177 | break; | ||
178 | case STORED: | ||
179 | if (n == 0) | ||
180 | LEAVE | ||
181 | NEEDOUT | ||
182 | t = s->sub.left; | ||
183 | if (t > n) t = n; | ||
184 | if (t > m) t = m; | ||
185 | memcpy(q, p, t); | ||
186 | p += t; n -= t; | ||
187 | q += t; m -= t; | ||
188 | if ((s->sub.left -= t) != 0) | ||
189 | break; | ||
190 | s->mode = s->last ? DRY : TYPE; | ||
191 | break; | ||
192 | case TABLE: | ||
193 | NEEDBITS(14) | ||
194 | s->sub.trees.table = t = (uInt)b & 0x3fff; | ||
195 | #ifndef PKZIP_BUG_WORKAROUND | ||
196 | if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) | ||
197 | { | ||
198 | s->mode = B_BAD; | ||
199 | z->msg = (char*)"too many length or distance symbols"; | ||
200 | r = Z_DATA_ERROR; | ||
201 | LEAVE | ||
202 | } | ||
203 | #endif | ||
204 | { | ||
205 | s->sub.trees.blens = WS(z)->working_blens; | ||
206 | } | ||
207 | DUMPBITS(14) | ||
208 | s->sub.trees.index = 0; | ||
209 | s->mode = BTREE; | ||
210 | case BTREE: | ||
211 | while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) | ||
212 | { | ||
213 | NEEDBITS(3) | ||
214 | s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; | ||
215 | DUMPBITS(3) | ||
216 | } | ||
217 | while (s->sub.trees.index < 19) | ||
218 | s->sub.trees.blens[border[s->sub.trees.index++]] = 0; | ||
219 | s->sub.trees.bb = 7; | ||
220 | t = zlib_inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, | ||
221 | &s->sub.trees.tb, s->hufts, z); | ||
222 | if (t != Z_OK) | ||
223 | { | ||
224 | r = t; | ||
225 | if (r == Z_DATA_ERROR) | ||
226 | s->mode = B_BAD; | ||
227 | LEAVE | ||
228 | } | ||
229 | s->sub.trees.index = 0; | ||
230 | s->mode = DTREE; | ||
231 | case DTREE: | ||
232 | while (t = s->sub.trees.table, | ||
233 | s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) | ||
234 | { | ||
235 | inflate_huft *h; | ||
236 | uInt i, j, c; | ||
237 | |||
238 | t = s->sub.trees.bb; | ||
239 | NEEDBITS(t) | ||
240 | h = s->sub.trees.tb + ((uInt)b & zlib_inflate_mask[t]); | ||
241 | t = h->bits; | ||
242 | c = h->base; | ||
243 | if (c < 16) | ||
244 | { | ||
245 | DUMPBITS(t) | ||
246 | s->sub.trees.blens[s->sub.trees.index++] = c; | ||
247 | } | ||
248 | else /* c == 16..18 */ | ||
249 | { | ||
250 | i = c == 18 ? 7 : c - 14; | ||
251 | j = c == 18 ? 11 : 3; | ||
252 | NEEDBITS(t + i) | ||
253 | DUMPBITS(t) | ||
254 | j += (uInt)b & zlib_inflate_mask[i]; | ||
255 | DUMPBITS(i) | ||
256 | i = s->sub.trees.index; | ||
257 | t = s->sub.trees.table; | ||
258 | if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || | ||
259 | (c == 16 && i < 1)) | ||
260 | { | ||
261 | s->mode = B_BAD; | ||
262 | z->msg = (char*)"invalid bit length repeat"; | ||
263 | r = Z_DATA_ERROR; | ||
264 | LEAVE | ||
265 | } | ||
266 | c = c == 16 ? s->sub.trees.blens[i - 1] : 0; | ||
267 | do { | ||
268 | s->sub.trees.blens[i++] = c; | ||
269 | } while (--j); | ||
270 | s->sub.trees.index = i; | ||
271 | } | ||
272 | } | ||
273 | s->sub.trees.tb = NULL; | ||
274 | { | ||
275 | uInt bl, bd; | ||
276 | inflate_huft *tl, *td; | ||
277 | inflate_codes_statef *c; | ||
278 | |||
279 | bl = 9; /* must be <= 9 for lookahead assumptions */ | ||
280 | bd = 6; /* must be <= 9 for lookahead assumptions */ | ||
281 | t = s->sub.trees.table; | ||
282 | t = zlib_inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), | ||
283 | s->sub.trees.blens, &bl, &bd, &tl, &td, | ||
284 | s->hufts, z); | ||
285 | if (t != Z_OK) | ||
286 | { | ||
287 | if (t == (uInt)Z_DATA_ERROR) | ||
288 | s->mode = B_BAD; | ||
289 | r = t; | ||
290 | LEAVE | ||
291 | } | ||
292 | if ((c = zlib_inflate_codes_new(bl, bd, tl, td, z)) == NULL) | ||
293 | { | ||
294 | r = Z_MEM_ERROR; | ||
295 | LEAVE | ||
296 | } | ||
297 | s->sub.decode.codes = c; | ||
298 | } | ||
299 | s->mode = CODES; | ||
300 | case CODES: | ||
301 | UPDATE | ||
302 | if ((r = zlib_inflate_codes(s, z, r)) != Z_STREAM_END) | ||
303 | return zlib_inflate_flush(s, z, r); | ||
304 | r = Z_OK; | ||
305 | zlib_inflate_codes_free(s->sub.decode.codes, z); | ||
306 | LOAD | ||
307 | if (!s->last) | ||
308 | { | ||
309 | s->mode = TYPE; | ||
310 | break; | ||
311 | } | ||
312 | s->mode = DRY; | ||
313 | case DRY: | ||
314 | FLUSH | ||
315 | if (s->read != s->write) | ||
316 | LEAVE | ||
317 | s->mode = B_DONE; | ||
318 | case B_DONE: | ||
319 | r = Z_STREAM_END; | ||
320 | LEAVE | ||
321 | case B_BAD: | ||
322 | r = Z_DATA_ERROR; | ||
323 | LEAVE | ||
324 | default: | ||
325 | r = Z_STREAM_ERROR; | ||
326 | LEAVE | ||
327 | } | ||
328 | } | ||
329 | |||
330 | |||
331 | int zlib_inflate_blocks_free( | ||
332 | inflate_blocks_statef *s, | ||
333 | z_streamp z | ||
334 | ) | ||
335 | { | ||
336 | zlib_inflate_blocks_reset(s, z, NULL); | ||
337 | return Z_OK; | ||
338 | } | ||
339 | |||
340 | |||
341 | #if 0 | ||
342 | void zlib_inflate_set_dictionary( | ||
343 | inflate_blocks_statef *s, | ||
344 | const Byte *d, | ||
345 | uInt n | ||
346 | ) | ||
347 | { | ||
348 | memcpy(s->window, d, n); | ||
349 | s->read = s->write = s->window + n; | ||
350 | } | ||
351 | #endif /* 0 */ | ||
352 | |||
353 | |||
354 | /* Returns true if inflate is currently at the end of a block generated | ||
355 | * by Z_SYNC_FLUSH or Z_FULL_FLUSH. | ||
356 | * IN assertion: s != NULL | ||
357 | */ | ||
358 | #if 0 | ||
359 | int zlib_inflate_blocks_sync_point( | ||
360 | inflate_blocks_statef *s | ||
361 | ) | ||
362 | { | ||
363 | return s->mode == LENS; | ||
364 | } | ||
365 | #endif /* 0 */ | ||
diff --git a/lib/zlib_inflate/infblock.h b/lib/zlib_inflate/infblock.h deleted file mode 100644 index ceee60b5107c..000000000000 --- a/lib/zlib_inflate/infblock.h +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | /* infblock.h -- header to use infblock.c | ||
2 | * Copyright (C) 1995-1998 Mark Adler | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | */ | ||
5 | |||
6 | /* WARNING: this file should *not* be used by applications. It is | ||
7 | part of the implementation of the compression library and is | ||
8 | subject to change. Applications should only use zlib.h. | ||
9 | */ | ||
10 | |||
11 | #ifndef _INFBLOCK_H | ||
12 | #define _INFBLOCK_H | ||
13 | |||
14 | struct inflate_blocks_state; | ||
15 | typedef struct inflate_blocks_state inflate_blocks_statef; | ||
16 | |||
17 | extern inflate_blocks_statef * zlib_inflate_blocks_new ( | ||
18 | z_streamp z, | ||
19 | check_func c, /* check function */ | ||
20 | uInt w); /* window size */ | ||
21 | |||
22 | extern int zlib_inflate_blocks ( | ||
23 | inflate_blocks_statef *, | ||
24 | z_streamp , | ||
25 | int); /* initial return code */ | ||
26 | |||
27 | extern void zlib_inflate_blocks_reset ( | ||
28 | inflate_blocks_statef *, | ||
29 | z_streamp , | ||
30 | uLong *); /* check value on output */ | ||
31 | |||
32 | extern int zlib_inflate_blocks_free ( | ||
33 | inflate_blocks_statef *, | ||
34 | z_streamp); | ||
35 | |||
36 | #if 0 | ||
37 | extern void zlib_inflate_set_dictionary ( | ||
38 | inflate_blocks_statef *s, | ||
39 | const Byte *d, /* dictionary */ | ||
40 | uInt n); /* dictionary length */ | ||
41 | #endif /* 0 */ | ||
42 | |||
43 | #if 0 | ||
44 | extern int zlib_inflate_blocks_sync_point ( | ||
45 | inflate_blocks_statef *s); | ||
46 | #endif /* 0 */ | ||
47 | |||
48 | #endif /* _INFBLOCK_H */ | ||
diff --git a/lib/zlib_inflate/infcodes.c b/lib/zlib_inflate/infcodes.c deleted file mode 100644 index 07cd7591cbb7..000000000000 --- a/lib/zlib_inflate/infcodes.c +++ /dev/null | |||
@@ -1,202 +0,0 @@ | |||
1 | /* infcodes.c -- process literals and length/distance pairs | ||
2 | * Copyright (C) 1995-1998 Mark Adler | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | */ | ||
5 | |||
6 | #include <linux/zutil.h> | ||
7 | #include "inftrees.h" | ||
8 | #include "infblock.h" | ||
9 | #include "infcodes.h" | ||
10 | #include "infutil.h" | ||
11 | #include "inffast.h" | ||
12 | |||
13 | /* simplify the use of the inflate_huft type with some defines */ | ||
14 | #define exop word.what.Exop | ||
15 | #define bits word.what.Bits | ||
16 | |||
17 | inflate_codes_statef *zlib_inflate_codes_new( | ||
18 | uInt bl, | ||
19 | uInt bd, | ||
20 | inflate_huft *tl, | ||
21 | inflate_huft *td, /* need separate declaration for Borland C++ */ | ||
22 | z_streamp z | ||
23 | ) | ||
24 | { | ||
25 | inflate_codes_statef *c; | ||
26 | |||
27 | c = &WS(z)->working_state; | ||
28 | { | ||
29 | c->mode = START; | ||
30 | c->lbits = (Byte)bl; | ||
31 | c->dbits = (Byte)bd; | ||
32 | c->ltree = tl; | ||
33 | c->dtree = td; | ||
34 | } | ||
35 | return c; | ||
36 | } | ||
37 | |||
38 | |||
39 | int zlib_inflate_codes( | ||
40 | inflate_blocks_statef *s, | ||
41 | z_streamp z, | ||
42 | int r | ||
43 | ) | ||
44 | { | ||
45 | uInt j; /* temporary storage */ | ||
46 | inflate_huft *t; /* temporary pointer */ | ||
47 | uInt e; /* extra bits or operation */ | ||
48 | uLong b; /* bit buffer */ | ||
49 | uInt k; /* bits in bit buffer */ | ||
50 | Byte *p; /* input data pointer */ | ||
51 | uInt n; /* bytes available there */ | ||
52 | Byte *q; /* output window write pointer */ | ||
53 | uInt m; /* bytes to end of window or read pointer */ | ||
54 | Byte *f; /* pointer to copy strings from */ | ||
55 | inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ | ||
56 | |||
57 | /* copy input/output information to locals (UPDATE macro restores) */ | ||
58 | LOAD | ||
59 | |||
60 | /* process input and output based on current state */ | ||
61 | while (1) switch (c->mode) | ||
62 | { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ | ||
63 | case START: /* x: set up for LEN */ | ||
64 | #ifndef SLOW | ||
65 | if (m >= 258 && n >= 10) | ||
66 | { | ||
67 | UPDATE | ||
68 | r = zlib_inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); | ||
69 | LOAD | ||
70 | if (r != Z_OK) | ||
71 | { | ||
72 | c->mode = r == Z_STREAM_END ? WASH : BADCODE; | ||
73 | break; | ||
74 | } | ||
75 | } | ||
76 | #endif /* !SLOW */ | ||
77 | c->sub.code.need = c->lbits; | ||
78 | c->sub.code.tree = c->ltree; | ||
79 | c->mode = LEN; | ||
80 | case LEN: /* i: get length/literal/eob next */ | ||
81 | j = c->sub.code.need; | ||
82 | NEEDBITS(j) | ||
83 | t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]); | ||
84 | DUMPBITS(t->bits) | ||
85 | e = (uInt)(t->exop); | ||
86 | if (e == 0) /* literal */ | ||
87 | { | ||
88 | c->sub.lit = t->base; | ||
89 | c->mode = LIT; | ||
90 | break; | ||
91 | } | ||
92 | if (e & 16) /* length */ | ||
93 | { | ||
94 | c->sub.copy.get = e & 15; | ||
95 | c->len = t->base; | ||
96 | c->mode = LENEXT; | ||
97 | break; | ||
98 | } | ||
99 | if ((e & 64) == 0) /* next table */ | ||
100 | { | ||
101 | c->sub.code.need = e; | ||
102 | c->sub.code.tree = t + t->base; | ||
103 | break; | ||
104 | } | ||
105 | if (e & 32) /* end of block */ | ||
106 | { | ||
107 | c->mode = WASH; | ||
108 | break; | ||
109 | } | ||
110 | c->mode = BADCODE; /* invalid code */ | ||
111 | z->msg = (char*)"invalid literal/length code"; | ||
112 | r = Z_DATA_ERROR; | ||
113 | LEAVE | ||
114 | case LENEXT: /* i: getting length extra (have base) */ | ||
115 | j = c->sub.copy.get; | ||
116 | NEEDBITS(j) | ||
117 | c->len += (uInt)b & zlib_inflate_mask[j]; | ||
118 | DUMPBITS(j) | ||
119 | c->sub.code.need = c->dbits; | ||
120 | c->sub.code.tree = c->dtree; | ||
121 | c->mode = DIST; | ||
122 | case DIST: /* i: get distance next */ | ||
123 | j = c->sub.code.need; | ||
124 | NEEDBITS(j) | ||
125 | t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]); | ||
126 | DUMPBITS(t->bits) | ||
127 | e = (uInt)(t->exop); | ||
128 | if (e & 16) /* distance */ | ||
129 | { | ||
130 | c->sub.copy.get = e & 15; | ||
131 | c->sub.copy.dist = t->base; | ||
132 | c->mode = DISTEXT; | ||
133 | break; | ||
134 | } | ||
135 | if ((e & 64) == 0) /* next table */ | ||
136 | { | ||
137 | c->sub.code.need = e; | ||
138 | c->sub.code.tree = t + t->base; | ||
139 | break; | ||
140 | } | ||
141 | c->mode = BADCODE; /* invalid code */ | ||
142 | z->msg = (char*)"invalid distance code"; | ||
143 | r = Z_DATA_ERROR; | ||
144 | LEAVE | ||
145 | case DISTEXT: /* i: getting distance extra */ | ||
146 | j = c->sub.copy.get; | ||
147 | NEEDBITS(j) | ||
148 | c->sub.copy.dist += (uInt)b & zlib_inflate_mask[j]; | ||
149 | DUMPBITS(j) | ||
150 | c->mode = COPY; | ||
151 | case COPY: /* o: copying bytes in window, waiting for space */ | ||
152 | f = q - c->sub.copy.dist; | ||
153 | while (f < s->window) /* modulo window size-"while" instead */ | ||
154 | f += s->end - s->window; /* of "if" handles invalid distances */ | ||
155 | while (c->len) | ||
156 | { | ||
157 | NEEDOUT | ||
158 | OUTBYTE(*f++) | ||
159 | if (f == s->end) | ||
160 | f = s->window; | ||
161 | c->len--; | ||
162 | } | ||
163 | c->mode = START; | ||
164 | break; | ||
165 | case LIT: /* o: got literal, waiting for output space */ | ||
166 | NEEDOUT | ||
167 | OUTBYTE(c->sub.lit) | ||
168 | c->mode = START; | ||
169 | break; | ||
170 | case WASH: /* o: got eob, possibly more output */ | ||
171 | if (k > 7) /* return unused byte, if any */ | ||
172 | { | ||
173 | k -= 8; | ||
174 | n++; | ||
175 | p--; /* can always return one */ | ||
176 | } | ||
177 | FLUSH | ||
178 | if (s->read != s->write) | ||
179 | LEAVE | ||
180 | c->mode = END; | ||
181 | case END: | ||
182 | r = Z_STREAM_END; | ||
183 | LEAVE | ||
184 | case BADCODE: /* x: got error */ | ||
185 | r = Z_DATA_ERROR; | ||
186 | LEAVE | ||
187 | default: | ||
188 | r = Z_STREAM_ERROR; | ||
189 | LEAVE | ||
190 | } | ||
191 | #ifdef NEED_DUMMY_RETURN | ||
192 | return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ | ||
193 | #endif | ||
194 | } | ||
195 | |||
196 | |||
197 | void zlib_inflate_codes_free( | ||
198 | inflate_codes_statef *c, | ||
199 | z_streamp z | ||
200 | ) | ||
201 | { | ||
202 | } | ||
diff --git a/lib/zlib_inflate/infcodes.h b/lib/zlib_inflate/infcodes.h deleted file mode 100644 index 5cff417523b0..000000000000 --- a/lib/zlib_inflate/infcodes.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* infcodes.h -- header to use infcodes.c | ||
2 | * Copyright (C) 1995-1998 Mark Adler | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | */ | ||
5 | |||
6 | /* WARNING: this file should *not* be used by applications. It is | ||
7 | part of the implementation of the compression library and is | ||
8 | subject to change. Applications should only use zlib.h. | ||
9 | */ | ||
10 | |||
11 | #ifndef _INFCODES_H | ||
12 | #define _INFCODES_H | ||
13 | |||
14 | #include "infblock.h" | ||
15 | |||
16 | struct inflate_codes_state; | ||
17 | typedef struct inflate_codes_state inflate_codes_statef; | ||
18 | |||
19 | extern inflate_codes_statef *zlib_inflate_codes_new ( | ||
20 | uInt, uInt, | ||
21 | inflate_huft *, inflate_huft *, | ||
22 | z_streamp ); | ||
23 | |||
24 | extern int zlib_inflate_codes ( | ||
25 | inflate_blocks_statef *, | ||
26 | z_streamp , | ||
27 | int); | ||
28 | |||
29 | extern void zlib_inflate_codes_free ( | ||
30 | inflate_codes_statef *, | ||
31 | z_streamp ); | ||
32 | |||
33 | #endif /* _INFCODES_H */ | ||
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c index 0bd7623fc85a..02a16eacb72d 100644 --- a/lib/zlib_inflate/inffast.c +++ b/lib/zlib_inflate/inffast.c | |||
@@ -1,176 +1,312 @@ | |||
1 | /* inffast.c -- process literals and length/distance pairs fast | 1 | /* inffast.c -- fast decoding |
2 | * Copyright (C) 1995-1998 Mark Adler | 2 | * Copyright (C) 1995-2004 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/zutil.h> | 6 | #include <linux/zutil.h> |
7 | #include "inftrees.h" | 7 | #include "inftrees.h" |
8 | #include "infblock.h" | 8 | #include "inflate.h" |
9 | #include "infcodes.h" | ||
10 | #include "infutil.h" | ||
11 | #include "inffast.h" | 9 | #include "inffast.h" |
12 | 10 | ||
13 | struct inflate_codes_state; | 11 | #ifndef ASMINF |
14 | 12 | ||
15 | /* simplify the use of the inflate_huft type with some defines */ | 13 | /* Allow machine dependent optimization for post-increment or pre-increment. |
16 | #define exop word.what.Exop | 14 | Based on testing to date, |
17 | #define bits word.what.Bits | 15 | Pre-increment preferred for: |
18 | 16 | - PowerPC G3 (Adler) | |
19 | /* macros for bit input with no checking and for returning unused bytes */ | 17 | - MIPS R5000 (Randers-Pehrson) |
20 | #define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}} | 18 | Post-increment preferred for: |
21 | #define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;} | 19 | - none |
22 | 20 | No measurable difference: | |
23 | /* Called with number of bytes left to write in window at least 258 | 21 | - Pentium III (Anderson) |
24 | (the maximum string length) and number of input bytes available | 22 | - M68060 (Nikl) |
25 | at least ten. The ten bytes are six bytes for the longest length/ | 23 | */ |
26 | distance pair plus four bytes for overloading the bit buffer. */ | 24 | #ifdef POSTINC |
27 | 25 | # define OFF 0 | |
28 | int zlib_inflate_fast( | 26 | # define PUP(a) *(a)++ |
29 | uInt bl, | 27 | #else |
30 | uInt bd, | 28 | # define OFF 1 |
31 | inflate_huft *tl, | 29 | # define PUP(a) *++(a) |
32 | inflate_huft *td, /* need separate declaration for Borland C++ */ | 30 | #endif |
33 | inflate_blocks_statef *s, | 31 | |
34 | z_streamp z | 32 | /* |
35 | ) | 33 | Decode literal, length, and distance codes and write out the resulting |
34 | literal and match bytes until either not enough input or output is | ||
35 | available, an end-of-block is encountered, or a data error is encountered. | ||
36 | When large enough input and output buffers are supplied to inflate(), for | ||
37 | example, a 16K input buffer and a 64K output buffer, more than 95% of the | ||
38 | inflate execution time is spent in this routine. | ||
39 | |||
40 | Entry assumptions: | ||
41 | |||
42 | state->mode == LEN | ||
43 | strm->avail_in >= 6 | ||
44 | strm->avail_out >= 258 | ||
45 | start >= strm->avail_out | ||
46 | state->bits < 8 | ||
47 | |||
48 | On return, state->mode is one of: | ||
49 | |||
50 | LEN -- ran out of enough output space or enough available input | ||
51 | TYPE -- reached end of block code, inflate() to interpret next block | ||
52 | BAD -- error in block data | ||
53 | |||
54 | Notes: | ||
55 | |||
56 | - The maximum input bits used by a length/distance pair is 15 bits for the | ||
57 | length code, 5 bits for the length extra, 15 bits for the distance code, | ||
58 | and 13 bits for the distance extra. This totals 48 bits, or six bytes. | ||
59 | Therefore if strm->avail_in >= 6, then there is enough input to avoid | ||
60 | checking for available input while decoding. | ||
61 | |||
62 | - The maximum bytes that a single length/distance pair can output is 258 | ||
63 | bytes, which is the maximum length that can be coded. inflate_fast() | ||
64 | requires strm->avail_out >= 258 for each loop to avoid checking for | ||
65 | output space. | ||
66 | */ | ||
67 | void inflate_fast(strm, start) | ||
68 | z_streamp strm; | ||
69 | unsigned start; /* inflate()'s starting value for strm->avail_out */ | ||
36 | { | 70 | { |
37 | inflate_huft *t; /* temporary pointer */ | 71 | struct inflate_state *state; |
38 | uInt e; /* extra bits or operation */ | 72 | unsigned char *in; /* local strm->next_in */ |
39 | uLong b; /* bit buffer */ | 73 | unsigned char *last; /* while in < last, enough input available */ |
40 | uInt k; /* bits in bit buffer */ | 74 | unsigned char *out; /* local strm->next_out */ |
41 | Byte *p; /* input data pointer */ | 75 | unsigned char *beg; /* inflate()'s initial strm->next_out */ |
42 | uInt n; /* bytes available there */ | 76 | unsigned char *end; /* while out < end, enough space available */ |
43 | Byte *q; /* output window write pointer */ | 77 | #ifdef INFLATE_STRICT |
44 | uInt m; /* bytes to end of window or read pointer */ | 78 | unsigned dmax; /* maximum distance from zlib header */ |
45 | uInt ml; /* mask for literal/length tree */ | 79 | #endif |
46 | uInt md; /* mask for distance tree */ | 80 | unsigned wsize; /* window size or zero if not using window */ |
47 | uInt c; /* bytes to copy */ | 81 | unsigned whave; /* valid bytes in the window */ |
48 | uInt d; /* distance back to copy from */ | 82 | unsigned write; /* window write index */ |
49 | Byte *r; /* copy source pointer */ | 83 | unsigned char *window; /* allocated sliding window, if wsize != 0 */ |
50 | 84 | unsigned long hold; /* local strm->hold */ | |
51 | /* load input, output, bit values */ | 85 | unsigned bits; /* local strm->bits */ |
52 | LOAD | 86 | code const *lcode; /* local strm->lencode */ |
53 | 87 | code const *dcode; /* local strm->distcode */ | |
54 | /* initialize masks */ | 88 | unsigned lmask; /* mask for first level of length codes */ |
55 | ml = zlib_inflate_mask[bl]; | 89 | unsigned dmask; /* mask for first level of distance codes */ |
56 | md = zlib_inflate_mask[bd]; | 90 | code this; /* retrieved table entry */ |
57 | 91 | unsigned op; /* code bits, operation, extra bits, or */ | |
58 | /* do until not enough input or output space for fast loop */ | 92 | /* window position, window bytes to copy */ |
59 | do { /* assume called with m >= 258 && n >= 10 */ | 93 | unsigned len; /* match length, unused bytes */ |
60 | /* get literal/length code */ | 94 | unsigned dist; /* match distance */ |
61 | GRABBITS(20) /* max bits for literal/length code */ | 95 | unsigned char *from; /* where to copy match from */ |
62 | if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) | 96 | |
63 | { | 97 | /* copy state to local variables */ |
64 | DUMPBITS(t->bits) | 98 | state = (struct inflate_state *)strm->state; |
65 | *q++ = (Byte)t->base; | 99 | in = strm->next_in - OFF; |
66 | m--; | 100 | last = in + (strm->avail_in - 5); |
67 | continue; | 101 | out = strm->next_out - OFF; |
68 | } | 102 | beg = out - (start - strm->avail_out); |
103 | end = out + (strm->avail_out - 257); | ||
104 | #ifdef INFLATE_STRICT | ||
105 | dmax = state->dmax; | ||
106 | #endif | ||
107 | wsize = state->wsize; | ||
108 | whave = state->whave; | ||
109 | write = state->write; | ||
110 | window = state->window; | ||
111 | hold = state->hold; | ||
112 | bits = state->bits; | ||
113 | lcode = state->lencode; | ||
114 | dcode = state->distcode; | ||
115 | lmask = (1U << state->lenbits) - 1; | ||
116 | dmask = (1U << state->distbits) - 1; | ||
117 | |||
118 | /* decode literals and length/distances until end-of-block or not enough | ||
119 | input data or output space */ | ||
69 | do { | 120 | do { |
70 | DUMPBITS(t->bits) | 121 | if (bits < 15) { |
71 | if (e & 16) | 122 | hold += (unsigned long)(PUP(in)) << bits; |
72 | { | 123 | bits += 8; |
73 | /* get extra bits for length */ | 124 | hold += (unsigned long)(PUP(in)) << bits; |
74 | e &= 15; | 125 | bits += 8; |
75 | c = t->base + ((uInt)b & zlib_inflate_mask[e]); | 126 | } |
76 | DUMPBITS(e) | 127 | this = lcode[hold & lmask]; |
77 | 128 | dolen: | |
78 | /* decode distance base of block to copy */ | 129 | op = (unsigned)(this.bits); |
79 | GRABBITS(15); /* max bits for distance code */ | 130 | hold >>= op; |
80 | e = (t = td + ((uInt)b & md))->exop; | 131 | bits -= op; |
81 | do { | 132 | op = (unsigned)(this.op); |
82 | DUMPBITS(t->bits) | 133 | if (op == 0) { /* literal */ |
83 | if (e & 16) | 134 | PUP(out) = (unsigned char)(this.val); |
84 | { | 135 | } |
85 | /* get extra bits to add to distance base */ | 136 | else if (op & 16) { /* length base */ |
86 | e &= 15; | 137 | len = (unsigned)(this.val); |
87 | GRABBITS(e) /* get extra bits (up to 13) */ | 138 | op &= 15; /* number of extra bits */ |
88 | d = t->base + ((uInt)b & zlib_inflate_mask[e]); | 139 | if (op) { |
89 | DUMPBITS(e) | 140 | if (bits < op) { |
90 | 141 | hold += (unsigned long)(PUP(in)) << bits; | |
91 | /* do the copy */ | 142 | bits += 8; |
92 | m -= c; | 143 | } |
93 | r = q - d; | 144 | len += (unsigned)hold & ((1U << op) - 1); |
94 | if (r < s->window) /* wrap if needed */ | 145 | hold >>= op; |
95 | { | 146 | bits -= op; |
96 | do { | 147 | } |
97 | r += s->end - s->window; /* force pointer in window */ | 148 | if (bits < 15) { |
98 | } while (r < s->window); /* covers invalid distances */ | 149 | hold += (unsigned long)(PUP(in)) << bits; |
99 | e = s->end - r; | 150 | bits += 8; |
100 | if (c > e) | 151 | hold += (unsigned long)(PUP(in)) << bits; |
101 | { | 152 | bits += 8; |
102 | c -= e; /* wrapped copy */ | 153 | } |
103 | do { | 154 | this = dcode[hold & dmask]; |
104 | *q++ = *r++; | 155 | dodist: |
105 | } while (--e); | 156 | op = (unsigned)(this.bits); |
106 | r = s->window; | 157 | hold >>= op; |
107 | do { | 158 | bits -= op; |
108 | *q++ = *r++; | 159 | op = (unsigned)(this.op); |
109 | } while (--c); | 160 | if (op & 16) { /* distance base */ |
110 | } | 161 | dist = (unsigned)(this.val); |
111 | else /* normal copy */ | 162 | op &= 15; /* number of extra bits */ |
112 | { | 163 | if (bits < op) { |
113 | *q++ = *r++; c--; | 164 | hold += (unsigned long)(PUP(in)) << bits; |
114 | *q++ = *r++; c--; | 165 | bits += 8; |
115 | do { | 166 | if (bits < op) { |
116 | *q++ = *r++; | 167 | hold += (unsigned long)(PUP(in)) << bits; |
117 | } while (--c); | 168 | bits += 8; |
118 | } | 169 | } |
170 | } | ||
171 | dist += (unsigned)hold & ((1U << op) - 1); | ||
172 | #ifdef INFLATE_STRICT | ||
173 | if (dist > dmax) { | ||
174 | strm->msg = (char *)"invalid distance too far back"; | ||
175 | state->mode = BAD; | ||
176 | break; | ||
177 | } | ||
178 | #endif | ||
179 | hold >>= op; | ||
180 | bits -= op; | ||
181 | op = (unsigned)(out - beg); /* max distance in output */ | ||
182 | if (dist > op) { /* see if copy from window */ | ||
183 | op = dist - op; /* distance back in window */ | ||
184 | if (op > whave) { | ||
185 | strm->msg = (char *)"invalid distance too far back"; | ||
186 | state->mode = BAD; | ||
187 | break; | ||
188 | } | ||
189 | from = window - OFF; | ||
190 | if (write == 0) { /* very common case */ | ||
191 | from += wsize - op; | ||
192 | if (op < len) { /* some from window */ | ||
193 | len -= op; | ||
194 | do { | ||
195 | PUP(out) = PUP(from); | ||
196 | } while (--op); | ||
197 | from = out - dist; /* rest from output */ | ||
198 | } | ||
199 | } | ||
200 | else if (write < op) { /* wrap around window */ | ||
201 | from += wsize + write - op; | ||
202 | op -= write; | ||
203 | if (op < len) { /* some from end of window */ | ||
204 | len -= op; | ||
205 | do { | ||
206 | PUP(out) = PUP(from); | ||
207 | } while (--op); | ||
208 | from = window - OFF; | ||
209 | if (write < len) { /* some from start of window */ | ||
210 | op = write; | ||
211 | len -= op; | ||
212 | do { | ||
213 | PUP(out) = PUP(from); | ||
214 | } while (--op); | ||
215 | from = out - dist; /* rest from output */ | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | else { /* contiguous in window */ | ||
220 | from += write - op; | ||
221 | if (op < len) { /* some from window */ | ||
222 | len -= op; | ||
223 | do { | ||
224 | PUP(out) = PUP(from); | ||
225 | } while (--op); | ||
226 | from = out - dist; /* rest from output */ | ||
227 | } | ||
228 | } | ||
229 | while (len > 2) { | ||
230 | PUP(out) = PUP(from); | ||
231 | PUP(out) = PUP(from); | ||
232 | PUP(out) = PUP(from); | ||
233 | len -= 3; | ||
234 | } | ||
235 | if (len) { | ||
236 | PUP(out) = PUP(from); | ||
237 | if (len > 1) | ||
238 | PUP(out) = PUP(from); | ||
239 | } | ||
240 | } | ||
241 | else { | ||
242 | from = out - dist; /* copy direct from output */ | ||
243 | do { /* minimum length is three */ | ||
244 | PUP(out) = PUP(from); | ||
245 | PUP(out) = PUP(from); | ||
246 | PUP(out) = PUP(from); | ||
247 | len -= 3; | ||
248 | } while (len > 2); | ||
249 | if (len) { | ||
250 | PUP(out) = PUP(from); | ||
251 | if (len > 1) | ||
252 | PUP(out) = PUP(from); | ||
253 | } | ||
254 | } | ||
255 | } | ||
256 | else if ((op & 64) == 0) { /* 2nd level distance code */ | ||
257 | this = dcode[this.val + (hold & ((1U << op) - 1))]; | ||
258 | goto dodist; | ||
119 | } | 259 | } |
120 | else /* normal copy */ | 260 | else { |
121 | { | 261 | strm->msg = (char *)"invalid distance code"; |
122 | *q++ = *r++; c--; | 262 | state->mode = BAD; |
123 | *q++ = *r++; c--; | 263 | break; |
124 | do { | ||
125 | *q++ = *r++; | ||
126 | } while (--c); | ||
127 | } | 264 | } |
265 | } | ||
266 | else if ((op & 64) == 0) { /* 2nd level length code */ | ||
267 | this = lcode[this.val + (hold & ((1U << op) - 1))]; | ||
268 | goto dolen; | ||
269 | } | ||
270 | else if (op & 32) { /* end-of-block */ | ||
271 | state->mode = TYPE; | ||
128 | break; | 272 | break; |
129 | } | ||
130 | else if ((e & 64) == 0) | ||
131 | { | ||
132 | t += t->base; | ||
133 | e = (t += ((uInt)b & zlib_inflate_mask[e]))->exop; | ||
134 | } | ||
135 | else | ||
136 | { | ||
137 | z->msg = (char*)"invalid distance code"; | ||
138 | UNGRAB | ||
139 | UPDATE | ||
140 | return Z_DATA_ERROR; | ||
141 | } | ||
142 | } while (1); | ||
143 | break; | ||
144 | } | ||
145 | if ((e & 64) == 0) | ||
146 | { | ||
147 | t += t->base; | ||
148 | if ((e = (t += ((uInt)b & zlib_inflate_mask[e]))->exop) == 0) | ||
149 | { | ||
150 | DUMPBITS(t->bits) | ||
151 | *q++ = (Byte)t->base; | ||
152 | m--; | ||
153 | break; | ||
154 | } | 273 | } |
155 | } | 274 | else { |
156 | else if (e & 32) | 275 | strm->msg = (char *)"invalid literal/length code"; |
157 | { | 276 | state->mode = BAD; |
158 | UNGRAB | 277 | break; |
159 | UPDATE | 278 | } |
160 | return Z_STREAM_END; | 279 | } while (in < last && out < end); |
161 | } | 280 | |
162 | else | 281 | /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ |
163 | { | 282 | len = bits >> 3; |
164 | z->msg = (char*)"invalid literal/length code"; | 283 | in -= len; |
165 | UNGRAB | 284 | bits -= len << 3; |
166 | UPDATE | 285 | hold &= (1U << bits) - 1; |
167 | return Z_DATA_ERROR; | 286 | |
168 | } | 287 | /* update state and return */ |
169 | } while (1); | 288 | strm->next_in = in + OFF; |
170 | } while (m >= 258 && n >= 10); | 289 | strm->next_out = out + OFF; |
171 | 290 | strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); | |
172 | /* not enough input or output--restore pointers and return */ | 291 | strm->avail_out = (unsigned)(out < end ? |
173 | UNGRAB | 292 | 257 + (end - out) : 257 - (out - end)); |
174 | UPDATE | 293 | state->hold = hold; |
175 | return Z_OK; | 294 | state->bits = bits; |
295 | return; | ||
176 | } | 296 | } |
297 | |||
298 | /* | ||
299 | inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): | ||
300 | - Using bit fields for code structure | ||
301 | - Different op definition to avoid & for extra bits (do & for table bits) | ||
302 | - Three separate decoding do-loops for direct, window, and write == 0 | ||
303 | - Special case for distance > 1 copies to do overlapped load and store copy | ||
304 | - Explicit branch predictions (based on measured branch probabilities) | ||
305 | - Deferring match copy and interspersed it with decoding subsequent codes | ||
306 | - Swapping literal/length else | ||
307 | - Swapping window/direct else | ||
308 | - Larger unrolled copy loops (three is about right) | ||
309 | - Moving len -= 3 statement into middle of loop | ||
310 | */ | ||
311 | |||
312 | #endif /* !ASMINF */ | ||
diff --git a/lib/zlib_inflate/inffast.h b/lib/zlib_inflate/inffast.h index fc720f0fa7f5..40315d9fddc4 100644 --- a/lib/zlib_inflate/inffast.h +++ b/lib/zlib_inflate/inffast.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* inffast.h -- header to use inffast.c | 1 | /* inffast.h -- header to use inffast.c |
2 | * Copyright (C) 1995-1998 Mark Adler | 2 | * Copyright (C) 1995-2003 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
6 | /* WARNING: this file should *not* be used by applications. It is | 6 | /* WARNING: this file should *not* be used by applications. It is |
@@ -8,10 +8,4 @@ | |||
8 | subject to change. Applications should only use zlib.h. | 8 | subject to change. Applications should only use zlib.h. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | extern int zlib_inflate_fast ( | 11 | void inflate_fast (z_streamp strm, unsigned start); |
12 | uInt, | ||
13 | uInt, | ||
14 | inflate_huft *, | ||
15 | inflate_huft *, | ||
16 | inflate_blocks_statef *, | ||
17 | z_streamp ); | ||
diff --git a/lib/zlib_inflate/inffixed.h b/lib/zlib_inflate/inffixed.h new file mode 100644 index 000000000000..75ed4b5978de --- /dev/null +++ b/lib/zlib_inflate/inffixed.h | |||
@@ -0,0 +1,94 @@ | |||
1 | /* inffixed.h -- table for decoding fixed codes | ||
2 | * Generated automatically by makefixed(). | ||
3 | */ | ||
4 | |||
5 | /* WARNING: this file should *not* be used by applications. It | ||
6 | is part of the implementation of the compression library and | ||
7 | is subject to change. Applications should only use zlib.h. | ||
8 | */ | ||
9 | |||
10 | static const code lenfix[512] = { | ||
11 | {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, | ||
12 | {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, | ||
13 | {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, | ||
14 | {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, | ||
15 | {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, | ||
16 | {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, | ||
17 | {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, | ||
18 | {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, | ||
19 | {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, | ||
20 | {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, | ||
21 | {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, | ||
22 | {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, | ||
23 | {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, | ||
24 | {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, | ||
25 | {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, | ||
26 | {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, | ||
27 | {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, | ||
28 | {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, | ||
29 | {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, | ||
30 | {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, | ||
31 | {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, | ||
32 | {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, | ||
33 | {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, | ||
34 | {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, | ||
35 | {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, | ||
36 | {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, | ||
37 | {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, | ||
38 | {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, | ||
39 | {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, | ||
40 | {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, | ||
41 | {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, | ||
42 | {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, | ||
43 | {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, | ||
44 | {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, | ||
45 | {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, | ||
46 | {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, | ||
47 | {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, | ||
48 | {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, | ||
49 | {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, | ||
50 | {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, | ||
51 | {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, | ||
52 | {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, | ||
53 | {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, | ||
54 | {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, | ||
55 | {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, | ||
56 | {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, | ||
57 | {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, | ||
58 | {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, | ||
59 | {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, | ||
60 | {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, | ||
61 | {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, | ||
62 | {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, | ||
63 | {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, | ||
64 | {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, | ||
65 | {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, | ||
66 | {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, | ||
67 | {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, | ||
68 | {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, | ||
69 | {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, | ||
70 | {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, | ||
71 | {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, | ||
72 | {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, | ||
73 | {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, | ||
74 | {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, | ||
75 | {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, | ||
76 | {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, | ||
77 | {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, | ||
78 | {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, | ||
79 | {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, | ||
80 | {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, | ||
81 | {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, | ||
82 | {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, | ||
83 | {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, | ||
84 | {0,9,255} | ||
85 | }; | ||
86 | |||
87 | static const code distfix[32] = { | ||
88 | {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, | ||
89 | {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, | ||
90 | {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, | ||
91 | {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, | ||
92 | {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, | ||
93 | {22,5,193},{64,5,0} | ||
94 | }; | ||
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c index 31b9e9054bf7..7f922dccf1a5 100644 --- a/lib/zlib_inflate/inflate.c +++ b/lib/zlib_inflate/inflate.c | |||
@@ -1,89 +1,148 @@ | |||
1 | /* inflate.c -- zlib interface to inflate modules | 1 | /* inflate.c -- zlib decompression |
2 | * Copyright (C) 1995-1998 Mark Adler | 2 | * Copyright (C) 1995-2005 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | * | ||
5 | * Based on zlib 1.2.3 but modified for the Linux Kernel by | ||
6 | * Richard Purdie <richard@openedhand.com> | ||
7 | * | ||
8 | * Changes mainly for static instead of dynamic memory allocation | ||
9 | * | ||
4 | */ | 10 | */ |
5 | 11 | ||
6 | #include <linux/zutil.h> | 12 | #include <linux/zutil.h> |
7 | #include "infblock.h" | 13 | #include "inftrees.h" |
14 | #include "inflate.h" | ||
15 | #include "inffast.h" | ||
8 | #include "infutil.h" | 16 | #include "infutil.h" |
9 | 17 | ||
10 | int zlib_inflate_workspacesize(void) | 18 | int zlib_inflate_workspacesize(void) |
11 | { | 19 | { |
12 | return sizeof(struct inflate_workspace); | 20 | return sizeof(struct inflate_workspace); |
13 | } | 21 | } |
14 | 22 | ||
23 | int zlib_inflateReset(z_streamp strm) | ||
24 | { | ||
25 | struct inflate_state *state; | ||
26 | |||
27 | if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; | ||
28 | state = (struct inflate_state *)strm->state; | ||
29 | strm->total_in = strm->total_out = state->total = 0; | ||
30 | strm->msg = NULL; | ||
31 | strm->adler = 1; /* to support ill-conceived Java test suite */ | ||
32 | state->mode = HEAD; | ||
33 | state->last = 0; | ||
34 | state->havedict = 0; | ||
35 | state->dmax = 32768U; | ||
36 | state->hold = 0; | ||
37 | state->bits = 0; | ||
38 | state->lencode = state->distcode = state->next = state->codes; | ||
15 | 39 | ||
16 | int zlib_inflateReset( | 40 | /* Initialise Window */ |
17 | z_streamp z | 41 | state->wsize = 1U << state->wbits; |
18 | ) | 42 | state->write = 0; |
43 | state->whave = 0; | ||
44 | |||
45 | return Z_OK; | ||
46 | } | ||
47 | |||
48 | #if 0 | ||
49 | int zlib_inflatePrime(z_streamp strm, int bits, int value) | ||
19 | { | 50 | { |
20 | if (z == NULL || z->state == NULL || z->workspace == NULL) | 51 | struct inflate_state *state; |
21 | return Z_STREAM_ERROR; | 52 | |
22 | z->total_in = z->total_out = 0; | 53 | if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; |
23 | z->msg = NULL; | 54 | state = (struct inflate_state *)strm->state; |
24 | z->state->mode = z->state->nowrap ? BLOCKS : METHOD; | 55 | if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; |
25 | zlib_inflate_blocks_reset(z->state->blocks, z, NULL); | 56 | value &= (1L << bits) - 1; |
26 | return Z_OK; | 57 | state->hold += value << state->bits; |
58 | state->bits += bits; | ||
59 | return Z_OK; | ||
27 | } | 60 | } |
61 | #endif | ||
62 | |||
63 | int zlib_inflateInit2(z_streamp strm, int windowBits) | ||
64 | { | ||
65 | struct inflate_state *state; | ||
66 | |||
67 | if (strm == NULL) return Z_STREAM_ERROR; | ||
68 | strm->msg = NULL; /* in case we return an error */ | ||
69 | |||
70 | state = &WS(strm)->inflate_state; | ||
71 | strm->state = (struct internal_state *)state; | ||
72 | |||
73 | if (windowBits < 0) { | ||
74 | state->wrap = 0; | ||
75 | windowBits = -windowBits; | ||
76 | } | ||
77 | else { | ||
78 | state->wrap = (windowBits >> 4) + 1; | ||
79 | } | ||
80 | if (windowBits < 8 || windowBits > 15) { | ||
81 | return Z_STREAM_ERROR; | ||
82 | } | ||
83 | state->wbits = (unsigned)windowBits; | ||
84 | state->window = &WS(strm)->working_window[0]; | ||
28 | 85 | ||
86 | return zlib_inflateReset(strm); | ||
87 | } | ||
29 | 88 | ||
30 | int zlib_inflateEnd( | 89 | /* |
31 | z_streamp z | 90 | Return state with length and distance decoding tables and index sizes set to |
32 | ) | 91 | fixed code decoding. This returns fixed tables from inffixed.h. |
92 | */ | ||
93 | static void zlib_fixedtables(struct inflate_state *state) | ||
33 | { | 94 | { |
34 | if (z == NULL || z->state == NULL || z->workspace == NULL) | 95 | # include "inffixed.h" |
35 | return Z_STREAM_ERROR; | 96 | state->lencode = lenfix; |
36 | if (z->state->blocks != NULL) | 97 | state->lenbits = 9; |
37 | zlib_inflate_blocks_free(z->state->blocks, z); | 98 | state->distcode = distfix; |
38 | z->state = NULL; | 99 | state->distbits = 5; |
39 | return Z_OK; | ||
40 | } | 100 | } |
41 | 101 | ||
42 | 102 | ||
43 | int zlib_inflateInit2_( | 103 | /* |
44 | z_streamp z, | 104 | Update the window with the last wsize (normally 32K) bytes written before |
45 | int w, | 105 | returning. This is only called when a window is already in use, or when |
46 | const char *version, | 106 | output has been written during this inflate call, but the end of the deflate |
47 | int stream_size | 107 | stream has not been reached yet. It is also called to window dictionary data |
48 | ) | 108 | when a dictionary is loaded. |
109 | |||
110 | Providing output buffers larger than 32K to inflate() should provide a speed | ||
111 | advantage, since only the last 32K of output is copied to the sliding window | ||
112 | upon return from inflate(), and since all distances after the first 32K of | ||
113 | output will fall in the output data, making match copies simpler and faster. | ||
114 | The advantage may be dependent on the size of the processor's data caches. | ||
115 | */ | ||
116 | static void zlib_updatewindow(z_streamp strm, unsigned out) | ||
49 | { | 117 | { |
50 | if (version == NULL || version[0] != ZLIB_VERSION[0] || | 118 | struct inflate_state *state; |
51 | stream_size != sizeof(z_stream) || z->workspace == NULL) | 119 | unsigned copy, dist; |
52 | return Z_VERSION_ERROR; | 120 | |
53 | 121 | state = (struct inflate_state *)strm->state; | |
54 | /* initialize state */ | 122 | |
55 | z->msg = NULL; | 123 | /* copy state->wsize or less output bytes into the circular window */ |
56 | z->state = &WS(z)->internal_state; | 124 | copy = out - strm->avail_out; |
57 | z->state->blocks = NULL; | 125 | if (copy >= state->wsize) { |
58 | 126 | memcpy(state->window, strm->next_out - state->wsize, state->wsize); | |
59 | /* handle undocumented nowrap option (no zlib header or check) */ | 127 | state->write = 0; |
60 | z->state->nowrap = 0; | 128 | state->whave = state->wsize; |
61 | if (w < 0) | 129 | } |
62 | { | 130 | else { |
63 | w = - w; | 131 | dist = state->wsize - state->write; |
64 | z->state->nowrap = 1; | 132 | if (dist > copy) dist = copy; |
65 | } | 133 | memcpy(state->window + state->write, strm->next_out - copy, dist); |
66 | 134 | copy -= dist; | |
67 | /* set window size */ | 135 | if (copy) { |
68 | if (w < 8 || w > 15) | 136 | memcpy(state->window, strm->next_out - copy, copy); |
69 | { | 137 | state->write = copy; |
70 | zlib_inflateEnd(z); | 138 | state->whave = state->wsize; |
71 | return Z_STREAM_ERROR; | 139 | } |
72 | } | 140 | else { |
73 | z->state->wbits = (uInt)w; | 141 | state->write += dist; |
74 | 142 | if (state->write == state->wsize) state->write = 0; | |
75 | /* create inflate_blocks state */ | 143 | if (state->whave < state->wsize) state->whave += dist; |
76 | if ((z->state->blocks = | 144 | } |
77 | zlib_inflate_blocks_new(z, z->state->nowrap ? NULL : zlib_adler32, (uInt)1 << w)) | 145 | } |
78 | == NULL) | ||
79 | { | ||
80 | zlib_inflateEnd(z); | ||
81 | return Z_MEM_ERROR; | ||
82 | } | ||
83 | |||
84 | /* reset state */ | ||
85 | zlib_inflateReset(z); | ||
86 | return Z_OK; | ||
87 | } | 146 | } |
88 | 147 | ||
89 | 148 | ||
@@ -91,157 +150,764 @@ int zlib_inflateInit2_( | |||
91 | * At the end of a Deflate-compressed PPP packet, we expect to have seen | 150 | * At the end of a Deflate-compressed PPP packet, we expect to have seen |
92 | * a `stored' block type value but not the (zero) length bytes. | 151 | * a `stored' block type value but not the (zero) length bytes. |
93 | */ | 152 | */ |
94 | static int zlib_inflate_packet_flush(inflate_blocks_statef *s) | 153 | /* |
154 | Returns true if inflate is currently at the end of a block generated by | ||
155 | Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP | ||
156 | implementation to provide an additional safety check. PPP uses | ||
157 | Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored | ||
158 | block. When decompressing, PPP checks that at the end of input packet, | ||
159 | inflate is waiting for these length bytes. | ||
160 | */ | ||
161 | static int zlib_inflateSyncPacket(z_streamp strm) | ||
95 | { | 162 | { |
96 | if (s->mode != LENS) | 163 | struct inflate_state *state; |
97 | return Z_DATA_ERROR; | 164 | |
98 | s->mode = TYPE; | 165 | if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; |
166 | state = (struct inflate_state *)strm->state; | ||
167 | |||
168 | if (state->mode == STORED && state->bits == 0) { | ||
169 | state->mode = TYPE; | ||
170 | return Z_OK; | ||
171 | } | ||
172 | return Z_DATA_ERROR; | ||
173 | } | ||
174 | |||
175 | /* Macros for inflate(): */ | ||
176 | |||
177 | /* check function to use adler32() for zlib or crc32() for gzip */ | ||
178 | #define UPDATE(check, buf, len) zlib_adler32(check, buf, len) | ||
179 | |||
180 | /* Load registers with state in inflate() for speed */ | ||
181 | #define LOAD() \ | ||
182 | do { \ | ||
183 | put = strm->next_out; \ | ||
184 | left = strm->avail_out; \ | ||
185 | next = strm->next_in; \ | ||
186 | have = strm->avail_in; \ | ||
187 | hold = state->hold; \ | ||
188 | bits = state->bits; \ | ||
189 | } while (0) | ||
190 | |||
191 | /* Restore state from registers in inflate() */ | ||
192 | #define RESTORE() \ | ||
193 | do { \ | ||
194 | strm->next_out = put; \ | ||
195 | strm->avail_out = left; \ | ||
196 | strm->next_in = next; \ | ||
197 | strm->avail_in = have; \ | ||
198 | state->hold = hold; \ | ||
199 | state->bits = bits; \ | ||
200 | } while (0) | ||
201 | |||
202 | /* Clear the input bit accumulator */ | ||
203 | #define INITBITS() \ | ||
204 | do { \ | ||
205 | hold = 0; \ | ||
206 | bits = 0; \ | ||
207 | } while (0) | ||
208 | |||
209 | /* Get a byte of input into the bit accumulator, or return from inflate() | ||
210 | if there is no input available. */ | ||
211 | #define PULLBYTE() \ | ||
212 | do { \ | ||
213 | if (have == 0) goto inf_leave; \ | ||
214 | have--; \ | ||
215 | hold += (unsigned long)(*next++) << bits; \ | ||
216 | bits += 8; \ | ||
217 | } while (0) | ||
218 | |||
219 | /* Assure that there are at least n bits in the bit accumulator. If there is | ||
220 | not enough available input to do that, then return from inflate(). */ | ||
221 | #define NEEDBITS(n) \ | ||
222 | do { \ | ||
223 | while (bits < (unsigned)(n)) \ | ||
224 | PULLBYTE(); \ | ||
225 | } while (0) | ||
226 | |||
227 | /* Return the low n bits of the bit accumulator (n < 16) */ | ||
228 | #define BITS(n) \ | ||
229 | ((unsigned)hold & ((1U << (n)) - 1)) | ||
230 | |||
231 | /* Remove n bits from the bit accumulator */ | ||
232 | #define DROPBITS(n) \ | ||
233 | do { \ | ||
234 | hold >>= (n); \ | ||
235 | bits -= (unsigned)(n); \ | ||
236 | } while (0) | ||
237 | |||
238 | /* Remove zero to seven bits as needed to go to a byte boundary */ | ||
239 | #define BYTEBITS() \ | ||
240 | do { \ | ||
241 | hold >>= bits & 7; \ | ||
242 | bits -= bits & 7; \ | ||
243 | } while (0) | ||
244 | |||
245 | /* Reverse the bytes in a 32-bit value */ | ||
246 | #define REVERSE(q) \ | ||
247 | ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ | ||
248 | (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) | ||
249 | |||
250 | /* | ||
251 | inflate() uses a state machine to process as much input data and generate as | ||
252 | much output data as possible before returning. The state machine is | ||
253 | structured roughly as follows: | ||
254 | |||
255 | for (;;) switch (state) { | ||
256 | ... | ||
257 | case STATEn: | ||
258 | if (not enough input data or output space to make progress) | ||
259 | return; | ||
260 | ... make progress ... | ||
261 | state = STATEm; | ||
262 | break; | ||
263 | ... | ||
264 | } | ||
265 | |||
266 | so when inflate() is called again, the same case is attempted again, and | ||
267 | if the appropriate resources are provided, the machine proceeds to the | ||
268 | next state. The NEEDBITS() macro is usually the way the state evaluates | ||
269 | whether it can proceed or should return. NEEDBITS() does the return if | ||
270 | the requested bits are not available. The typical use of the BITS macros | ||
271 | is: | ||
272 | |||
273 | NEEDBITS(n); | ||
274 | ... do something with BITS(n) ... | ||
275 | DROPBITS(n); | ||
276 | |||
277 | where NEEDBITS(n) either returns from inflate() if there isn't enough | ||
278 | input left to load n bits into the accumulator, or it continues. BITS(n) | ||
279 | gives the low n bits in the accumulator. When done, DROPBITS(n) drops | ||
280 | the low n bits off the accumulator. INITBITS() clears the accumulator | ||
281 | and sets the number of available bits to zero. BYTEBITS() discards just | ||
282 | enough bits to put the accumulator on a byte boundary. After BYTEBITS() | ||
283 | and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. | ||
284 | |||
285 | NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return | ||
286 | if there is no input available. The decoding of variable length codes uses | ||
287 | PULLBYTE() directly in order to pull just enough bytes to decode the next | ||
288 | code, and no more. | ||
289 | |||
290 | Some states loop until they get enough input, making sure that enough | ||
291 | state information is maintained to continue the loop where it left off | ||
292 | if NEEDBITS() returns in the loop. For example, want, need, and keep | ||
293 | would all have to actually be part of the saved state in case NEEDBITS() | ||
294 | returns: | ||
295 | |||
296 | case STATEw: | ||
297 | while (want < need) { | ||
298 | NEEDBITS(n); | ||
299 | keep[want++] = BITS(n); | ||
300 | DROPBITS(n); | ||
301 | } | ||
302 | state = STATEx; | ||
303 | case STATEx: | ||
304 | |||
305 | As shown above, if the next state is also the next case, then the break | ||
306 | is omitted. | ||
307 | |||
308 | A state may also return if there is not enough output space available to | ||
309 | complete that state. Those states are copying stored data, writing a | ||
310 | literal byte, and copying a matching string. | ||
311 | |||
312 | When returning, a "goto inf_leave" is used to update the total counters, | ||
313 | update the check value, and determine whether any progress has been made | ||
314 | during that inflate() call in order to return the proper return code. | ||
315 | Progress is defined as a change in either strm->avail_in or strm->avail_out. | ||
316 | When there is a window, goto inf_leave will update the window with the last | ||
317 | output written. If a goto inf_leave occurs in the middle of decompression | ||
318 | and there is no window currently, goto inf_leave will create one and copy | ||
319 | output to the window for the next call of inflate(). | ||
320 | |||
321 | In this implementation, the flush parameter of inflate() only affects the | ||
322 | return code (per zlib.h). inflate() always writes as much as possible to | ||
323 | strm->next_out, given the space available and the provided input--the effect | ||
324 | documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers | ||
325 | the allocation of and copying into a sliding window until necessary, which | ||
326 | provides the effect documented in zlib.h for Z_FINISH when the entire input | ||
327 | stream available. So the only thing the flush parameter actually does is: | ||
328 | when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it | ||
329 | will return Z_BUF_ERROR if it has not reached the end of the stream. | ||
330 | */ | ||
331 | |||
332 | int zlib_inflate(z_streamp strm, int flush) | ||
333 | { | ||
334 | struct inflate_state *state; | ||
335 | unsigned char *next; /* next input */ | ||
336 | unsigned char *put; /* next output */ | ||
337 | unsigned have, left; /* available input and output */ | ||
338 | unsigned long hold; /* bit buffer */ | ||
339 | unsigned bits; /* bits in bit buffer */ | ||
340 | unsigned in, out; /* save starting available input and output */ | ||
341 | unsigned copy; /* number of stored or match bytes to copy */ | ||
342 | unsigned char *from; /* where to copy match bytes from */ | ||
343 | code this; /* current decoding table entry */ | ||
344 | code last; /* parent table entry */ | ||
345 | unsigned len; /* length to copy for repeats, bits to drop */ | ||
346 | int ret; /* return code */ | ||
347 | static const unsigned short order[19] = /* permutation of code lengths */ | ||
348 | {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; | ||
349 | |||
350 | if (strm == NULL || strm->state == NULL || strm->next_out == NULL || | ||
351 | (strm->next_in == NULL && strm->avail_in != 0)) | ||
352 | return Z_STREAM_ERROR; | ||
353 | |||
354 | state = (struct inflate_state *)strm->state; | ||
355 | |||
356 | if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ | ||
357 | LOAD(); | ||
358 | in = have; | ||
359 | out = left; | ||
360 | ret = Z_OK; | ||
361 | for (;;) | ||
362 | switch (state->mode) { | ||
363 | case HEAD: | ||
364 | if (state->wrap == 0) { | ||
365 | state->mode = TYPEDO; | ||
366 | break; | ||
367 | } | ||
368 | NEEDBITS(16); | ||
369 | if ( | ||
370 | ((BITS(8) << 8) + (hold >> 8)) % 31) { | ||
371 | strm->msg = (char *)"incorrect header check"; | ||
372 | state->mode = BAD; | ||
373 | break; | ||
374 | } | ||
375 | if (BITS(4) != Z_DEFLATED) { | ||
376 | strm->msg = (char *)"unknown compression method"; | ||
377 | state->mode = BAD; | ||
378 | break; | ||
379 | } | ||
380 | DROPBITS(4); | ||
381 | len = BITS(4) + 8; | ||
382 | if (len > state->wbits) { | ||
383 | strm->msg = (char *)"invalid window size"; | ||
384 | state->mode = BAD; | ||
385 | break; | ||
386 | } | ||
387 | state->dmax = 1U << len; | ||
388 | strm->adler = state->check = zlib_adler32(0L, NULL, 0); | ||
389 | state->mode = hold & 0x200 ? DICTID : TYPE; | ||
390 | INITBITS(); | ||
391 | break; | ||
392 | case DICTID: | ||
393 | NEEDBITS(32); | ||
394 | strm->adler = state->check = REVERSE(hold); | ||
395 | INITBITS(); | ||
396 | state->mode = DICT; | ||
397 | case DICT: | ||
398 | if (state->havedict == 0) { | ||
399 | RESTORE(); | ||
400 | return Z_NEED_DICT; | ||
401 | } | ||
402 | strm->adler = state->check = zlib_adler32(0L, NULL, 0); | ||
403 | state->mode = TYPE; | ||
404 | case TYPE: | ||
405 | if (flush == Z_BLOCK) goto inf_leave; | ||
406 | case TYPEDO: | ||
407 | if (state->last) { | ||
408 | BYTEBITS(); | ||
409 | state->mode = CHECK; | ||
410 | break; | ||
411 | } | ||
412 | NEEDBITS(3); | ||
413 | state->last = BITS(1); | ||
414 | DROPBITS(1); | ||
415 | switch (BITS(2)) { | ||
416 | case 0: /* stored block */ | ||
417 | state->mode = STORED; | ||
418 | break; | ||
419 | case 1: /* fixed block */ | ||
420 | zlib_fixedtables(state); | ||
421 | state->mode = LEN; /* decode codes */ | ||
422 | break; | ||
423 | case 2: /* dynamic block */ | ||
424 | state->mode = TABLE; | ||
425 | break; | ||
426 | case 3: | ||
427 | strm->msg = (char *)"invalid block type"; | ||
428 | state->mode = BAD; | ||
429 | } | ||
430 | DROPBITS(2); | ||
431 | break; | ||
432 | case STORED: | ||
433 | BYTEBITS(); /* go to byte boundary */ | ||
434 | NEEDBITS(32); | ||
435 | if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { | ||
436 | strm->msg = (char *)"invalid stored block lengths"; | ||
437 | state->mode = BAD; | ||
438 | break; | ||
439 | } | ||
440 | state->length = (unsigned)hold & 0xffff; | ||
441 | INITBITS(); | ||
442 | state->mode = COPY; | ||
443 | case COPY: | ||
444 | copy = state->length; | ||
445 | if (copy) { | ||
446 | if (copy > have) copy = have; | ||
447 | if (copy > left) copy = left; | ||
448 | if (copy == 0) goto inf_leave; | ||
449 | memcpy(put, next, copy); | ||
450 | have -= copy; | ||
451 | next += copy; | ||
452 | left -= copy; | ||
453 | put += copy; | ||
454 | state->length -= copy; | ||
455 | break; | ||
456 | } | ||
457 | state->mode = TYPE; | ||
458 | break; | ||
459 | case TABLE: | ||
460 | NEEDBITS(14); | ||
461 | state->nlen = BITS(5) + 257; | ||
462 | DROPBITS(5); | ||
463 | state->ndist = BITS(5) + 1; | ||
464 | DROPBITS(5); | ||
465 | state->ncode = BITS(4) + 4; | ||
466 | DROPBITS(4); | ||
467 | #ifndef PKZIP_BUG_WORKAROUND | ||
468 | if (state->nlen > 286 || state->ndist > 30) { | ||
469 | strm->msg = (char *)"too many length or distance symbols"; | ||
470 | state->mode = BAD; | ||
471 | break; | ||
472 | } | ||
473 | #endif | ||
474 | state->have = 0; | ||
475 | state->mode = LENLENS; | ||
476 | case LENLENS: | ||
477 | while (state->have < state->ncode) { | ||
478 | NEEDBITS(3); | ||
479 | state->lens[order[state->have++]] = (unsigned short)BITS(3); | ||
480 | DROPBITS(3); | ||
481 | } | ||
482 | while (state->have < 19) | ||
483 | state->lens[order[state->have++]] = 0; | ||
484 | state->next = state->codes; | ||
485 | state->lencode = (code const *)(state->next); | ||
486 | state->lenbits = 7; | ||
487 | ret = zlib_inflate_table(CODES, state->lens, 19, &(state->next), | ||
488 | &(state->lenbits), state->work); | ||
489 | if (ret) { | ||
490 | strm->msg = (char *)"invalid code lengths set"; | ||
491 | state->mode = BAD; | ||
492 | break; | ||
493 | } | ||
494 | state->have = 0; | ||
495 | state->mode = CODELENS; | ||
496 | case CODELENS: | ||
497 | while (state->have < state->nlen + state->ndist) { | ||
498 | for (;;) { | ||
499 | this = state->lencode[BITS(state->lenbits)]; | ||
500 | if ((unsigned)(this.bits) <= bits) break; | ||
501 | PULLBYTE(); | ||
502 | } | ||
503 | if (this.val < 16) { | ||
504 | NEEDBITS(this.bits); | ||
505 | DROPBITS(this.bits); | ||
506 | state->lens[state->have++] = this.val; | ||
507 | } | ||
508 | else { | ||
509 | if (this.val == 16) { | ||
510 | NEEDBITS(this.bits + 2); | ||
511 | DROPBITS(this.bits); | ||
512 | if (state->have == 0) { | ||
513 | strm->msg = (char *)"invalid bit length repeat"; | ||
514 | state->mode = BAD; | ||
515 | break; | ||
516 | } | ||
517 | len = state->lens[state->have - 1]; | ||
518 | copy = 3 + BITS(2); | ||
519 | DROPBITS(2); | ||
520 | } | ||
521 | else if (this.val == 17) { | ||
522 | NEEDBITS(this.bits + 3); | ||
523 | DROPBITS(this.bits); | ||
524 | len = 0; | ||
525 | copy = 3 + BITS(3); | ||
526 | DROPBITS(3); | ||
527 | } | ||
528 | else { | ||
529 | NEEDBITS(this.bits + 7); | ||
530 | DROPBITS(this.bits); | ||
531 | len = 0; | ||
532 | copy = 11 + BITS(7); | ||
533 | DROPBITS(7); | ||
534 | } | ||
535 | if (state->have + copy > state->nlen + state->ndist) { | ||
536 | strm->msg = (char *)"invalid bit length repeat"; | ||
537 | state->mode = BAD; | ||
538 | break; | ||
539 | } | ||
540 | while (copy--) | ||
541 | state->lens[state->have++] = (unsigned short)len; | ||
542 | } | ||
543 | } | ||
544 | |||
545 | /* handle error breaks in while */ | ||
546 | if (state->mode == BAD) break; | ||
547 | |||
548 | /* build code tables */ | ||
549 | state->next = state->codes; | ||
550 | state->lencode = (code const *)(state->next); | ||
551 | state->lenbits = 9; | ||
552 | ret = zlib_inflate_table(LENS, state->lens, state->nlen, &(state->next), | ||
553 | &(state->lenbits), state->work); | ||
554 | if (ret) { | ||
555 | strm->msg = (char *)"invalid literal/lengths set"; | ||
556 | state->mode = BAD; | ||
557 | break; | ||
558 | } | ||
559 | state->distcode = (code const *)(state->next); | ||
560 | state->distbits = 6; | ||
561 | ret = zlib_inflate_table(DISTS, state->lens + state->nlen, state->ndist, | ||
562 | &(state->next), &(state->distbits), state->work); | ||
563 | if (ret) { | ||
564 | strm->msg = (char *)"invalid distances set"; | ||
565 | state->mode = BAD; | ||
566 | break; | ||
567 | } | ||
568 | state->mode = LEN; | ||
569 | case LEN: | ||
570 | if (have >= 6 && left >= 258) { | ||
571 | RESTORE(); | ||
572 | inflate_fast(strm, out); | ||
573 | LOAD(); | ||
574 | break; | ||
575 | } | ||
576 | for (;;) { | ||
577 | this = state->lencode[BITS(state->lenbits)]; | ||
578 | if ((unsigned)(this.bits) <= bits) break; | ||
579 | PULLBYTE(); | ||
580 | } | ||
581 | if (this.op && (this.op & 0xf0) == 0) { | ||
582 | last = this; | ||
583 | for (;;) { | ||
584 | this = state->lencode[last.val + | ||
585 | (BITS(last.bits + last.op) >> last.bits)]; | ||
586 | if ((unsigned)(last.bits + this.bits) <= bits) break; | ||
587 | PULLBYTE(); | ||
588 | } | ||
589 | DROPBITS(last.bits); | ||
590 | } | ||
591 | DROPBITS(this.bits); | ||
592 | state->length = (unsigned)this.val; | ||
593 | if ((int)(this.op) == 0) { | ||
594 | state->mode = LIT; | ||
595 | break; | ||
596 | } | ||
597 | if (this.op & 32) { | ||
598 | state->mode = TYPE; | ||
599 | break; | ||
600 | } | ||
601 | if (this.op & 64) { | ||
602 | strm->msg = (char *)"invalid literal/length code"; | ||
603 | state->mode = BAD; | ||
604 | break; | ||
605 | } | ||
606 | state->extra = (unsigned)(this.op) & 15; | ||
607 | state->mode = LENEXT; | ||
608 | case LENEXT: | ||
609 | if (state->extra) { | ||
610 | NEEDBITS(state->extra); | ||
611 | state->length += BITS(state->extra); | ||
612 | DROPBITS(state->extra); | ||
613 | } | ||
614 | state->mode = DIST; | ||
615 | case DIST: | ||
616 | for (;;) { | ||
617 | this = state->distcode[BITS(state->distbits)]; | ||
618 | if ((unsigned)(this.bits) <= bits) break; | ||
619 | PULLBYTE(); | ||
620 | } | ||
621 | if ((this.op & 0xf0) == 0) { | ||
622 | last = this; | ||
623 | for (;;) { | ||
624 | this = state->distcode[last.val + | ||
625 | (BITS(last.bits + last.op) >> last.bits)]; | ||
626 | if ((unsigned)(last.bits + this.bits) <= bits) break; | ||
627 | PULLBYTE(); | ||
628 | } | ||
629 | DROPBITS(last.bits); | ||
630 | } | ||
631 | DROPBITS(this.bits); | ||
632 | if (this.op & 64) { | ||
633 | strm->msg = (char *)"invalid distance code"; | ||
634 | state->mode = BAD; | ||
635 | break; | ||
636 | } | ||
637 | state->offset = (unsigned)this.val; | ||
638 | state->extra = (unsigned)(this.op) & 15; | ||
639 | state->mode = DISTEXT; | ||
640 | case DISTEXT: | ||
641 | if (state->extra) { | ||
642 | NEEDBITS(state->extra); | ||
643 | state->offset += BITS(state->extra); | ||
644 | DROPBITS(state->extra); | ||
645 | } | ||
646 | #ifdef INFLATE_STRICT | ||
647 | if (state->offset > state->dmax) { | ||
648 | strm->msg = (char *)"invalid distance too far back"; | ||
649 | state->mode = BAD; | ||
650 | break; | ||
651 | } | ||
652 | #endif | ||
653 | if (state->offset > state->whave + out - left) { | ||
654 | strm->msg = (char *)"invalid distance too far back"; | ||
655 | state->mode = BAD; | ||
656 | break; | ||
657 | } | ||
658 | state->mode = MATCH; | ||
659 | case MATCH: | ||
660 | if (left == 0) goto inf_leave; | ||
661 | copy = out - left; | ||
662 | if (state->offset > copy) { /* copy from window */ | ||
663 | copy = state->offset - copy; | ||
664 | if (copy > state->write) { | ||
665 | copy -= state->write; | ||
666 | from = state->window + (state->wsize - copy); | ||
667 | } | ||
668 | else | ||
669 | from = state->window + (state->write - copy); | ||
670 | if (copy > state->length) copy = state->length; | ||
671 | } | ||
672 | else { /* copy from output */ | ||
673 | from = put - state->offset; | ||
674 | copy = state->length; | ||
675 | } | ||
676 | if (copy > left) copy = left; | ||
677 | left -= copy; | ||
678 | state->length -= copy; | ||
679 | do { | ||
680 | *put++ = *from++; | ||
681 | } while (--copy); | ||
682 | if (state->length == 0) state->mode = LEN; | ||
683 | break; | ||
684 | case LIT: | ||
685 | if (left == 0) goto inf_leave; | ||
686 | *put++ = (unsigned char)(state->length); | ||
687 | left--; | ||
688 | state->mode = LEN; | ||
689 | break; | ||
690 | case CHECK: | ||
691 | if (state->wrap) { | ||
692 | NEEDBITS(32); | ||
693 | out -= left; | ||
694 | strm->total_out += out; | ||
695 | state->total += out; | ||
696 | if (out) | ||
697 | strm->adler = state->check = | ||
698 | UPDATE(state->check, put - out, out); | ||
699 | out = left; | ||
700 | if (( | ||
701 | REVERSE(hold)) != state->check) { | ||
702 | strm->msg = (char *)"incorrect data check"; | ||
703 | state->mode = BAD; | ||
704 | break; | ||
705 | } | ||
706 | INITBITS(); | ||
707 | } | ||
708 | state->mode = DONE; | ||
709 | case DONE: | ||
710 | ret = Z_STREAM_END; | ||
711 | goto inf_leave; | ||
712 | case BAD: | ||
713 | ret = Z_DATA_ERROR; | ||
714 | goto inf_leave; | ||
715 | case MEM: | ||
716 | return Z_MEM_ERROR; | ||
717 | case SYNC: | ||
718 | default: | ||
719 | return Z_STREAM_ERROR; | ||
720 | } | ||
721 | |||
722 | /* | ||
723 | Return from inflate(), updating the total counts and the check value. | ||
724 | If there was no progress during the inflate() call, return a buffer | ||
725 | error. Call zlib_updatewindow() to create and/or update the window state. | ||
726 | */ | ||
727 | inf_leave: | ||
728 | RESTORE(); | ||
729 | if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) | ||
730 | zlib_updatewindow(strm, out); | ||
731 | |||
732 | in -= strm->avail_in; | ||
733 | out -= strm->avail_out; | ||
734 | strm->total_in += in; | ||
735 | strm->total_out += out; | ||
736 | state->total += out; | ||
737 | if (state->wrap && out) | ||
738 | strm->adler = state->check = | ||
739 | UPDATE(state->check, strm->next_out - out, out); | ||
740 | |||
741 | strm->data_type = state->bits + (state->last ? 64 : 0) + | ||
742 | (state->mode == TYPE ? 128 : 0); | ||
743 | if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) | ||
744 | ret = Z_BUF_ERROR; | ||
745 | |||
746 | if (flush == Z_PACKET_FLUSH && ret == Z_OK && | ||
747 | (strm->avail_out != 0 || strm->avail_in == 0)) | ||
748 | return zlib_inflateSyncPacket(strm); | ||
749 | return ret; | ||
750 | } | ||
751 | |||
752 | int zlib_inflateEnd(z_streamp strm) | ||
753 | { | ||
754 | if (strm == NULL || strm->state == NULL) | ||
755 | return Z_STREAM_ERROR; | ||
99 | return Z_OK; | 756 | return Z_OK; |
100 | } | 757 | } |
101 | 758 | ||
759 | #if 0 | ||
760 | int zlib_inflateSetDictionary(z_streamp strm, const Byte *dictionary, | ||
761 | uInt dictLength) | ||
762 | { | ||
763 | struct inflate_state *state; | ||
764 | unsigned long id; | ||
765 | |||
766 | /* check state */ | ||
767 | if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; | ||
768 | state = (struct inflate_state *)strm->state; | ||
769 | if (state->wrap != 0 && state->mode != DICT) | ||
770 | return Z_STREAM_ERROR; | ||
771 | |||
772 | /* check for correct dictionary id */ | ||
773 | if (state->mode == DICT) { | ||
774 | id = zlib_adler32(0L, NULL, 0); | ||
775 | id = zlib_adler32(id, dictionary, dictLength); | ||
776 | if (id != state->check) | ||
777 | return Z_DATA_ERROR; | ||
778 | } | ||
779 | |||
780 | /* copy dictionary to window */ | ||
781 | zlib_updatewindow(strm, strm->avail_out); | ||
102 | 782 | ||
103 | int zlib_inflateInit_( | 783 | if (dictLength > state->wsize) { |
104 | z_streamp z, | 784 | memcpy(state->window, dictionary + dictLength - state->wsize, |
105 | const char *version, | 785 | state->wsize); |
106 | int stream_size | 786 | state->whave = state->wsize; |
107 | ) | 787 | } |
788 | else { | ||
789 | memcpy(state->window + state->wsize - dictLength, dictionary, | ||
790 | dictLength); | ||
791 | state->whave = dictLength; | ||
792 | } | ||
793 | state->havedict = 1; | ||
794 | return Z_OK; | ||
795 | } | ||
796 | #endif | ||
797 | |||
798 | #if 0 | ||
799 | /* | ||
800 | Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found | ||
801 | or when out of input. When called, *have is the number of pattern bytes | ||
802 | found in order so far, in 0..3. On return *have is updated to the new | ||
803 | state. If on return *have equals four, then the pattern was found and the | ||
804 | return value is how many bytes were read including the last byte of the | ||
805 | pattern. If *have is less than four, then the pattern has not been found | ||
806 | yet and the return value is len. In the latter case, zlib_syncsearch() can be | ||
807 | called again with more data and the *have state. *have is initialized to | ||
808 | zero for the first call. | ||
809 | */ | ||
810 | static unsigned zlib_syncsearch(unsigned *have, unsigned char *buf, | ||
811 | unsigned len) | ||
108 | { | 812 | { |
109 | return zlib_inflateInit2_(z, DEF_WBITS, version, stream_size); | 813 | unsigned got; |
814 | unsigned next; | ||
815 | |||
816 | got = *have; | ||
817 | next = 0; | ||
818 | while (next < len && got < 4) { | ||
819 | if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) | ||
820 | got++; | ||
821 | else if (buf[next]) | ||
822 | got = 0; | ||
823 | else | ||
824 | got = 4 - got; | ||
825 | next++; | ||
826 | } | ||
827 | *have = got; | ||
828 | return next; | ||
110 | } | 829 | } |
830 | #endif | ||
111 | 831 | ||
112 | #undef NEEDBYTE | 832 | #if 0 |
113 | #undef NEXTBYTE | 833 | int zlib_inflateSync(z_streamp strm) |
114 | #define NEEDBYTE {if(z->avail_in==0)goto empty;r=trv;} | 834 | { |
115 | #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) | 835 | unsigned len; /* number of bytes to look at or looked at */ |
836 | unsigned long in, out; /* temporary to save total_in and total_out */ | ||
837 | unsigned char buf[4]; /* to restore bit buffer to byte string */ | ||
838 | struct inflate_state *state; | ||
839 | |||
840 | /* check parameters */ | ||
841 | if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR; | ||
842 | state = (struct inflate_state *)strm->state; | ||
843 | if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; | ||
844 | |||
845 | /* if first time, start search in bit buffer */ | ||
846 | if (state->mode != SYNC) { | ||
847 | state->mode = SYNC; | ||
848 | state->hold <<= state->bits & 7; | ||
849 | state->bits -= state->bits & 7; | ||
850 | len = 0; | ||
851 | while (state->bits >= 8) { | ||
852 | buf[len++] = (unsigned char)(state->hold); | ||
853 | state->hold >>= 8; | ||
854 | state->bits -= 8; | ||
855 | } | ||
856 | state->have = 0; | ||
857 | zlib_syncsearch(&(state->have), buf, len); | ||
858 | } | ||
859 | |||
860 | /* search available input */ | ||
861 | len = zlib_syncsearch(&(state->have), strm->next_in, strm->avail_in); | ||
862 | strm->avail_in -= len; | ||
863 | strm->next_in += len; | ||
864 | strm->total_in += len; | ||
865 | |||
866 | /* return no joy or set up to restart inflate() on a new block */ | ||
867 | if (state->have != 4) return Z_DATA_ERROR; | ||
868 | in = strm->total_in; out = strm->total_out; | ||
869 | zlib_inflateReset(strm); | ||
870 | strm->total_in = in; strm->total_out = out; | ||
871 | state->mode = TYPE; | ||
872 | return Z_OK; | ||
873 | } | ||
874 | #endif | ||
116 | 875 | ||
117 | int zlib_inflate( | 876 | /* |
118 | z_streamp z, | 877 | * This subroutine adds the data at next_in/avail_in to the output history |
119 | int f | 878 | * without performing any output. The output buffer must be "caught up"; |
120 | ) | 879 | * i.e. no pending output but this should always be the case. The state must |
880 | * be waiting on the start of a block (i.e. mode == TYPE or HEAD). On exit, | ||
881 | * the output will also be caught up, and the checksum will have been updated | ||
882 | * if need be. | ||
883 | */ | ||
884 | int zlib_inflateIncomp(z_stream *z) | ||
121 | { | 885 | { |
122 | int r, trv; | 886 | struct inflate_state *state = (struct inflate_state *)z->state; |
123 | uInt b; | 887 | Byte *saved_no = z->next_out; |
124 | 888 | uInt saved_ao = z->avail_out; | |
125 | if (z == NULL || z->state == NULL || z->next_in == NULL) | 889 | |
126 | return Z_STREAM_ERROR; | 890 | if (state->mode != TYPE && state->mode != HEAD) |
127 | trv = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; | 891 | return Z_DATA_ERROR; |
128 | r = Z_BUF_ERROR; | 892 | |
129 | while (1) switch (z->state->mode) | 893 | /* Setup some variables to allow misuse of updateWindow */ |
130 | { | 894 | z->avail_out = 0; |
131 | case METHOD: | 895 | z->next_out = z->next_in + z->avail_in; |
132 | NEEDBYTE | 896 | |
133 | if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) | 897 | zlib_updatewindow(z, z->avail_in); |
134 | { | 898 | |
135 | z->state->mode = I_BAD; | 899 | /* Restore saved variables */ |
136 | z->msg = (char*)"unknown compression method"; | 900 | z->avail_out = saved_ao; |
137 | z->state->sub.marker = 5; /* can't try inflateSync */ | 901 | z->next_out = saved_no; |
138 | break; | 902 | |
139 | } | 903 | z->adler = state->check = |
140 | if ((z->state->sub.method >> 4) + 8 > z->state->wbits) | 904 | UPDATE(state->check, z->next_in, z->avail_in); |
141 | { | 905 | |
142 | z->state->mode = I_BAD; | 906 | z->total_out += z->avail_in; |
143 | z->msg = (char*)"invalid window size"; | 907 | z->total_in += z->avail_in; |
144 | z->state->sub.marker = 5; /* can't try inflateSync */ | 908 | z->next_in += z->avail_in; |
145 | break; | 909 | state->total += z->avail_in; |
146 | } | 910 | z->avail_in = 0; |
147 | z->state->mode = FLAG; | 911 | |
148 | case FLAG: | 912 | return Z_OK; |
149 | NEEDBYTE | ||
150 | b = NEXTBYTE; | ||
151 | if (((z->state->sub.method << 8) + b) % 31) | ||
152 | { | ||
153 | z->state->mode = I_BAD; | ||
154 | z->msg = (char*)"incorrect header check"; | ||
155 | z->state->sub.marker = 5; /* can't try inflateSync */ | ||
156 | break; | ||
157 | } | ||
158 | if (!(b & PRESET_DICT)) | ||
159 | { | ||
160 | z->state->mode = BLOCKS; | ||
161 | break; | ||
162 | } | ||
163 | z->state->mode = DICT4; | ||
164 | case DICT4: | ||
165 | NEEDBYTE | ||
166 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; | ||
167 | z->state->mode = DICT3; | ||
168 | case DICT3: | ||
169 | NEEDBYTE | ||
170 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; | ||
171 | z->state->mode = DICT2; | ||
172 | case DICT2: | ||
173 | NEEDBYTE | ||
174 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; | ||
175 | z->state->mode = DICT1; | ||
176 | case DICT1: | ||
177 | NEEDBYTE | ||
178 | z->state->sub.check.need += (uLong)NEXTBYTE; | ||
179 | z->adler = z->state->sub.check.need; | ||
180 | z->state->mode = DICT0; | ||
181 | return Z_NEED_DICT; | ||
182 | case DICT0: | ||
183 | z->state->mode = I_BAD; | ||
184 | z->msg = (char*)"need dictionary"; | ||
185 | z->state->sub.marker = 0; /* can try inflateSync */ | ||
186 | return Z_STREAM_ERROR; | ||
187 | case BLOCKS: | ||
188 | r = zlib_inflate_blocks(z->state->blocks, z, r); | ||
189 | if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0) | ||
190 | r = zlib_inflate_packet_flush(z->state->blocks); | ||
191 | if (r == Z_DATA_ERROR) | ||
192 | { | ||
193 | z->state->mode = I_BAD; | ||
194 | z->state->sub.marker = 0; /* can try inflateSync */ | ||
195 | break; | ||
196 | } | ||
197 | if (r == Z_OK) | ||
198 | r = trv; | ||
199 | if (r != Z_STREAM_END) | ||
200 | return r; | ||
201 | r = trv; | ||
202 | zlib_inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); | ||
203 | if (z->state->nowrap) | ||
204 | { | ||
205 | z->state->mode = I_DONE; | ||
206 | break; | ||
207 | } | ||
208 | z->state->mode = CHECK4; | ||
209 | case CHECK4: | ||
210 | NEEDBYTE | ||
211 | z->state->sub.check.need = (uLong)NEXTBYTE << 24; | ||
212 | z->state->mode = CHECK3; | ||
213 | case CHECK3: | ||
214 | NEEDBYTE | ||
215 | z->state->sub.check.need += (uLong)NEXTBYTE << 16; | ||
216 | z->state->mode = CHECK2; | ||
217 | case CHECK2: | ||
218 | NEEDBYTE | ||
219 | z->state->sub.check.need += (uLong)NEXTBYTE << 8; | ||
220 | z->state->mode = CHECK1; | ||
221 | case CHECK1: | ||
222 | NEEDBYTE | ||
223 | z->state->sub.check.need += (uLong)NEXTBYTE; | ||
224 | |||
225 | if (z->state->sub.check.was != z->state->sub.check.need) | ||
226 | { | ||
227 | z->state->mode = I_BAD; | ||
228 | z->msg = (char*)"incorrect data check"; | ||
229 | z->state->sub.marker = 5; /* can't try inflateSync */ | ||
230 | break; | ||
231 | } | ||
232 | z->state->mode = I_DONE; | ||
233 | case I_DONE: | ||
234 | return Z_STREAM_END; | ||
235 | case I_BAD: | ||
236 | return Z_DATA_ERROR; | ||
237 | default: | ||
238 | return Z_STREAM_ERROR; | ||
239 | } | ||
240 | empty: | ||
241 | if (f != Z_PACKET_FLUSH) | ||
242 | return r; | ||
243 | z->state->mode = I_BAD; | ||
244 | z->msg = (char *)"need more for packet flush"; | ||
245 | z->state->sub.marker = 0; /* can try inflateSync */ | ||
246 | return Z_DATA_ERROR; | ||
247 | } | 913 | } |
diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h new file mode 100644 index 000000000000..df8a6c92052d --- /dev/null +++ b/lib/zlib_inflate/inflate.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* inflate.h -- internal inflate state definition | ||
2 | * Copyright (C) 1995-2004 Mark Adler | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | */ | ||
5 | |||
6 | /* WARNING: this file should *not* be used by applications. It is | ||
7 | part of the implementation of the compression library and is | ||
8 | subject to change. Applications should only use zlib.h. | ||
9 | */ | ||
10 | |||
11 | /* Possible inflate modes between inflate() calls */ | ||
12 | typedef enum { | ||
13 | HEAD, /* i: waiting for magic header */ | ||
14 | FLAGS, /* i: waiting for method and flags (gzip) */ | ||
15 | TIME, /* i: waiting for modification time (gzip) */ | ||
16 | OS, /* i: waiting for extra flags and operating system (gzip) */ | ||
17 | EXLEN, /* i: waiting for extra length (gzip) */ | ||
18 | EXTRA, /* i: waiting for extra bytes (gzip) */ | ||
19 | NAME, /* i: waiting for end of file name (gzip) */ | ||
20 | COMMENT, /* i: waiting for end of comment (gzip) */ | ||
21 | HCRC, /* i: waiting for header crc (gzip) */ | ||
22 | DICTID, /* i: waiting for dictionary check value */ | ||
23 | DICT, /* waiting for inflateSetDictionary() call */ | ||
24 | TYPE, /* i: waiting for type bits, including last-flag bit */ | ||
25 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ | ||
26 | STORED, /* i: waiting for stored size (length and complement) */ | ||
27 | COPY, /* i/o: waiting for input or output to copy stored block */ | ||
28 | TABLE, /* i: waiting for dynamic block table lengths */ | ||
29 | LENLENS, /* i: waiting for code length code lengths */ | ||
30 | CODELENS, /* i: waiting for length/lit and distance code lengths */ | ||
31 | LEN, /* i: waiting for length/lit code */ | ||
32 | LENEXT, /* i: waiting for length extra bits */ | ||
33 | DIST, /* i: waiting for distance code */ | ||
34 | DISTEXT, /* i: waiting for distance extra bits */ | ||
35 | MATCH, /* o: waiting for output space to copy string */ | ||
36 | LIT, /* o: waiting for output space to write literal */ | ||
37 | CHECK, /* i: waiting for 32-bit check value */ | ||
38 | LENGTH, /* i: waiting for 32-bit length (gzip) */ | ||
39 | DONE, /* finished check, done -- remain here until reset */ | ||
40 | BAD, /* got a data error -- remain here until reset */ | ||
41 | MEM, /* got an inflate() memory error -- remain here until reset */ | ||
42 | SYNC /* looking for synchronization bytes to restart inflate() */ | ||
43 | } inflate_mode; | ||
44 | |||
45 | /* | ||
46 | State transitions between above modes - | ||
47 | |||
48 | (most modes can go to the BAD or MEM mode -- not shown for clarity) | ||
49 | |||
50 | Process header: | ||
51 | HEAD -> (gzip) or (zlib) | ||
52 | (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME | ||
53 | NAME -> COMMENT -> HCRC -> TYPE | ||
54 | (zlib) -> DICTID or TYPE | ||
55 | DICTID -> DICT -> TYPE | ||
56 | Read deflate blocks: | ||
57 | TYPE -> STORED or TABLE or LEN or CHECK | ||
58 | STORED -> COPY -> TYPE | ||
59 | TABLE -> LENLENS -> CODELENS -> LEN | ||
60 | Read deflate codes: | ||
61 | LEN -> LENEXT or LIT or TYPE | ||
62 | LENEXT -> DIST -> DISTEXT -> MATCH -> LEN | ||
63 | LIT -> LEN | ||
64 | Process trailer: | ||
65 | CHECK -> LENGTH -> DONE | ||
66 | */ | ||
67 | |||
68 | /* state maintained between inflate() calls. Approximately 7K bytes. */ | ||
69 | struct inflate_state { | ||
70 | inflate_mode mode; /* current inflate mode */ | ||
71 | int last; /* true if processing last block */ | ||
72 | int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ | ||
73 | int havedict; /* true if dictionary provided */ | ||
74 | int flags; /* gzip header method and flags (0 if zlib) */ | ||
75 | unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ | ||
76 | unsigned long check; /* protected copy of check value */ | ||
77 | unsigned long total; /* protected copy of output count */ | ||
78 | /* gz_headerp head; */ /* where to save gzip header information */ | ||
79 | /* sliding window */ | ||
80 | unsigned wbits; /* log base 2 of requested window size */ | ||
81 | unsigned wsize; /* window size or zero if not using window */ | ||
82 | unsigned whave; /* valid bytes in the window */ | ||
83 | unsigned write; /* window write index */ | ||
84 | unsigned char *window; /* allocated sliding window, if needed */ | ||
85 | /* bit accumulator */ | ||
86 | unsigned long hold; /* input bit accumulator */ | ||
87 | unsigned bits; /* number of bits in "in" */ | ||
88 | /* for string and stored block copying */ | ||
89 | unsigned length; /* literal or length of data to copy */ | ||
90 | unsigned offset; /* distance back to copy string from */ | ||
91 | /* for table and code decoding */ | ||
92 | unsigned extra; /* extra bits needed */ | ||
93 | /* fixed and dynamic code tables */ | ||
94 | code const *lencode; /* starting table for length/literal codes */ | ||
95 | code const *distcode; /* starting table for distance codes */ | ||
96 | unsigned lenbits; /* index bits for lencode */ | ||
97 | unsigned distbits; /* index bits for distcode */ | ||
98 | /* dynamic table building */ | ||
99 | unsigned ncode; /* number of code length code lengths */ | ||
100 | unsigned nlen; /* number of length code lengths */ | ||
101 | unsigned ndist; /* number of distance code lengths */ | ||
102 | unsigned have; /* number of code lengths in lens[] */ | ||
103 | code *next; /* next available space in codes[] */ | ||
104 | unsigned short lens[320]; /* temporary storage for code lengths */ | ||
105 | unsigned short work[288]; /* work area for code table building */ | ||
106 | code codes[ENOUGH]; /* space for code tables */ | ||
107 | }; | ||
diff --git a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c index ef49738f57ec..2061d4f06765 100644 --- a/lib/zlib_inflate/inflate_syms.c +++ b/lib/zlib_inflate/inflate_syms.c | |||
@@ -12,8 +12,7 @@ | |||
12 | 12 | ||
13 | EXPORT_SYMBOL(zlib_inflate_workspacesize); | 13 | EXPORT_SYMBOL(zlib_inflate_workspacesize); |
14 | EXPORT_SYMBOL(zlib_inflate); | 14 | EXPORT_SYMBOL(zlib_inflate); |
15 | EXPORT_SYMBOL(zlib_inflateInit_); | 15 | EXPORT_SYMBOL(zlib_inflateInit2); |
16 | EXPORT_SYMBOL(zlib_inflateInit2_); | ||
17 | EXPORT_SYMBOL(zlib_inflateEnd); | 16 | EXPORT_SYMBOL(zlib_inflateEnd); |
18 | EXPORT_SYMBOL(zlib_inflateReset); | 17 | EXPORT_SYMBOL(zlib_inflateReset); |
19 | EXPORT_SYMBOL(zlib_inflateIncomp); | 18 | EXPORT_SYMBOL(zlib_inflateIncomp); |
diff --git a/lib/zlib_inflate/inflate_sync.c b/lib/zlib_inflate/inflate_sync.c deleted file mode 100644 index 61411ff89d61..000000000000 --- a/lib/zlib_inflate/inflate_sync.c +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | /* inflate.c -- zlib interface to inflate modules | ||
2 | * Copyright (C) 1995-1998 Mark Adler | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | */ | ||
5 | |||
6 | #include <linux/zutil.h> | ||
7 | #include "infblock.h" | ||
8 | #include "infutil.h" | ||
9 | |||
10 | #if 0 | ||
11 | int zlib_inflateSync( | ||
12 | z_streamp z | ||
13 | ) | ||
14 | { | ||
15 | uInt n; /* number of bytes to look at */ | ||
16 | Byte *p; /* pointer to bytes */ | ||
17 | uInt m; /* number of marker bytes found in a row */ | ||
18 | uLong r, w; /* temporaries to save total_in and total_out */ | ||
19 | |||
20 | /* set up */ | ||
21 | if (z == NULL || z->state == NULL) | ||
22 | return Z_STREAM_ERROR; | ||
23 | if (z->state->mode != I_BAD) | ||
24 | { | ||
25 | z->state->mode = I_BAD; | ||
26 | z->state->sub.marker = 0; | ||
27 | } | ||
28 | if ((n = z->avail_in) == 0) | ||
29 | return Z_BUF_ERROR; | ||
30 | p = z->next_in; | ||
31 | m = z->state->sub.marker; | ||
32 | |||
33 | /* search */ | ||
34 | while (n && m < 4) | ||
35 | { | ||
36 | static const Byte mark[4] = {0, 0, 0xff, 0xff}; | ||
37 | if (*p == mark[m]) | ||
38 | m++; | ||
39 | else if (*p) | ||
40 | m = 0; | ||
41 | else | ||
42 | m = 4 - m; | ||
43 | p++, n--; | ||
44 | } | ||
45 | |||
46 | /* restore */ | ||
47 | z->total_in += p - z->next_in; | ||
48 | z->next_in = p; | ||
49 | z->avail_in = n; | ||
50 | z->state->sub.marker = m; | ||
51 | |||
52 | /* return no joy or set up to restart on a new block */ | ||
53 | if (m != 4) | ||
54 | return Z_DATA_ERROR; | ||
55 | r = z->total_in; w = z->total_out; | ||
56 | zlib_inflateReset(z); | ||
57 | z->total_in = r; z->total_out = w; | ||
58 | z->state->mode = BLOCKS; | ||
59 | return Z_OK; | ||
60 | } | ||
61 | #endif /* 0 */ | ||
62 | |||
63 | |||
64 | /* Returns true if inflate is currently at the end of a block generated | ||
65 | * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP | ||
66 | * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH | ||
67 | * but removes the length bytes of the resulting empty stored block. When | ||
68 | * decompressing, PPP checks that at the end of input packet, inflate is | ||
69 | * waiting for these length bytes. | ||
70 | */ | ||
71 | #if 0 | ||
72 | int zlib_inflateSyncPoint( | ||
73 | z_streamp z | ||
74 | ) | ||
75 | { | ||
76 | if (z == NULL || z->state == NULL || z->state->blocks == NULL) | ||
77 | return Z_STREAM_ERROR; | ||
78 | return zlib_inflate_blocks_sync_point(z->state->blocks); | ||
79 | } | ||
80 | #endif /* 0 */ | ||
81 | |||
82 | /* | ||
83 | * This subroutine adds the data at next_in/avail_in to the output history | ||
84 | * without performing any output. The output buffer must be "caught up"; | ||
85 | * i.e. no pending output (hence s->read equals s->write), and the state must | ||
86 | * be BLOCKS (i.e. we should be willing to see the start of a series of | ||
87 | * BLOCKS). On exit, the output will also be caught up, and the checksum | ||
88 | * will have been updated if need be. | ||
89 | */ | ||
90 | static int zlib_inflate_addhistory(inflate_blocks_statef *s, | ||
91 | z_stream *z) | ||
92 | { | ||
93 | uLong b; /* bit buffer */ /* NOT USED HERE */ | ||
94 | uInt k; /* bits in bit buffer */ /* NOT USED HERE */ | ||
95 | uInt t; /* temporary storage */ | ||
96 | Byte *p; /* input data pointer */ | ||
97 | uInt n; /* bytes available there */ | ||
98 | Byte *q; /* output window write pointer */ | ||
99 | uInt m; /* bytes to end of window or read pointer */ | ||
100 | |||
101 | if (s->read != s->write) | ||
102 | return Z_STREAM_ERROR; | ||
103 | if (s->mode != TYPE) | ||
104 | return Z_DATA_ERROR; | ||
105 | |||
106 | /* we're ready to rock */ | ||
107 | LOAD | ||
108 | /* while there is input ready, copy to output buffer, moving | ||
109 | * pointers as needed. | ||
110 | */ | ||
111 | while (n) { | ||
112 | t = n; /* how many to do */ | ||
113 | /* is there room until end of buffer? */ | ||
114 | if (t > m) t = m; | ||
115 | /* update check information */ | ||
116 | if (s->checkfn != NULL) | ||
117 | s->check = (*s->checkfn)(s->check, q, t); | ||
118 | memcpy(q, p, t); | ||
119 | q += t; | ||
120 | p += t; | ||
121 | n -= t; | ||
122 | z->total_out += t; | ||
123 | s->read = q; /* drag read pointer forward */ | ||
124 | /* WWRAP */ /* expand WWRAP macro by hand to handle s->read */ | ||
125 | if (q == s->end) { | ||
126 | s->read = q = s->window; | ||
127 | m = WAVAIL; | ||
128 | } | ||
129 | } | ||
130 | UPDATE | ||
131 | return Z_OK; | ||
132 | } | ||
133 | |||
134 | |||
135 | /* | ||
136 | * This subroutine adds the data at next_in/avail_in to the output history | ||
137 | * without performing any output. The output buffer must be "caught up"; | ||
138 | * i.e. no pending output (hence s->read equals s->write), and the state must | ||
139 | * be BLOCKS (i.e. we should be willing to see the start of a series of | ||
140 | * BLOCKS). On exit, the output will also be caught up, and the checksum | ||
141 | * will have been updated if need be. | ||
142 | */ | ||
143 | |||
144 | int zlib_inflateIncomp( | ||
145 | z_stream *z | ||
146 | |||
147 | ) | ||
148 | { | ||
149 | if (z->state->mode != BLOCKS) | ||
150 | return Z_DATA_ERROR; | ||
151 | return zlib_inflate_addhistory(z->state->blocks, z); | ||
152 | } | ||
diff --git a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c index 874950ec4858..62343c53bf7e 100644 --- a/lib/zlib_inflate/inftrees.c +++ b/lib/zlib_inflate/inftrees.c | |||
@@ -1,412 +1,329 @@ | |||
1 | /* inftrees.c -- generate Huffman trees for efficient decoding | 1 | /* inftrees.c -- generate Huffman trees for efficient decoding |
2 | * Copyright (C) 1995-1998 Mark Adler | 2 | * Copyright (C) 1995-2005 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/zutil.h> | 6 | #include <linux/zutil.h> |
7 | #include "inftrees.h" | 7 | #include "inftrees.h" |
8 | #include "infutil.h" | ||
9 | 8 | ||
10 | static const char inflate_copyright[] __attribute_used__ = | 9 | #define MAXBITS 15 |
11 | " inflate 1.1.3 Copyright 1995-1998 Mark Adler "; | 10 | |
11 | const char inflate_copyright[] = | ||
12 | " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; | ||
12 | /* | 13 | /* |
13 | If you use the zlib library in a product, an acknowledgment is welcome | 14 | If you use the zlib library in a product, an acknowledgment is welcome |
14 | in the documentation of your product. If for some reason you cannot | 15 | in the documentation of your product. If for some reason you cannot |
15 | include such an acknowledgment, I would appreciate that you keep this | 16 | include such an acknowledgment, I would appreciate that you keep this |
16 | copyright string in the executable of your product. | 17 | copyright string in the executable of your product. |
17 | */ | 18 | */ |
18 | struct internal_state; | ||
19 | |||
20 | /* simplify the use of the inflate_huft type with some defines */ | ||
21 | #define exop word.what.Exop | ||
22 | #define bits word.what.Bits | ||
23 | |||
24 | |||
25 | static int huft_build ( | ||
26 | uInt *, /* code lengths in bits */ | ||
27 | uInt, /* number of codes */ | ||
28 | uInt, /* number of "simple" codes */ | ||
29 | const uInt *, /* list of base values for non-simple codes */ | ||
30 | const uInt *, /* list of extra bits for non-simple codes */ | ||
31 | inflate_huft **, /* result: starting table */ | ||
32 | uInt *, /* maximum lookup bits (returns actual) */ | ||
33 | inflate_huft *, /* space for trees */ | ||
34 | uInt *, /* hufts used in space */ | ||
35 | uInt * ); /* space for values */ | ||
36 | |||
37 | /* Tables for deflate from PKZIP's appnote.txt. */ | ||
38 | static const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ | ||
39 | 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, | ||
40 | 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; | ||
41 | /* see note #13 above about 258 */ | ||
42 | static const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ | ||
43 | 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, | ||
44 | 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ | ||
45 | static const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ | ||
46 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, | ||
47 | 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, | ||
48 | 8193, 12289, 16385, 24577}; | ||
49 | static const uInt cpdext[30] = { /* Extra bits for distance codes */ | ||
50 | 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, | ||
51 | 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, | ||
52 | 12, 12, 13, 13}; | ||
53 | 19 | ||
54 | /* | 20 | /* |
55 | Huffman code decoding is performed using a multi-level table lookup. | 21 | Build a set of tables to decode the provided canonical Huffman code. |
56 | The fastest way to decode is to simply build a lookup table whose | 22 | The code lengths are lens[0..codes-1]. The result starts at *table, |
57 | size is determined by the longest code. However, the time it takes | 23 | whose indices are 0..2^bits-1. work is a writable array of at least |
58 | to build this table can also be a factor if the data being decoded | 24 | lens shorts, which is used as a work area. type is the type of code |
59 | is not very long. The most common codes are necessarily the | 25 | to be generated, CODES, LENS, or DISTS. On return, zero is success, |
60 | shortest codes, so those codes dominate the decoding time, and hence | 26 | -1 is an invalid code, and +1 means that ENOUGH isn't enough. table |
61 | the speed. The idea is you can have a shorter table that decodes the | 27 | on return points to the next available entry's address. bits is the |
62 | shorter, more probable codes, and then point to subsidiary tables for | 28 | requested root table index bits, and on return it is the actual root |
63 | the longer codes. The time it costs to decode the longer codes is | 29 | table index bits. It will differ if the request is greater than the |
64 | then traded against the time it takes to make longer tables. | 30 | longest code or if it is less than the shortest code. |
65 | |||
66 | This results of this trade are in the variables lbits and dbits | ||
67 | below. lbits is the number of bits the first level table for literal/ | ||
68 | length codes can decode in one step, and dbits is the same thing for | ||
69 | the distance codes. Subsequent tables are also less than or equal to | ||
70 | those sizes. These values may be adjusted either when all of the | ||
71 | codes are shorter than that, in which case the longest code length in | ||
72 | bits is used, or when the shortest code is *longer* than the requested | ||
73 | table size, in which case the length of the shortest code in bits is | ||
74 | used. | ||
75 | |||
76 | There are two different values for the two tables, since they code a | ||
77 | different number of possibilities each. The literal/length table | ||
78 | codes 286 possible values, or in a flat code, a little over eight | ||
79 | bits. The distance table codes 30 possible values, or a little less | ||
80 | than five bits, flat. The optimum values for speed end up being | ||
81 | about one bit more than those, so lbits is 8+1 and dbits is 5+1. | ||
82 | The optimum values may differ though from machine to machine, and | ||
83 | possibly even between compilers. Your mileage may vary. | ||
84 | */ | 31 | */ |
85 | 32 | int zlib_inflate_table(type, lens, codes, table, bits, work) | |
86 | 33 | codetype type; | |
87 | /* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ | 34 | unsigned short *lens; |
88 | #define BMAX 15 /* maximum bit length of any code */ | 35 | unsigned codes; |
89 | 36 | code **table; | |
90 | static int huft_build( | 37 | unsigned *bits; |
91 | uInt *b, /* code lengths in bits (all assumed <= BMAX) */ | 38 | unsigned short *work; |
92 | uInt n, /* number of codes (assumed <= 288) */ | ||
93 | uInt s, /* number of simple-valued codes (0..s-1) */ | ||
94 | const uInt *d, /* list of base values for non-simple codes */ | ||
95 | const uInt *e, /* list of extra bits for non-simple codes */ | ||
96 | inflate_huft **t, /* result: starting table */ | ||
97 | uInt *m, /* maximum lookup bits, returns actual */ | ||
98 | inflate_huft *hp, /* space for trees */ | ||
99 | uInt *hn, /* hufts used in space */ | ||
100 | uInt *v /* working area: values in order of bit length */ | ||
101 | ) | ||
102 | /* Given a list of code lengths and a maximum table size, make a set of | ||
103 | tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR | ||
104 | if the given code set is incomplete (the tables are still built in this | ||
105 | case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of | ||
106 | lengths), or Z_MEM_ERROR if not enough memory. */ | ||
107 | { | 39 | { |
40 | unsigned len; /* a code's length in bits */ | ||
41 | unsigned sym; /* index of code symbols */ | ||
42 | unsigned min, max; /* minimum and maximum code lengths */ | ||
43 | unsigned root; /* number of index bits for root table */ | ||
44 | unsigned curr; /* number of index bits for current table */ | ||
45 | unsigned drop; /* code bits to drop for sub-table */ | ||
46 | int left; /* number of prefix codes available */ | ||
47 | unsigned used; /* code entries in table used */ | ||
48 | unsigned huff; /* Huffman code */ | ||
49 | unsigned incr; /* for incrementing code, index */ | ||
50 | unsigned fill; /* index for replicating entries */ | ||
51 | unsigned low; /* low bits for current root entry */ | ||
52 | unsigned mask; /* mask for low root bits */ | ||
53 | code this; /* table entry for duplication */ | ||
54 | code *next; /* next available space in table */ | ||
55 | const unsigned short *base; /* base value table to use */ | ||
56 | const unsigned short *extra; /* extra bits table to use */ | ||
57 | int end; /* use base and extra for symbol > end */ | ||
58 | unsigned short count[MAXBITS+1]; /* number of codes of each length */ | ||
59 | unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ | ||
60 | static const unsigned short lbase[31] = { /* Length codes 257..285 base */ | ||
61 | 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, | ||
62 | 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; | ||
63 | static const unsigned short lext[31] = { /* Length codes 257..285 extra */ | ||
64 | 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, | ||
65 | 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; | ||
66 | static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ | ||
67 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, | ||
68 | 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, | ||
69 | 8193, 12289, 16385, 24577, 0, 0}; | ||
70 | static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ | ||
71 | 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, | ||
72 | 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, | ||
73 | 28, 28, 29, 29, 64, 64}; | ||
74 | |||
75 | /* | ||
76 | Process a set of code lengths to create a canonical Huffman code. The | ||
77 | code lengths are lens[0..codes-1]. Each length corresponds to the | ||
78 | symbols 0..codes-1. The Huffman code is generated by first sorting the | ||
79 | symbols by length from short to long, and retaining the symbol order | ||
80 | for codes with equal lengths. Then the code starts with all zero bits | ||
81 | for the first code of the shortest length, and the codes are integer | ||
82 | increments for the same length, and zeros are appended as the length | ||
83 | increases. For the deflate format, these bits are stored backwards | ||
84 | from their more natural integer increment ordering, and so when the | ||
85 | decoding tables are built in the large loop below, the integer codes | ||
86 | are incremented backwards. | ||
87 | |||
88 | This routine assumes, but does not check, that all of the entries in | ||
89 | lens[] are in the range 0..MAXBITS. The caller must assure this. | ||
90 | 1..MAXBITS is interpreted as that code length. zero means that that | ||
91 | symbol does not occur in this code. | ||
92 | |||
93 | The codes are sorted by computing a count of codes for each length, | ||
94 | creating from that a table of starting indices for each length in the | ||
95 | sorted table, and then entering the symbols in order in the sorted | ||
96 | table. The sorted table is work[], with that space being provided by | ||
97 | the caller. | ||
98 | |||
99 | The length counts are used for other purposes as well, i.e. finding | ||
100 | the minimum and maximum length codes, determining if there are any | ||
101 | codes at all, checking for a valid set of lengths, and looking ahead | ||
102 | at length counts to determine sub-table sizes when building the | ||
103 | decoding tables. | ||
104 | */ | ||
105 | |||
106 | /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ | ||
107 | for (len = 0; len <= MAXBITS; len++) | ||
108 | count[len] = 0; | ||
109 | for (sym = 0; sym < codes; sym++) | ||
110 | count[lens[sym]]++; | ||
111 | |||
112 | /* bound code lengths, force root to be within code lengths */ | ||
113 | root = *bits; | ||
114 | for (max = MAXBITS; max >= 1; max--) | ||
115 | if (count[max] != 0) break; | ||
116 | if (root > max) root = max; | ||
117 | if (max == 0) { /* no symbols to code at all */ | ||
118 | this.op = (unsigned char)64; /* invalid code marker */ | ||
119 | this.bits = (unsigned char)1; | ||
120 | this.val = (unsigned short)0; | ||
121 | *(*table)++ = this; /* make a table to force an error */ | ||
122 | *(*table)++ = this; | ||
123 | *bits = 1; | ||
124 | return 0; /* no symbols, but wait for decoding to report error */ | ||
125 | } | ||
126 | for (min = 1; min <= MAXBITS; min++) | ||
127 | if (count[min] != 0) break; | ||
128 | if (root < min) root = min; | ||
129 | |||
130 | /* check for an over-subscribed or incomplete set of lengths */ | ||
131 | left = 1; | ||
132 | for (len = 1; len <= MAXBITS; len++) { | ||
133 | left <<= 1; | ||
134 | left -= count[len]; | ||
135 | if (left < 0) return -1; /* over-subscribed */ | ||
136 | } | ||
137 | if (left > 0 && (type == CODES || max != 1)) | ||
138 | return -1; /* incomplete set */ | ||
139 | |||
140 | /* generate offsets into symbol table for each length for sorting */ | ||
141 | offs[1] = 0; | ||
142 | for (len = 1; len < MAXBITS; len++) | ||
143 | offs[len + 1] = offs[len] + count[len]; | ||
144 | |||
145 | /* sort symbols by length, by symbol order within each length */ | ||
146 | for (sym = 0; sym < codes; sym++) | ||
147 | if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; | ||
148 | |||
149 | /* | ||
150 | Create and fill in decoding tables. In this loop, the table being | ||
151 | filled is at next and has curr index bits. The code being used is huff | ||
152 | with length len. That code is converted to an index by dropping drop | ||
153 | bits off of the bottom. For codes where len is less than drop + curr, | ||
154 | those top drop + curr - len bits are incremented through all values to | ||
155 | fill the table with replicated entries. | ||
156 | |||
157 | root is the number of index bits for the root table. When len exceeds | ||
158 | root, sub-tables are created pointed to by the root entry with an index | ||
159 | of the low root bits of huff. This is saved in low to check for when a | ||
160 | new sub-table should be started. drop is zero when the root table is | ||
161 | being filled, and drop is root when sub-tables are being filled. | ||
162 | |||
163 | When a new sub-table is needed, it is necessary to look ahead in the | ||
164 | code lengths to determine what size sub-table is needed. The length | ||
165 | counts are used for this, and so count[] is decremented as codes are | ||
166 | entered in the tables. | ||
167 | |||
168 | used keeps track of how many table entries have been allocated from the | ||
169 | provided *table space. It is checked when a LENS table is being made | ||
170 | against the space in *table, ENOUGH, minus the maximum space needed by | ||
171 | the worst case distance code, MAXD. This should never happen, but the | ||
172 | sufficiency of ENOUGH has not been proven exhaustively, hence the check. | ||
173 | This assumes that when type == LENS, bits == 9. | ||
174 | |||
175 | sym increments through all symbols, and the loop terminates when | ||
176 | all codes of length max, i.e. all codes, have been processed. This | ||
177 | routine permits incomplete codes, so another loop after this one fills | ||
178 | in the rest of the decoding tables with invalid code markers. | ||
179 | */ | ||
180 | |||
181 | /* set up for code type */ | ||
182 | switch (type) { | ||
183 | case CODES: | ||
184 | base = extra = work; /* dummy value--not used */ | ||
185 | end = 19; | ||
186 | break; | ||
187 | case LENS: | ||
188 | base = lbase; | ||
189 | base -= 257; | ||
190 | extra = lext; | ||
191 | extra -= 257; | ||
192 | end = 256; | ||
193 | break; | ||
194 | default: /* DISTS */ | ||
195 | base = dbase; | ||
196 | extra = dext; | ||
197 | end = -1; | ||
198 | } | ||
108 | 199 | ||
109 | uInt a; /* counter for codes of length k */ | 200 | /* initialize state for loop */ |
110 | uInt c[BMAX+1]; /* bit length count table */ | 201 | huff = 0; /* starting code */ |
111 | uInt f; /* i repeats in table every f entries */ | 202 | sym = 0; /* starting code symbol */ |
112 | int g; /* maximum code length */ | 203 | len = min; /* starting code length */ |
113 | int h; /* table level */ | 204 | next = *table; /* current table to fill in */ |
114 | register uInt i; /* counter, current code */ | 205 | curr = root; /* current table index bits */ |
115 | register uInt j; /* counter */ | 206 | drop = 0; /* current bits to drop from code for index */ |
116 | register int k; /* number of bits in current code */ | 207 | low = (unsigned)(-1); /* trigger new sub-table when len > root */ |
117 | int l; /* bits per table (returned in m) */ | 208 | used = 1U << root; /* use root table entries */ |
118 | uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ | 209 | mask = used - 1; /* mask for comparing low */ |
119 | register uInt *p; /* pointer into c[], b[], or v[] */ | 210 | |
120 | inflate_huft *q; /* points to current table */ | 211 | /* check available table space */ |
121 | struct inflate_huft_s r; /* table entry for structure assignment */ | 212 | if (type == LENS && used >= ENOUGH - MAXD) |
122 | inflate_huft *u[BMAX]; /* table stack */ | 213 | return 1; |
123 | register int w; /* bits before this table == (l * h) */ | 214 | |
124 | uInt x[BMAX+1]; /* bit offsets, then code stack */ | 215 | /* process all codes and make table entries */ |
125 | uInt *xp; /* pointer into x */ | 216 | for (;;) { |
126 | int y; /* number of dummy codes added */ | 217 | /* create table entry */ |
127 | uInt z; /* number of entries in current table */ | 218 | this.bits = (unsigned char)(len - drop); |
128 | 219 | if ((int)(work[sym]) < end) { | |
129 | 220 | this.op = (unsigned char)0; | |
130 | /* Generate counts for each bit length */ | 221 | this.val = work[sym]; |
131 | p = c; | ||
132 | #define C0 *p++ = 0; | ||
133 | #define C2 C0 C0 C0 C0 | ||
134 | #define C4 C2 C2 C2 C2 | ||
135 | C4 /* clear c[]--assume BMAX+1 is 16 */ | ||
136 | p = b; i = n; | ||
137 | do { | ||
138 | c[*p++]++; /* assume all entries <= BMAX */ | ||
139 | } while (--i); | ||
140 | if (c[0] == n) /* null input--all zero length codes */ | ||
141 | { | ||
142 | *t = NULL; | ||
143 | *m = 0; | ||
144 | return Z_OK; | ||
145 | } | ||
146 | |||
147 | |||
148 | /* Find minimum and maximum length, bound *m by those */ | ||
149 | l = *m; | ||
150 | for (j = 1; j <= BMAX; j++) | ||
151 | if (c[j]) | ||
152 | break; | ||
153 | k = j; /* minimum code length */ | ||
154 | if ((uInt)l < j) | ||
155 | l = j; | ||
156 | for (i = BMAX; i; i--) | ||
157 | if (c[i]) | ||
158 | break; | ||
159 | g = i; /* maximum code length */ | ||
160 | if ((uInt)l > i) | ||
161 | l = i; | ||
162 | *m = l; | ||
163 | |||
164 | |||
165 | /* Adjust last length count to fill out codes, if needed */ | ||
166 | for (y = 1 << j; j < i; j++, y <<= 1) | ||
167 | if ((y -= c[j]) < 0) | ||
168 | return Z_DATA_ERROR; | ||
169 | if ((y -= c[i]) < 0) | ||
170 | return Z_DATA_ERROR; | ||
171 | c[i] += y; | ||
172 | |||
173 | |||
174 | /* Generate starting offsets into the value table for each length */ | ||
175 | x[1] = j = 0; | ||
176 | p = c + 1; xp = x + 2; | ||
177 | while (--i) { /* note that i == g from above */ | ||
178 | *xp++ = (j += *p++); | ||
179 | } | ||
180 | |||
181 | |||
182 | /* Make a table of values in order of bit lengths */ | ||
183 | p = b; i = 0; | ||
184 | do { | ||
185 | if ((j = *p++) != 0) | ||
186 | v[x[j]++] = i; | ||
187 | } while (++i < n); | ||
188 | n = x[g]; /* set n to length of v */ | ||
189 | |||
190 | |||
191 | /* Generate the Huffman codes and for each, make the table entries */ | ||
192 | x[0] = i = 0; /* first Huffman code is zero */ | ||
193 | p = v; /* grab values in bit order */ | ||
194 | h = -1; /* no tables yet--level -1 */ | ||
195 | w = -l; /* bits decoded == (l * h) */ | ||
196 | u[0] = NULL; /* just to keep compilers happy */ | ||
197 | q = NULL; /* ditto */ | ||
198 | z = 0; /* ditto */ | ||
199 | |||
200 | /* go through the bit lengths (k already is bits in shortest code) */ | ||
201 | for (; k <= g; k++) | ||
202 | { | ||
203 | a = c[k]; | ||
204 | while (a--) | ||
205 | { | ||
206 | /* here i is the Huffman code of length k bits for value *p */ | ||
207 | /* make tables up to required level */ | ||
208 | while (k > w + l) | ||
209 | { | ||
210 | h++; | ||
211 | w += l; /* previous table always l bits */ | ||
212 | |||
213 | /* compute minimum size table less than or equal to l bits */ | ||
214 | z = g - w; | ||
215 | z = z > (uInt)l ? l : z; /* table size upper limit */ | ||
216 | if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ | ||
217 | { /* too few codes for k-w bit table */ | ||
218 | f -= a + 1; /* deduct codes from patterns left */ | ||
219 | xp = c + k; | ||
220 | if (j < z) | ||
221 | while (++j < z) /* try smaller tables up to z bits */ | ||
222 | { | ||
223 | if ((f <<= 1) <= *++xp) | ||
224 | break; /* enough codes to use up j bits */ | ||
225 | f -= *xp; /* else deduct codes from patterns */ | ||
226 | } | ||
227 | } | 222 | } |
228 | z = 1 << j; /* table entries for j-bit table */ | 223 | else if ((int)(work[sym]) > end) { |
229 | 224 | this.op = (unsigned char)(extra[work[sym]]); | |
230 | /* allocate new table */ | 225 | this.val = base[work[sym]]; |
231 | if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ | 226 | } |
232 | return Z_DATA_ERROR; /* overflow of MANY */ | 227 | else { |
233 | u[h] = q = hp + *hn; | 228 | this.op = (unsigned char)(32 + 64); /* end of block */ |
234 | *hn += z; | 229 | this.val = 0; |
235 | |||
236 | /* connect to last table, if there is one */ | ||
237 | if (h) | ||
238 | { | ||
239 | x[h] = i; /* save pattern for backing up */ | ||
240 | r.bits = (Byte)l; /* bits to dump before this table */ | ||
241 | r.exop = (Byte)j; /* bits in this table */ | ||
242 | j = i >> (w - l); | ||
243 | r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ | ||
244 | u[h-1][j] = r; /* connect to last table */ | ||
245 | } | 230 | } |
246 | else | ||
247 | *t = q; /* first table is returned result */ | ||
248 | } | ||
249 | |||
250 | /* set up table entry in r */ | ||
251 | r.bits = (Byte)(k - w); | ||
252 | if (p >= v + n) | ||
253 | r.exop = 128 + 64; /* out of values--invalid code */ | ||
254 | else if (*p < s) | ||
255 | { | ||
256 | r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ | ||
257 | r.base = *p++; /* simple code is just the value */ | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ | ||
262 | r.base = d[*p++ - s]; | ||
263 | } | ||
264 | |||
265 | /* fill code-like entries with r */ | ||
266 | f = 1 << (k - w); | ||
267 | for (j = i >> w; j < z; j += f) | ||
268 | q[j] = r; | ||
269 | |||
270 | /* backwards increment the k-bit code i */ | ||
271 | for (j = 1 << (k - 1); i & j; j >>= 1) | ||
272 | i ^= j; | ||
273 | i ^= j; | ||
274 | |||
275 | /* backup over finished tables */ | ||
276 | mask = (1 << w) - 1; /* needed on HP, cc -O bug */ | ||
277 | while ((i & mask) != x[h]) | ||
278 | { | ||
279 | h--; /* don't need to update q */ | ||
280 | w -= l; | ||
281 | mask = (1 << w) - 1; | ||
282 | } | ||
283 | } | ||
284 | } | ||
285 | 231 | ||
232 | /* replicate for those indices with low len bits equal to huff */ | ||
233 | incr = 1U << (len - drop); | ||
234 | fill = 1U << curr; | ||
235 | min = fill; /* save offset to next table */ | ||
236 | do { | ||
237 | fill -= incr; | ||
238 | next[(huff >> drop) + fill] = this; | ||
239 | } while (fill != 0); | ||
240 | |||
241 | /* backwards increment the len-bit code huff */ | ||
242 | incr = 1U << (len - 1); | ||
243 | while (huff & incr) | ||
244 | incr >>= 1; | ||
245 | if (incr != 0) { | ||
246 | huff &= incr - 1; | ||
247 | huff += incr; | ||
248 | } | ||
249 | else | ||
250 | huff = 0; | ||
286 | 251 | ||
287 | /* Return Z_BUF_ERROR if we were given an incomplete table */ | 252 | /* go to next symbol, update count, len */ |
288 | return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; | 253 | sym++; |
289 | } | 254 | if (--(count[len]) == 0) { |
255 | if (len == max) break; | ||
256 | len = lens[work[sym]]; | ||
257 | } | ||
290 | 258 | ||
259 | /* create new sub-table if needed */ | ||
260 | if (len > root && (huff & mask) != low) { | ||
261 | /* if first time, transition to sub-tables */ | ||
262 | if (drop == 0) | ||
263 | drop = root; | ||
264 | |||
265 | /* increment past last table */ | ||
266 | next += min; /* here min is 1 << curr */ | ||
267 | |||
268 | /* determine length of next table */ | ||
269 | curr = len - drop; | ||
270 | left = (int)(1 << curr); | ||
271 | while (curr + drop < max) { | ||
272 | left -= count[curr + drop]; | ||
273 | if (left <= 0) break; | ||
274 | curr++; | ||
275 | left <<= 1; | ||
276 | } | ||
291 | 277 | ||
292 | int zlib_inflate_trees_bits( | 278 | /* check for enough space */ |
293 | uInt *c, /* 19 code lengths */ | 279 | used += 1U << curr; |
294 | uInt *bb, /* bits tree desired/actual depth */ | 280 | if (type == LENS && used >= ENOUGH - MAXD) |
295 | inflate_huft **tb, /* bits tree result */ | 281 | return 1; |
296 | inflate_huft *hp, /* space for trees */ | ||
297 | z_streamp z /* for messages */ | ||
298 | ) | ||
299 | { | ||
300 | int r; | ||
301 | uInt hn = 0; /* hufts used in space */ | ||
302 | uInt *v; /* work area for huft_build */ | ||
303 | |||
304 | v = WS(z)->tree_work_area_1; | ||
305 | r = huft_build(c, 19, 19, NULL, NULL, tb, bb, hp, &hn, v); | ||
306 | if (r == Z_DATA_ERROR) | ||
307 | z->msg = (char*)"oversubscribed dynamic bit lengths tree"; | ||
308 | else if (r == Z_BUF_ERROR || *bb == 0) | ||
309 | { | ||
310 | z->msg = (char*)"incomplete dynamic bit lengths tree"; | ||
311 | r = Z_DATA_ERROR; | ||
312 | } | ||
313 | return r; | ||
314 | } | ||
315 | 282 | ||
316 | int zlib_inflate_trees_dynamic( | 283 | /* point entry in root table to sub-table */ |
317 | uInt nl, /* number of literal/length codes */ | 284 | low = huff & mask; |
318 | uInt nd, /* number of distance codes */ | 285 | (*table)[low].op = (unsigned char)curr; |
319 | uInt *c, /* that many (total) code lengths */ | 286 | (*table)[low].bits = (unsigned char)root; |
320 | uInt *bl, /* literal desired/actual bit depth */ | 287 | (*table)[low].val = (unsigned short)(next - *table); |
321 | uInt *bd, /* distance desired/actual bit depth */ | 288 | } |
322 | inflate_huft **tl, /* literal/length tree result */ | ||
323 | inflate_huft **td, /* distance tree result */ | ||
324 | inflate_huft *hp, /* space for trees */ | ||
325 | z_streamp z /* for messages */ | ||
326 | ) | ||
327 | { | ||
328 | int r; | ||
329 | uInt hn = 0; /* hufts used in space */ | ||
330 | uInt *v; /* work area for huft_build */ | ||
331 | |||
332 | /* allocate work area */ | ||
333 | v = WS(z)->tree_work_area_2; | ||
334 | |||
335 | /* build literal/length tree */ | ||
336 | r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); | ||
337 | if (r != Z_OK || *bl == 0) | ||
338 | { | ||
339 | if (r == Z_DATA_ERROR) | ||
340 | z->msg = (char*)"oversubscribed literal/length tree"; | ||
341 | else if (r != Z_MEM_ERROR) | ||
342 | { | ||
343 | z->msg = (char*)"incomplete literal/length tree"; | ||
344 | r = Z_DATA_ERROR; | ||
345 | } | ||
346 | return r; | ||
347 | } | ||
348 | |||
349 | /* build distance tree */ | ||
350 | r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); | ||
351 | if (r != Z_OK || (*bd == 0 && nl > 257)) | ||
352 | { | ||
353 | if (r == Z_DATA_ERROR) | ||
354 | z->msg = (char*)"oversubscribed distance tree"; | ||
355 | else if (r == Z_BUF_ERROR) { | ||
356 | #ifdef PKZIP_BUG_WORKAROUND | ||
357 | r = Z_OK; | ||
358 | } | ||
359 | #else | ||
360 | z->msg = (char*)"incomplete distance tree"; | ||
361 | r = Z_DATA_ERROR; | ||
362 | } | ||
363 | else if (r != Z_MEM_ERROR) | ||
364 | { | ||
365 | z->msg = (char*)"empty distance tree with lengths"; | ||
366 | r = Z_DATA_ERROR; | ||
367 | } | 289 | } |
368 | return r; | ||
369 | #endif | ||
370 | } | ||
371 | 290 | ||
372 | /* done */ | 291 | /* |
373 | return Z_OK; | 292 | Fill in rest of table for incomplete codes. This loop is similar to the |
374 | } | 293 | loop above in incrementing huff for table indices. It is assumed that |
294 | len is equal to curr + drop, so there is no loop needed to increment | ||
295 | through high index bits. When the current sub-table is filled, the loop | ||
296 | drops back to the root table to fill in any remaining entries there. | ||
297 | */ | ||
298 | this.op = (unsigned char)64; /* invalid code marker */ | ||
299 | this.bits = (unsigned char)(len - drop); | ||
300 | this.val = (unsigned short)0; | ||
301 | while (huff != 0) { | ||
302 | /* when done with sub-table, drop back to root table */ | ||
303 | if (drop != 0 && (huff & mask) != low) { | ||
304 | drop = 0; | ||
305 | len = root; | ||
306 | next = *table; | ||
307 | this.bits = (unsigned char)len; | ||
308 | } | ||
375 | 309 | ||
310 | /* put invalid code marker in table */ | ||
311 | next[huff >> drop] = this; | ||
376 | 312 | ||
377 | int zlib_inflate_trees_fixed( | 313 | /* backwards increment the len-bit code huff */ |
378 | uInt *bl, /* literal desired/actual bit depth */ | 314 | incr = 1U << (len - 1); |
379 | uInt *bd, /* distance desired/actual bit depth */ | 315 | while (huff & incr) |
380 | inflate_huft **tl, /* literal/length tree result */ | 316 | incr >>= 1; |
381 | inflate_huft **td, /* distance tree result */ | 317 | if (incr != 0) { |
382 | inflate_huft *hp, /* space for trees */ | 318 | huff &= incr - 1; |
383 | z_streamp z /* for memory allocation */ | 319 | huff += incr; |
384 | ) | 320 | } |
385 | { | 321 | else |
386 | int i; /* temporary variable */ | 322 | huff = 0; |
387 | unsigned l[288]; /* length list for huft_build */ | 323 | } |
388 | uInt *v; /* work area for huft_build */ | 324 | |
389 | 325 | /* set return parameters */ | |
390 | /* set up literal table */ | 326 | *table += used; |
391 | for (i = 0; i < 144; i++) | 327 | *bits = root; |
392 | l[i] = 8; | 328 | return 0; |
393 | for (; i < 256; i++) | ||
394 | l[i] = 9; | ||
395 | for (; i < 280; i++) | ||
396 | l[i] = 7; | ||
397 | for (; i < 288; i++) /* make a complete, but wrong code set */ | ||
398 | l[i] = 8; | ||
399 | *bl = 9; | ||
400 | v = WS(z)->tree_work_area_1; | ||
401 | if ((i = huft_build(l, 288, 257, cplens, cplext, tl, bl, hp, &i, v)) != 0) | ||
402 | return i; | ||
403 | |||
404 | /* set up distance table */ | ||
405 | for (i = 0; i < 30; i++) /* make an incomplete code set */ | ||
406 | l[i] = 5; | ||
407 | *bd = 5; | ||
408 | if ((i = huft_build(l, 30, 0, cpdist, cpdext, td, bd, hp, &i, v)) > 1) | ||
409 | return i; | ||
410 | |||
411 | return Z_OK; | ||
412 | } | 329 | } |
diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h index e37705adc008..5f5219b1240e 100644 --- a/lib/zlib_inflate/inftrees.h +++ b/lib/zlib_inflate/inftrees.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* inftrees.h -- header to use inftrees.c | 1 | /* inftrees.h -- header to use inftrees.c |
2 | * Copyright (C) 1995-1998 Mark Adler | 2 | * Copyright (C) 1995-2005 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
6 | /* WARNING: this file should *not* be used by applications. It is | 6 | /* WARNING: this file should *not* be used by applications. It is |
@@ -8,57 +8,48 @@ | |||
8 | subject to change. Applications should only use zlib.h. | 8 | subject to change. Applications should only use zlib.h. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | /* Huffman code lookup table entry--this entry is four bytes for machines | 11 | /* Structure for decoding tables. Each entry provides either the |
12 | that have 16-bit pointers (e.g. PC's in the small or medium model). */ | 12 | information needed to do the operation requested by the code that |
13 | 13 | indexed that table entry, or it provides a pointer to another | |
14 | #ifndef _INFTREES_H | 14 | table that indexes more bits of the code. op indicates whether |
15 | #define _INFTREES_H | 15 | the entry is a pointer to another table, a literal, a length or |
16 | 16 | distance, an end-of-block, or an invalid code. For a table | |
17 | typedef struct inflate_huft_s inflate_huft; | 17 | pointer, the low four bits of op is the number of index bits of |
18 | 18 | that table. For a length or distance, the low four bits of op | |
19 | struct inflate_huft_s { | 19 | is the number of extra bits to get after the code. bits is |
20 | union { | 20 | the number of bits in this code or part of the code to drop off |
21 | struct { | 21 | of the bit buffer. val is the actual byte to output in the case |
22 | Byte Exop; /* number of extra bits or operation */ | 22 | of a literal, the base length or distance, or the offset from |
23 | Byte Bits; /* number of bits in this code or subcode */ | 23 | the current table to the next table. Each entry is four bytes. */ |
24 | } what; | 24 | typedef struct { |
25 | uInt pad; /* pad structure to a power of 2 (4 bytes for */ | 25 | unsigned char op; /* operation, extra bits, table bits */ |
26 | } word; /* 16-bit, 8 bytes for 32-bit int's) */ | 26 | unsigned char bits; /* bits in this part of the code */ |
27 | uInt base; /* literal, length base, distance base, | 27 | unsigned short val; /* offset in table or code value */ |
28 | or table offset */ | 28 | } code; |
29 | }; | 29 | |
30 | /* op values as set by inflate_table(): | ||
31 | 00000000 - literal | ||
32 | 0000tttt - table link, tttt != 0 is the number of table index bits | ||
33 | 0001eeee - length or distance, eeee is the number of extra bits | ||
34 | 01100000 - end of block | ||
35 | 01000000 - invalid code | ||
36 | */ | ||
30 | 37 | ||
31 | /* Maximum size of dynamic tree. The maximum found in a long but non- | 38 | /* Maximum size of dynamic tree. The maximum found in a long but non- |
32 | exhaustive search was 1004 huft structures (850 for length/literals | 39 | exhaustive search was 1444 code structures (852 for length/literals |
33 | and 154 for distances, the latter actually the result of an | 40 | and 592 for distances, the latter actually the result of an |
34 | exhaustive search). The actual maximum is not known, but the | 41 | exhaustive search). The true maximum is not known, but the value |
35 | value below is more than safe. */ | 42 | below is more than safe. */ |
36 | #define MANY 1440 | 43 | #define ENOUGH 2048 |
37 | 44 | #define MAXD 592 | |
38 | extern int zlib_inflate_trees_bits ( | 45 | |
39 | uInt *, /* 19 code lengths */ | 46 | /* Type of code to build for inftable() */ |
40 | uInt *, /* bits tree desired/actual depth */ | 47 | typedef enum { |
41 | inflate_huft **, /* bits tree result */ | 48 | CODES, |
42 | inflate_huft *, /* space for trees */ | 49 | LENS, |
43 | z_streamp); /* for messages */ | 50 | DISTS |
44 | 51 | } codetype; | |
45 | extern int zlib_inflate_trees_dynamic ( | 52 | |
46 | uInt, /* number of literal/length codes */ | 53 | extern int zlib_inflate_table (codetype type, unsigned short *lens, |
47 | uInt, /* number of distance codes */ | 54 | unsigned codes, code **table, |
48 | uInt *, /* that many (total) code lengths */ | 55 | unsigned *bits, unsigned short *work); |
49 | uInt *, /* literal desired/actual bit depth */ | ||
50 | uInt *, /* distance desired/actual bit depth */ | ||
51 | inflate_huft **, /* literal/length tree result */ | ||
52 | inflate_huft **, /* distance tree result */ | ||
53 | inflate_huft *, /* space for trees */ | ||
54 | z_streamp); /* for messages */ | ||
55 | |||
56 | extern int zlib_inflate_trees_fixed ( | ||
57 | uInt *, /* literal desired/actual bit depth */ | ||
58 | uInt *, /* distance desired/actual bit depth */ | ||
59 | inflate_huft **, /* literal/length tree result */ | ||
60 | inflate_huft **, /* distance tree result */ | ||
61 | inflate_huft *, /* space for trees */ | ||
62 | z_streamp); /* for memory allocation */ | ||
63 | |||
64 | #endif /* _INFTREES_H */ | ||
diff --git a/lib/zlib_inflate/infutil.c b/lib/zlib_inflate/infutil.c deleted file mode 100644 index 00202b3438e1..000000000000 --- a/lib/zlib_inflate/infutil.c +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | /* inflate_util.c -- data and routines common to blocks and codes | ||
2 | * Copyright (C) 1995-1998 Mark Adler | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | */ | ||
5 | |||
6 | #include <linux/zutil.h> | ||
7 | #include "infblock.h" | ||
8 | #include "inftrees.h" | ||
9 | #include "infcodes.h" | ||
10 | #include "infutil.h" | ||
11 | |||
12 | struct inflate_codes_state; | ||
13 | |||
14 | /* And'ing with mask[n] masks the lower n bits */ | ||
15 | uInt zlib_inflate_mask[17] = { | ||
16 | 0x0000, | ||
17 | 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, | ||
18 | 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff | ||
19 | }; | ||
20 | |||
21 | |||
22 | /* copy as much as possible from the sliding window to the output area */ | ||
23 | int zlib_inflate_flush( | ||
24 | inflate_blocks_statef *s, | ||
25 | z_streamp z, | ||
26 | int r | ||
27 | ) | ||
28 | { | ||
29 | uInt n; | ||
30 | Byte *p; | ||
31 | Byte *q; | ||
32 | |||
33 | /* local copies of source and destination pointers */ | ||
34 | p = z->next_out; | ||
35 | q = s->read; | ||
36 | |||
37 | /* compute number of bytes to copy as far as end of window */ | ||
38 | n = (uInt)((q <= s->write ? s->write : s->end) - q); | ||
39 | if (n > z->avail_out) n = z->avail_out; | ||
40 | if (n && r == Z_BUF_ERROR) r = Z_OK; | ||
41 | |||
42 | /* update counters */ | ||
43 | z->avail_out -= n; | ||
44 | z->total_out += n; | ||
45 | |||
46 | /* update check information */ | ||
47 | if (s->checkfn != NULL) | ||
48 | z->adler = s->check = (*s->checkfn)(s->check, q, n); | ||
49 | |||
50 | /* copy as far as end of window */ | ||
51 | memcpy(p, q, n); | ||
52 | p += n; | ||
53 | q += n; | ||
54 | |||
55 | /* see if more to copy at beginning of window */ | ||
56 | if (q == s->end) | ||
57 | { | ||
58 | /* wrap pointers */ | ||
59 | q = s->window; | ||
60 | if (s->write == s->end) | ||
61 | s->write = s->window; | ||
62 | |||
63 | /* compute bytes to copy */ | ||
64 | n = (uInt)(s->write - q); | ||
65 | if (n > z->avail_out) n = z->avail_out; | ||
66 | if (n && r == Z_BUF_ERROR) r = Z_OK; | ||
67 | |||
68 | /* update counters */ | ||
69 | z->avail_out -= n; | ||
70 | z->total_out += n; | ||
71 | |||
72 | /* update check information */ | ||
73 | if (s->checkfn != NULL) | ||
74 | z->adler = s->check = (*s->checkfn)(s->check, q, n); | ||
75 | |||
76 | /* copy */ | ||
77 | memcpy(p, q, n); | ||
78 | p += n; | ||
79 | q += n; | ||
80 | } | ||
81 | |||
82 | /* update pointers */ | ||
83 | z->next_out = p; | ||
84 | s->read = q; | ||
85 | |||
86 | /* done */ | ||
87 | return r; | ||
88 | } | ||
diff --git a/lib/zlib_inflate/infutil.h b/lib/zlib_inflate/infutil.h index a15875fc5f72..eb1a9007bd86 100644 --- a/lib/zlib_inflate/infutil.h +++ b/lib/zlib_inflate/infutil.h | |||
@@ -11,184 +11,12 @@ | |||
11 | #ifndef _INFUTIL_H | 11 | #ifndef _INFUTIL_H |
12 | #define _INFUTIL_H | 12 | #define _INFUTIL_H |
13 | 13 | ||
14 | #include <linux/zconf.h> | 14 | #include <linux/zlib.h> |
15 | #include "inftrees.h" | ||
16 | #include "infcodes.h" | ||
17 | |||
18 | typedef enum { | ||
19 | TYPE, /* get type bits (3, including end bit) */ | ||
20 | LENS, /* get lengths for stored */ | ||
21 | STORED, /* processing stored block */ | ||
22 | TABLE, /* get table lengths */ | ||
23 | BTREE, /* get bit lengths tree for a dynamic block */ | ||
24 | DTREE, /* get length, distance trees for a dynamic block */ | ||
25 | CODES, /* processing fixed or dynamic block */ | ||
26 | DRY, /* output remaining window bytes */ | ||
27 | B_DONE, /* finished last block, done */ | ||
28 | B_BAD} /* got a data error--stuck here */ | ||
29 | inflate_block_mode; | ||
30 | |||
31 | /* inflate blocks semi-private state */ | ||
32 | struct inflate_blocks_state { | ||
33 | |||
34 | /* mode */ | ||
35 | inflate_block_mode mode; /* current inflate_block mode */ | ||
36 | |||
37 | /* mode dependent information */ | ||
38 | union { | ||
39 | uInt left; /* if STORED, bytes left to copy */ | ||
40 | struct { | ||
41 | uInt table; /* table lengths (14 bits) */ | ||
42 | uInt index; /* index into blens (or border) */ | ||
43 | uInt *blens; /* bit lengths of codes */ | ||
44 | uInt bb; /* bit length tree depth */ | ||
45 | inflate_huft *tb; /* bit length decoding tree */ | ||
46 | } trees; /* if DTREE, decoding info for trees */ | ||
47 | struct { | ||
48 | inflate_codes_statef | ||
49 | *codes; | ||
50 | } decode; /* if CODES, current state */ | ||
51 | } sub; /* submode */ | ||
52 | uInt last; /* true if this block is the last block */ | ||
53 | |||
54 | /* mode independent information */ | ||
55 | uInt bitk; /* bits in bit buffer */ | ||
56 | uLong bitb; /* bit buffer */ | ||
57 | inflate_huft *hufts; /* single malloc for tree space */ | ||
58 | Byte *window; /* sliding window */ | ||
59 | Byte *end; /* one byte after sliding window */ | ||
60 | Byte *read; /* window read pointer */ | ||
61 | Byte *write; /* window write pointer */ | ||
62 | check_func checkfn; /* check function */ | ||
63 | uLong check; /* check on output */ | ||
64 | |||
65 | }; | ||
66 | |||
67 | |||
68 | /* defines for inflate input/output */ | ||
69 | /* update pointers and return */ | ||
70 | #define UPDBITS {s->bitb=b;s->bitk=k;} | ||
71 | #define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} | ||
72 | #define UPDOUT {s->write=q;} | ||
73 | #define UPDATE {UPDBITS UPDIN UPDOUT} | ||
74 | #define LEAVE {UPDATE return zlib_inflate_flush(s,z,r);} | ||
75 | /* get bytes and bits */ | ||
76 | #define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} | ||
77 | #define NEEDBYTE {if(n)r=Z_OK;else LEAVE} | ||
78 | #define NEXTBYTE (n--,*p++) | ||
79 | #define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}} | ||
80 | #define DUMPBITS(j) {b>>=(j);k-=(j);} | ||
81 | /* output bytes */ | ||
82 | #define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q) | ||
83 | #define LOADOUT {q=s->write;m=(uInt)WAVAIL;} | ||
84 | #define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} | ||
85 | #define FLUSH {UPDOUT r=zlib_inflate_flush(s,z,r); LOADOUT} | ||
86 | #define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} | ||
87 | #define OUTBYTE(a) {*q++=(Byte)(a);m--;} | ||
88 | /* load local pointers */ | ||
89 | #define LOAD {LOADIN LOADOUT} | ||
90 | |||
91 | /* masks for lower bits (size given to avoid silly warnings with Visual C++) */ | ||
92 | extern uInt zlib_inflate_mask[17]; | ||
93 | |||
94 | /* copy as much as possible from the sliding window to the output area */ | ||
95 | extern int zlib_inflate_flush ( | ||
96 | inflate_blocks_statef *, | ||
97 | z_streamp , | ||
98 | int); | ||
99 | |||
100 | /* inflate private state */ | ||
101 | typedef enum { | ||
102 | METHOD, /* waiting for method byte */ | ||
103 | FLAG, /* waiting for flag byte */ | ||
104 | DICT4, /* four dictionary check bytes to go */ | ||
105 | DICT3, /* three dictionary check bytes to go */ | ||
106 | DICT2, /* two dictionary check bytes to go */ | ||
107 | DICT1, /* one dictionary check byte to go */ | ||
108 | DICT0, /* waiting for inflateSetDictionary */ | ||
109 | BLOCKS, /* decompressing blocks */ | ||
110 | CHECK4, /* four check bytes to go */ | ||
111 | CHECK3, /* three check bytes to go */ | ||
112 | CHECK2, /* two check bytes to go */ | ||
113 | CHECK1, /* one check byte to go */ | ||
114 | I_DONE, /* finished check, done */ | ||
115 | I_BAD} /* got an error--stay here */ | ||
116 | inflate_mode; | ||
117 | |||
118 | struct internal_state { | ||
119 | |||
120 | /* mode */ | ||
121 | inflate_mode mode; /* current inflate mode */ | ||
122 | |||
123 | /* mode dependent information */ | ||
124 | union { | ||
125 | uInt method; /* if FLAGS, method byte */ | ||
126 | struct { | ||
127 | uLong was; /* computed check value */ | ||
128 | uLong need; /* stream check value */ | ||
129 | } check; /* if CHECK, check values to compare */ | ||
130 | uInt marker; /* if BAD, inflateSync's marker bytes count */ | ||
131 | } sub; /* submode */ | ||
132 | |||
133 | /* mode independent information */ | ||
134 | int nowrap; /* flag for no wrapper */ | ||
135 | uInt wbits; /* log2(window size) (8..15, defaults to 15) */ | ||
136 | inflate_blocks_statef | ||
137 | *blocks; /* current inflate_blocks state */ | ||
138 | |||
139 | }; | ||
140 | |||
141 | /* inflate codes private state */ | ||
142 | typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ | ||
143 | START, /* x: set up for LEN */ | ||
144 | LEN, /* i: get length/literal/eob next */ | ||
145 | LENEXT, /* i: getting length extra (have base) */ | ||
146 | DIST, /* i: get distance next */ | ||
147 | DISTEXT, /* i: getting distance extra */ | ||
148 | COPY, /* o: copying bytes in window, waiting for space */ | ||
149 | LIT, /* o: got literal, waiting for output space */ | ||
150 | WASH, /* o: got eob, possibly still output waiting */ | ||
151 | END, /* x: got eob and all data flushed */ | ||
152 | BADCODE} /* x: got error */ | ||
153 | inflate_codes_mode; | ||
154 | |||
155 | struct inflate_codes_state { | ||
156 | |||
157 | /* mode */ | ||
158 | inflate_codes_mode mode; /* current inflate_codes mode */ | ||
159 | |||
160 | /* mode dependent information */ | ||
161 | uInt len; | ||
162 | union { | ||
163 | struct { | ||
164 | inflate_huft *tree; /* pointer into tree */ | ||
165 | uInt need; /* bits needed */ | ||
166 | } code; /* if LEN or DIST, where in tree */ | ||
167 | uInt lit; /* if LIT, literal */ | ||
168 | struct { | ||
169 | uInt get; /* bits to get for extra */ | ||
170 | uInt dist; /* distance back to copy from */ | ||
171 | } copy; /* if EXT or COPY, where and how much */ | ||
172 | } sub; /* submode */ | ||
173 | |||
174 | /* mode independent information */ | ||
175 | Byte lbits; /* ltree bits decoded per branch */ | ||
176 | Byte dbits; /* dtree bits decoder per branch */ | ||
177 | inflate_huft *ltree; /* literal/length/eob tree */ | ||
178 | inflate_huft *dtree; /* distance tree */ | ||
179 | |||
180 | }; | ||
181 | 15 | ||
182 | /* memory allocation for inflation */ | 16 | /* memory allocation for inflation */ |
183 | 17 | ||
184 | struct inflate_workspace { | 18 | struct inflate_workspace { |
185 | inflate_codes_statef working_state; | 19 | struct inflate_state inflate_state; |
186 | struct inflate_blocks_state working_blocks_state; | ||
187 | struct internal_state internal_state; | ||
188 | unsigned int tree_work_area_1[19]; | ||
189 | unsigned int tree_work_area_2[288]; | ||
190 | unsigned working_blens[258 + 0x1f + 0x1f]; | ||
191 | inflate_huft working_hufts[MANY]; | ||
192 | unsigned char working_window[1 << MAX_WBITS]; | 20 | unsigned char working_window[1 << MAX_WBITS]; |
193 | }; | 21 | }; |
194 | 22 | ||
diff --git a/security/dummy.c b/security/dummy.c index 64f6da0f422e..6de4a4a5eb13 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -860,7 +860,7 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz | |||
860 | } | 860 | } |
861 | 861 | ||
862 | #ifdef CONFIG_KEYS | 862 | #ifdef CONFIG_KEYS |
863 | static inline int dummy_key_alloc(struct key *key) | 863 | static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx) |
864 | { | 864 | { |
865 | return 0; | 865 | return 0; |
866 | } | 866 | } |
diff --git a/security/keys/key.c b/security/keys/key.c index 3fdc49c6a02c..51f851557389 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -247,8 +247,8 @@ static inline void key_alloc_serial(struct key *key) | |||
247 | * instantiate the key or discard it before returning | 247 | * instantiate the key or discard it before returning |
248 | */ | 248 | */ |
249 | struct key *key_alloc(struct key_type *type, const char *desc, | 249 | struct key *key_alloc(struct key_type *type, const char *desc, |
250 | uid_t uid, gid_t gid, key_perm_t perm, | 250 | uid_t uid, gid_t gid, struct task_struct *ctx, |
251 | int not_in_quota) | 251 | key_perm_t perm, int not_in_quota) |
252 | { | 252 | { |
253 | struct key_user *user = NULL; | 253 | struct key_user *user = NULL; |
254 | struct key *key; | 254 | struct key *key; |
@@ -318,7 +318,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
318 | #endif | 318 | #endif |
319 | 319 | ||
320 | /* let the security module know about the key */ | 320 | /* let the security module know about the key */ |
321 | ret = security_key_alloc(key); | 321 | ret = security_key_alloc(key, ctx); |
322 | if (ret < 0) | 322 | if (ret < 0) |
323 | goto security_error; | 323 | goto security_error; |
324 | 324 | ||
@@ -822,7 +822,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
822 | 822 | ||
823 | /* allocate a new key */ | 823 | /* allocate a new key */ |
824 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, | 824 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, |
825 | perm, not_in_quota); | 825 | current, perm, not_in_quota); |
826 | if (IS_ERR(key)) { | 826 | if (IS_ERR(key)) { |
827 | key_ref = ERR_PTR(PTR_ERR(key)); | 827 | key_ref = ERR_PTR(PTR_ERR(key)); |
828 | goto error_3; | 828 | goto error_3; |
@@ -907,6 +907,10 @@ void key_revoke(struct key *key) | |||
907 | * it */ | 907 | * it */ |
908 | down_write(&key->sem); | 908 | down_write(&key->sem); |
909 | set_bit(KEY_FLAG_REVOKED, &key->flags); | 909 | set_bit(KEY_FLAG_REVOKED, &key->flags); |
910 | |||
911 | if (key->type->revoke) | ||
912 | key->type->revoke(key); | ||
913 | |||
910 | up_write(&key->sem); | 914 | up_write(&key->sem); |
911 | 915 | ||
912 | } /* end key_revoke() */ | 916 | } /* end key_revoke() */ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index bffa924c1f88..1357207fc9df 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -240,13 +240,14 @@ static long keyring_read(const struct key *keyring, | |||
240 | * allocate a keyring and link into the destination keyring | 240 | * allocate a keyring and link into the destination keyring |
241 | */ | 241 | */ |
242 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 242 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
243 | int not_in_quota, struct key *dest) | 243 | struct task_struct *ctx, int not_in_quota, |
244 | struct key *dest) | ||
244 | { | 245 | { |
245 | struct key *keyring; | 246 | struct key *keyring; |
246 | int ret; | 247 | int ret; |
247 | 248 | ||
248 | keyring = key_alloc(&key_type_keyring, description, | 249 | keyring = key_alloc(&key_type_keyring, description, |
249 | uid, gid, | 250 | uid, gid, ctx, |
250 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | 251 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, |
251 | not_in_quota); | 252 | not_in_quota); |
252 | 253 | ||
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 217a0bef3c82..4d9825f9962c 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -67,7 +67,8 @@ struct key root_session_keyring = { | |||
67 | /* | 67 | /* |
68 | * allocate the keyrings to be associated with a UID | 68 | * allocate the keyrings to be associated with a UID |
69 | */ | 69 | */ |
70 | int alloc_uid_keyring(struct user_struct *user) | 70 | int alloc_uid_keyring(struct user_struct *user, |
71 | struct task_struct *ctx) | ||
71 | { | 72 | { |
72 | struct key *uid_keyring, *session_keyring; | 73 | struct key *uid_keyring, *session_keyring; |
73 | char buf[20]; | 74 | char buf[20]; |
@@ -76,7 +77,7 @@ int alloc_uid_keyring(struct user_struct *user) | |||
76 | /* concoct a default session keyring */ | 77 | /* concoct a default session keyring */ |
77 | sprintf(buf, "_uid_ses.%u", user->uid); | 78 | sprintf(buf, "_uid_ses.%u", user->uid); |
78 | 79 | ||
79 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL); | 80 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL); |
80 | if (IS_ERR(session_keyring)) { | 81 | if (IS_ERR(session_keyring)) { |
81 | ret = PTR_ERR(session_keyring); | 82 | ret = PTR_ERR(session_keyring); |
82 | goto error; | 83 | goto error; |
@@ -86,7 +87,7 @@ int alloc_uid_keyring(struct user_struct *user) | |||
86 | * keyring */ | 87 | * keyring */ |
87 | sprintf(buf, "_uid.%u", user->uid); | 88 | sprintf(buf, "_uid.%u", user->uid); |
88 | 89 | ||
89 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, | 90 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, |
90 | session_keyring); | 91 | session_keyring); |
91 | if (IS_ERR(uid_keyring)) { | 92 | if (IS_ERR(uid_keyring)) { |
92 | key_put(session_keyring); | 93 | key_put(session_keyring); |
@@ -143,7 +144,7 @@ int install_thread_keyring(struct task_struct *tsk) | |||
143 | 144 | ||
144 | sprintf(buf, "_tid.%u", tsk->pid); | 145 | sprintf(buf, "_tid.%u", tsk->pid); |
145 | 146 | ||
146 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 147 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
147 | if (IS_ERR(keyring)) { | 148 | if (IS_ERR(keyring)) { |
148 | ret = PTR_ERR(keyring); | 149 | ret = PTR_ERR(keyring); |
149 | goto error; | 150 | goto error; |
@@ -177,7 +178,7 @@ int install_process_keyring(struct task_struct *tsk) | |||
177 | if (!tsk->signal->process_keyring) { | 178 | if (!tsk->signal->process_keyring) { |
178 | sprintf(buf, "_pid.%u", tsk->tgid); | 179 | sprintf(buf, "_pid.%u", tsk->tgid); |
179 | 180 | ||
180 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 181 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
181 | if (IS_ERR(keyring)) { | 182 | if (IS_ERR(keyring)) { |
182 | ret = PTR_ERR(keyring); | 183 | ret = PTR_ERR(keyring); |
183 | goto error; | 184 | goto error; |
@@ -217,7 +218,7 @@ static int install_session_keyring(struct task_struct *tsk, | |||
217 | if (!keyring) { | 218 | if (!keyring) { |
218 | sprintf(buf, "_ses.%u", tsk->tgid); | 219 | sprintf(buf, "_ses.%u", tsk->tgid); |
219 | 220 | ||
220 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); | 221 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); |
221 | if (IS_ERR(keyring)) | 222 | if (IS_ERR(keyring)) |
222 | return PTR_ERR(keyring); | 223 | return PTR_ERR(keyring); |
223 | } | 224 | } |
@@ -390,6 +391,8 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
390 | struct request_key_auth *rka; | 391 | struct request_key_auth *rka; |
391 | key_ref_t key_ref, ret, err; | 392 | key_ref_t key_ref, ret, err; |
392 | 393 | ||
394 | might_sleep(); | ||
395 | |||
393 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | 396 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were |
394 | * searchable, but we failed to find a key or we found a negative key; | 397 | * searchable, but we failed to find a key or we found a negative key; |
395 | * otherwise we want to return a sample error (probably -EACCES) if | 398 | * otherwise we want to return a sample error (probably -EACCES) if |
@@ -495,27 +498,35 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
495 | */ | 498 | */ |
496 | if (context->request_key_auth && | 499 | if (context->request_key_auth && |
497 | context == current && | 500 | context == current && |
498 | type != &key_type_request_key_auth && | 501 | type != &key_type_request_key_auth |
499 | key_validate(context->request_key_auth) == 0 | ||
500 | ) { | 502 | ) { |
501 | rka = context->request_key_auth->payload.data; | 503 | /* defend against the auth key being revoked */ |
504 | down_read(&context->request_key_auth->sem); | ||
502 | 505 | ||
503 | key_ref = search_process_keyrings(type, description, match, | 506 | if (key_validate(context->request_key_auth) == 0) { |
504 | rka->context); | 507 | rka = context->request_key_auth->payload.data; |
505 | 508 | ||
506 | if (!IS_ERR(key_ref)) | 509 | key_ref = search_process_keyrings(type, description, |
507 | goto found; | 510 | match, rka->context); |
508 | 511 | ||
509 | switch (PTR_ERR(key_ref)) { | 512 | up_read(&context->request_key_auth->sem); |
510 | case -EAGAIN: /* no key */ | 513 | |
511 | if (ret) | 514 | if (!IS_ERR(key_ref)) |
515 | goto found; | ||
516 | |||
517 | switch (PTR_ERR(key_ref)) { | ||
518 | case -EAGAIN: /* no key */ | ||
519 | if (ret) | ||
520 | break; | ||
521 | case -ENOKEY: /* negative key */ | ||
522 | ret = key_ref; | ||
512 | break; | 523 | break; |
513 | case -ENOKEY: /* negative key */ | 524 | default: |
514 | ret = key_ref; | 525 | err = key_ref; |
515 | break; | 526 | break; |
516 | default: | 527 | } |
517 | err = key_ref; | 528 | } else { |
518 | break; | 529 | up_read(&context->request_key_auth->sem); |
519 | } | 530 | } |
520 | } | 531 | } |
521 | 532 | ||
@@ -717,7 +728,7 @@ long join_session_keyring(const char *name) | |||
717 | keyring = find_keyring_by_name(name, 0); | 728 | keyring = find_keyring_by_name(name, 0); |
718 | if (PTR_ERR(keyring) == -ENOKEY) { | 729 | if (PTR_ERR(keyring) == -ENOKEY) { |
719 | /* not found - try and create a new one */ | 730 | /* not found - try and create a new one */ |
720 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); | 731 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); |
721 | if (IS_ERR(keyring)) { | 732 | if (IS_ERR(keyring)) { |
722 | ret = PTR_ERR(keyring); | 733 | ret = PTR_ERR(keyring); |
723 | goto error2; | 734 | goto error2; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index f030a0ccbb93..eab66a06ca53 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -48,7 +48,8 @@ static int call_sbin_request_key(struct key *key, | |||
48 | /* allocate a new session keyring */ | 48 | /* allocate a new session keyring */ |
49 | sprintf(desc, "_req.%u", key->serial); | 49 | sprintf(desc, "_req.%u", key->serial); |
50 | 50 | ||
51 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); | 51 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, |
52 | current, 1, NULL); | ||
52 | if (IS_ERR(keyring)) { | 53 | if (IS_ERR(keyring)) { |
53 | ret = PTR_ERR(keyring); | 54 | ret = PTR_ERR(keyring); |
54 | goto error_alloc; | 55 | goto error_alloc; |
@@ -137,7 +138,8 @@ static struct key *__request_key_construction(struct key_type *type, | |||
137 | 138 | ||
138 | /* create a key and add it to the queue */ | 139 | /* create a key and add it to the queue */ |
139 | key = key_alloc(type, description, | 140 | key = key_alloc(type, description, |
140 | current->fsuid, current->fsgid, KEY_POS_ALL, 0); | 141 | current->fsuid, current->fsgid, |
142 | current, KEY_POS_ALL, 0); | ||
141 | if (IS_ERR(key)) | 143 | if (IS_ERR(key)) |
142 | goto alloc_failed; | 144 | goto alloc_failed; |
143 | 145 | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index cce6ba6b0323..cb9817ced3fd 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | static int request_key_auth_instantiate(struct key *, const void *, size_t); | 21 | static int request_key_auth_instantiate(struct key *, const void *, size_t); |
22 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 22 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
23 | static void request_key_auth_revoke(struct key *); | ||
23 | static void request_key_auth_destroy(struct key *); | 24 | static void request_key_auth_destroy(struct key *); |
24 | static long request_key_auth_read(const struct key *, char __user *, size_t); | 25 | static long request_key_auth_read(const struct key *, char __user *, size_t); |
25 | 26 | ||
@@ -31,6 +32,7 @@ struct key_type key_type_request_key_auth = { | |||
31 | .def_datalen = sizeof(struct request_key_auth), | 32 | .def_datalen = sizeof(struct request_key_auth), |
32 | .instantiate = request_key_auth_instantiate, | 33 | .instantiate = request_key_auth_instantiate, |
33 | .describe = request_key_auth_describe, | 34 | .describe = request_key_auth_describe, |
35 | .revoke = request_key_auth_revoke, | ||
34 | .destroy = request_key_auth_destroy, | 36 | .destroy = request_key_auth_destroy, |
35 | .read = request_key_auth_read, | 37 | .read = request_key_auth_read, |
36 | }; | 38 | }; |
@@ -93,6 +95,24 @@ static long request_key_auth_read(const struct key *key, | |||
93 | 95 | ||
94 | /*****************************************************************************/ | 96 | /*****************************************************************************/ |
95 | /* | 97 | /* |
98 | * handle revocation of an authorisation token key | ||
99 | * - called with the key sem write-locked | ||
100 | */ | ||
101 | static void request_key_auth_revoke(struct key *key) | ||
102 | { | ||
103 | struct request_key_auth *rka = key->payload.data; | ||
104 | |||
105 | kenter("{%d}", key->serial); | ||
106 | |||
107 | if (rka->context) { | ||
108 | put_task_struct(rka->context); | ||
109 | rka->context = NULL; | ||
110 | } | ||
111 | |||
112 | } /* end request_key_auth_revoke() */ | ||
113 | |||
114 | /*****************************************************************************/ | ||
115 | /* | ||
96 | * destroy an instantiation authorisation token key | 116 | * destroy an instantiation authorisation token key |
97 | */ | 117 | */ |
98 | static void request_key_auth_destroy(struct key *key) | 118 | static void request_key_auth_destroy(struct key *key) |
@@ -101,6 +121,11 @@ static void request_key_auth_destroy(struct key *key) | |||
101 | 121 | ||
102 | kenter("{%d}", key->serial); | 122 | kenter("{%d}", key->serial); |
103 | 123 | ||
124 | if (rka->context) { | ||
125 | put_task_struct(rka->context); | ||
126 | rka->context = NULL; | ||
127 | } | ||
128 | |||
104 | key_put(rka->target_key); | 129 | key_put(rka->target_key); |
105 | kfree(rka); | 130 | kfree(rka); |
106 | 131 | ||
@@ -131,14 +156,26 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
131 | * another process */ | 156 | * another process */ |
132 | if (current->request_key_auth) { | 157 | if (current->request_key_auth) { |
133 | /* it is - use that instantiation context here too */ | 158 | /* it is - use that instantiation context here too */ |
159 | down_read(¤t->request_key_auth->sem); | ||
160 | |||
161 | /* if the auth key has been revoked, then the key we're | ||
162 | * servicing is already instantiated */ | ||
163 | if (test_bit(KEY_FLAG_REVOKED, | ||
164 | ¤t->request_key_auth->flags)) | ||
165 | goto auth_key_revoked; | ||
166 | |||
134 | irka = current->request_key_auth->payload.data; | 167 | irka = current->request_key_auth->payload.data; |
135 | rka->context = irka->context; | 168 | rka->context = irka->context; |
136 | rka->pid = irka->pid; | 169 | rka->pid = irka->pid; |
170 | get_task_struct(rka->context); | ||
171 | |||
172 | up_read(¤t->request_key_auth->sem); | ||
137 | } | 173 | } |
138 | else { | 174 | else { |
139 | /* it isn't - use this process as the context */ | 175 | /* it isn't - use this process as the context */ |
140 | rka->context = current; | 176 | rka->context = current; |
141 | rka->pid = current->pid; | 177 | rka->pid = current->pid; |
178 | get_task_struct(rka->context); | ||
142 | } | 179 | } |
143 | 180 | ||
144 | rka->target_key = key_get(target); | 181 | rka->target_key = key_get(target); |
@@ -148,7 +185,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
148 | sprintf(desc, "%x", target->serial); | 185 | sprintf(desc, "%x", target->serial); |
149 | 186 | ||
150 | authkey = key_alloc(&key_type_request_key_auth, desc, | 187 | authkey = key_alloc(&key_type_request_key_auth, desc, |
151 | current->fsuid, current->fsgid, | 188 | current->fsuid, current->fsgid, current, |
152 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | | 189 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | |
153 | KEY_USR_VIEW, 1); | 190 | KEY_USR_VIEW, 1); |
154 | if (IS_ERR(authkey)) { | 191 | if (IS_ERR(authkey)) { |
@@ -161,9 +198,15 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
161 | if (ret < 0) | 198 | if (ret < 0) |
162 | goto error_inst; | 199 | goto error_inst; |
163 | 200 | ||
164 | kleave(" = {%d})", authkey->serial); | 201 | kleave(" = {%d}", authkey->serial); |
165 | return authkey; | 202 | return authkey; |
166 | 203 | ||
204 | auth_key_revoked: | ||
205 | up_read(¤t->request_key_auth->sem); | ||
206 | kfree(rka); | ||
207 | kleave("= -EKEYREVOKED"); | ||
208 | return ERR_PTR(-EKEYREVOKED); | ||
209 | |||
167 | error_inst: | 210 | error_inst: |
168 | key_revoke(authkey); | 211 | key_revoke(authkey); |
169 | key_put(authkey); | 212 | key_put(authkey); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 54adc9d31e92..524915dfda64 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -4252,6 +4252,57 @@ static int selinux_setprocattr(struct task_struct *p, | |||
4252 | return size; | 4252 | return size; |
4253 | } | 4253 | } |
4254 | 4254 | ||
4255 | #ifdef CONFIG_KEYS | ||
4256 | |||
4257 | static int selinux_key_alloc(struct key *k, struct task_struct *tsk) | ||
4258 | { | ||
4259 | struct task_security_struct *tsec = tsk->security; | ||
4260 | struct key_security_struct *ksec; | ||
4261 | |||
4262 | ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL); | ||
4263 | if (!ksec) | ||
4264 | return -ENOMEM; | ||
4265 | |||
4266 | ksec->obj = k; | ||
4267 | ksec->sid = tsec->sid; | ||
4268 | k->security = ksec; | ||
4269 | |||
4270 | return 0; | ||
4271 | } | ||
4272 | |||
4273 | static void selinux_key_free(struct key *k) | ||
4274 | { | ||
4275 | struct key_security_struct *ksec = k->security; | ||
4276 | |||
4277 | k->security = NULL; | ||
4278 | kfree(ksec); | ||
4279 | } | ||
4280 | |||
4281 | static int selinux_key_permission(key_ref_t key_ref, | ||
4282 | struct task_struct *ctx, | ||
4283 | key_perm_t perm) | ||
4284 | { | ||
4285 | struct key *key; | ||
4286 | struct task_security_struct *tsec; | ||
4287 | struct key_security_struct *ksec; | ||
4288 | |||
4289 | key = key_ref_to_ptr(key_ref); | ||
4290 | |||
4291 | tsec = ctx->security; | ||
4292 | ksec = key->security; | ||
4293 | |||
4294 | /* if no specific permissions are requested, we skip the | ||
4295 | permission check. No serious, additional covert channels | ||
4296 | appear to be created. */ | ||
4297 | if (perm == 0) | ||
4298 | return 0; | ||
4299 | |||
4300 | return avc_has_perm(tsec->sid, ksec->sid, | ||
4301 | SECCLASS_KEY, perm, NULL); | ||
4302 | } | ||
4303 | |||
4304 | #endif | ||
4305 | |||
4255 | static struct security_operations selinux_ops = { | 4306 | static struct security_operations selinux_ops = { |
4256 | .ptrace = selinux_ptrace, | 4307 | .ptrace = selinux_ptrace, |
4257 | .capget = selinux_capget, | 4308 | .capget = selinux_capget, |
@@ -4406,6 +4457,12 @@ static struct security_operations selinux_ops = { | |||
4406 | .xfrm_state_delete_security = selinux_xfrm_state_delete, | 4457 | .xfrm_state_delete_security = selinux_xfrm_state_delete, |
4407 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, | 4458 | .xfrm_policy_lookup = selinux_xfrm_policy_lookup, |
4408 | #endif | 4459 | #endif |
4460 | |||
4461 | #ifdef CONFIG_KEYS | ||
4462 | .key_alloc = selinux_key_alloc, | ||
4463 | .key_free = selinux_key_free, | ||
4464 | .key_permission = selinux_key_permission, | ||
4465 | #endif | ||
4409 | }; | 4466 | }; |
4410 | 4467 | ||
4411 | static __init int selinux_init(void) | 4468 | static __init int selinux_init(void) |
@@ -4441,6 +4498,13 @@ static __init int selinux_init(void) | |||
4441 | } else { | 4498 | } else { |
4442 | printk(KERN_INFO "SELinux: Starting in permissive mode\n"); | 4499 | printk(KERN_INFO "SELinux: Starting in permissive mode\n"); |
4443 | } | 4500 | } |
4501 | |||
4502 | #ifdef CONFIG_KEYS | ||
4503 | /* Add security information to initial keyrings */ | ||
4504 | security_key_alloc(&root_user_keyring, current); | ||
4505 | security_key_alloc(&root_session_keyring, current); | ||
4506 | #endif | ||
4507 | |||
4444 | return 0; | 4508 | return 0; |
4445 | } | 4509 | } |
4446 | 4510 | ||
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index 70ee65a58817..bc020bde6c86 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
@@ -242,3 +242,9 @@ | |||
242 | S_(SECCLASS_PACKET, PACKET__SEND, "send") | 242 | S_(SECCLASS_PACKET, PACKET__SEND, "send") |
243 | S_(SECCLASS_PACKET, PACKET__RECV, "recv") | 243 | S_(SECCLASS_PACKET, PACKET__RECV, "recv") |
244 | S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") | 244 | S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") |
245 | S_(SECCLASS_KEY, KEY__VIEW, "view") | ||
246 | S_(SECCLASS_KEY, KEY__READ, "read") | ||
247 | S_(SECCLASS_KEY, KEY__WRITE, "write") | ||
248 | S_(SECCLASS_KEY, KEY__SEARCH, "search") | ||
249 | S_(SECCLASS_KEY, KEY__LINK, "link") | ||
250 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") | ||
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 1d9cf3d306bc..1205227a3a33 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
@@ -959,3 +959,11 @@ | |||
959 | #define PACKET__SEND 0x00000001UL | 959 | #define PACKET__SEND 0x00000001UL |
960 | #define PACKET__RECV 0x00000002UL | 960 | #define PACKET__RECV 0x00000002UL |
961 | #define PACKET__RELABELTO 0x00000004UL | 961 | #define PACKET__RELABELTO 0x00000004UL |
962 | |||
963 | #define KEY__VIEW 0x00000001UL | ||
964 | #define KEY__READ 0x00000002UL | ||
965 | #define KEY__WRITE 0x00000004UL | ||
966 | #define KEY__SEARCH 0x00000008UL | ||
967 | #define KEY__LINK 0x00000010UL | ||
968 | #define KEY__SETATTR 0x00000020UL | ||
969 | |||
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h index 3aec75fee4f7..24303b61309f 100644 --- a/security/selinux/include/class_to_string.h +++ b/security/selinux/include/class_to_string.h | |||
@@ -60,3 +60,4 @@ | |||
60 | S_("netlink_kobject_uevent_socket") | 60 | S_("netlink_kobject_uevent_socket") |
61 | S_("appletalk_socket") | 61 | S_("appletalk_socket") |
62 | S_("packet") | 62 | S_("packet") |
63 | S_("key") | ||
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h index a0eb9e281d18..95887aed2a68 100644 --- a/security/selinux/include/flask.h +++ b/security/selinux/include/flask.h | |||
@@ -62,6 +62,7 @@ | |||
62 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 | 62 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 |
63 | #define SECCLASS_APPLETALK_SOCKET 56 | 63 | #define SECCLASS_APPLETALK_SOCKET 56 |
64 | #define SECCLASS_PACKET 57 | 64 | #define SECCLASS_PACKET 57 |
65 | #define SECCLASS_KEY 58 | ||
65 | 66 | ||
66 | /* | 67 | /* |
67 | * Security identifier indices for initial entities | 68 | * Security identifier indices for initial entities |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 54c030778882..8f5547ad1856 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -99,6 +99,11 @@ struct sk_security_struct { | |||
99 | u32 peer_sid; /* SID of peer */ | 99 | u32 peer_sid; /* SID of peer */ |
100 | }; | 100 | }; |
101 | 101 | ||
102 | struct key_security_struct { | ||
103 | struct key *obj; /* back pointer */ | ||
104 | u32 sid; /* SID of key */ | ||
105 | }; | ||
106 | |||
102 | extern unsigned int selinux_checkreqprot; | 107 | extern unsigned int selinux_checkreqprot; |
103 | 108 | ||
104 | #endif /* _SELINUX_OBJSEC_H_ */ | 109 | #endif /* _SELINUX_OBJSEC_H_ */ |
diff --git a/sound/Kconfig b/sound/Kconfig index b65ee4701f98..e0d791a98452 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -58,6 +58,8 @@ source "sound/pci/Kconfig" | |||
58 | 58 | ||
59 | source "sound/ppc/Kconfig" | 59 | source "sound/ppc/Kconfig" |
60 | 60 | ||
61 | source "sound/aoa/Kconfig" | ||
62 | |||
61 | source "sound/arm/Kconfig" | 63 | source "sound/arm/Kconfig" |
62 | 64 | ||
63 | source "sound/mips/Kconfig" | 65 | source "sound/mips/Kconfig" |
diff --git a/sound/Makefile b/sound/Makefile index f352bb235968..a682ea30f0c9 100644 --- a/sound/Makefile +++ b/sound/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | obj-$(CONFIG_SOUND) += soundcore.o | 4 | obj-$(CONFIG_SOUND) += soundcore.o |
5 | obj-$(CONFIG_SOUND_PRIME) += oss/ | 5 | obj-$(CONFIG_SOUND_PRIME) += oss/ |
6 | obj-$(CONFIG_DMASOUND) += oss/ | 6 | obj-$(CONFIG_DMASOUND) += oss/ |
7 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ | 7 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ aoa/ |
8 | 8 | ||
9 | ifeq ($(CONFIG_SND),y) | 9 | ifeq ($(CONFIG_SND),y) |
10 | obj-y += last.o | 10 | obj-y += last.o |
diff --git a/sound/aoa/Kconfig b/sound/aoa/Kconfig new file mode 100644 index 000000000000..a85194fe0b06 --- /dev/null +++ b/sound/aoa/Kconfig | |||
@@ -0,0 +1,17 @@ | |||
1 | menu "Apple Onboard Audio driver" | ||
2 | depends on SND!=n && PPC | ||
3 | |||
4 | config SND_AOA | ||
5 | tristate "Apple Onboard Audio driver" | ||
6 | depends on SOUND && SND_PCM | ||
7 | ---help--- | ||
8 | This option enables the new driver for the various | ||
9 | Apple Onboard Audio components. | ||
10 | |||
11 | source "sound/aoa/fabrics/Kconfig" | ||
12 | |||
13 | source "sound/aoa/codecs/Kconfig" | ||
14 | |||
15 | source "sound/aoa/soundbus/Kconfig" | ||
16 | |||
17 | endmenu | ||
diff --git a/sound/aoa/Makefile b/sound/aoa/Makefile new file mode 100644 index 000000000000..d8de3e7df48d --- /dev/null +++ b/sound/aoa/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | obj-$(CONFIG_SND_AOA) += core/ | ||
2 | obj-$(CONFIG_SND_AOA) += codecs/ | ||
3 | obj-$(CONFIG_SND_AOA) += fabrics/ | ||
4 | obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/ | ||
diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h new file mode 100644 index 000000000000..3a61f3115573 --- /dev/null +++ b/sound/aoa/aoa-gpio.h | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio GPIO definitions | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #ifndef __AOA_GPIO_H | ||
10 | #define __AOA_GPIO_H | ||
11 | #include <linux/workqueue.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <asm/prom.h> | ||
14 | |||
15 | typedef void (*notify_func_t)(void *data); | ||
16 | |||
17 | enum notify_type { | ||
18 | AOA_NOTIFY_HEADPHONE, | ||
19 | AOA_NOTIFY_LINE_IN, | ||
20 | AOA_NOTIFY_LINE_OUT, | ||
21 | }; | ||
22 | |||
23 | struct gpio_runtime; | ||
24 | struct gpio_methods { | ||
25 | /* for initialisation/de-initialisation of the GPIO layer */ | ||
26 | void (*init)(struct gpio_runtime *rt); | ||
27 | void (*exit)(struct gpio_runtime *rt); | ||
28 | |||
29 | /* turn off headphone, speakers, lineout */ | ||
30 | void (*all_amps_off)(struct gpio_runtime *rt); | ||
31 | /* turn headphone, speakers, lineout back to previous setting */ | ||
32 | void (*all_amps_restore)(struct gpio_runtime *rt); | ||
33 | |||
34 | void (*set_headphone)(struct gpio_runtime *rt, int on); | ||
35 | void (*set_speakers)(struct gpio_runtime *rt, int on); | ||
36 | void (*set_lineout)(struct gpio_runtime *rt, int on); | ||
37 | |||
38 | int (*get_headphone)(struct gpio_runtime *rt); | ||
39 | int (*get_speakers)(struct gpio_runtime *rt); | ||
40 | int (*get_lineout)(struct gpio_runtime *rt); | ||
41 | |||
42 | void (*set_hw_reset)(struct gpio_runtime *rt, int on); | ||
43 | |||
44 | /* use this to be notified of any events. The notification | ||
45 | * function is passed the data, and is called in process | ||
46 | * context by the use of schedule_work. | ||
47 | * The interface for it is that setting a function to NULL | ||
48 | * removes it, and they return 0 if the operation succeeded, | ||
49 | * and -EBUSY if the notification is already assigned by | ||
50 | * someone else. */ | ||
51 | int (*set_notify)(struct gpio_runtime *rt, | ||
52 | enum notify_type type, | ||
53 | notify_func_t notify, | ||
54 | void *data); | ||
55 | /* returns 0 if not plugged in, 1 if plugged in | ||
56 | * or a negative error code */ | ||
57 | int (*get_detect)(struct gpio_runtime *rt, | ||
58 | enum notify_type type); | ||
59 | }; | ||
60 | |||
61 | struct gpio_notification { | ||
62 | notify_func_t notify; | ||
63 | void *data; | ||
64 | void *gpio_private; | ||
65 | struct work_struct work; | ||
66 | struct mutex mutex; | ||
67 | }; | ||
68 | |||
69 | struct gpio_runtime { | ||
70 | /* to be assigned by fabric */ | ||
71 | struct device_node *node; | ||
72 | /* since everyone needs this pointer anyway... */ | ||
73 | struct gpio_methods *methods; | ||
74 | /* to be used by the gpio implementation */ | ||
75 | int implementation_private; | ||
76 | struct gpio_notification headphone_notify; | ||
77 | struct gpio_notification line_in_notify; | ||
78 | struct gpio_notification line_out_notify; | ||
79 | }; | ||
80 | |||
81 | #endif /* __AOA_GPIO_H */ | ||
diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h new file mode 100644 index 000000000000..378ef1e9879b --- /dev/null +++ b/sound/aoa/aoa.h | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio definitions | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #ifndef __AOA_H | ||
10 | #define __AOA_H | ||
11 | #include <asm/prom.h> | ||
12 | #include <linux/module.h> | ||
13 | /* So apparently there's a reason for requiring driver.h to be included first! */ | ||
14 | #include <sound/driver.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/asound.h> | ||
17 | #include <sound/control.h> | ||
18 | #include "aoa-gpio.h" | ||
19 | #include "soundbus/soundbus.h" | ||
20 | |||
21 | #define MAX_CODEC_NAME_LEN 32 | ||
22 | |||
23 | struct aoa_codec { | ||
24 | char name[MAX_CODEC_NAME_LEN]; | ||
25 | |||
26 | struct module *owner; | ||
27 | |||
28 | /* called when the fabric wants to init this codec. | ||
29 | * Do alsa card manipulations from here. */ | ||
30 | int (*init)(struct aoa_codec *codec); | ||
31 | |||
32 | /* called when the fabric is done with the codec. | ||
33 | * The alsa card will be cleaned up so don't bother. */ | ||
34 | void (*exit)(struct aoa_codec *codec); | ||
35 | |||
36 | /* May be NULL, but can be used by the fabric. | ||
37 | * Refcounting is the codec driver's responsibility */ | ||
38 | struct device_node *node; | ||
39 | |||
40 | /* assigned by fabric before init() is called, points | ||
41 | * to the soundbus device. Cannot be NULL. */ | ||
42 | struct soundbus_dev *soundbus_dev; | ||
43 | |||
44 | /* assigned by the fabric before init() is called, points | ||
45 | * to the fabric's gpio runtime record for the relevant | ||
46 | * device. */ | ||
47 | struct gpio_runtime *gpio; | ||
48 | |||
49 | /* assigned by the fabric before init() is called, contains | ||
50 | * a codec specific bitmask of what outputs and inputs are | ||
51 | * actually connected */ | ||
52 | u32 connected; | ||
53 | |||
54 | /* data the fabric can associate with this structure */ | ||
55 | void *fabric_data; | ||
56 | |||
57 | /* private! */ | ||
58 | struct list_head list; | ||
59 | struct aoa_fabric *fabric; | ||
60 | }; | ||
61 | |||
62 | /* return 0 on success */ | ||
63 | extern int | ||
64 | aoa_codec_register(struct aoa_codec *codec); | ||
65 | extern void | ||
66 | aoa_codec_unregister(struct aoa_codec *codec); | ||
67 | |||
68 | #define MAX_LAYOUT_NAME_LEN 32 | ||
69 | |||
70 | struct aoa_fabric { | ||
71 | char name[MAX_LAYOUT_NAME_LEN]; | ||
72 | |||
73 | struct module *owner; | ||
74 | |||
75 | /* once codecs register, they are passed here after. | ||
76 | * They are of course not initialised, since the | ||
77 | * fabric is responsible for initialising some fields | ||
78 | * in the codec structure! */ | ||
79 | int (*found_codec)(struct aoa_codec *codec); | ||
80 | /* called for each codec when it is removed, | ||
81 | * also in the case that aoa_fabric_unregister | ||
82 | * is called and all codecs are removed | ||
83 | * from this fabric. | ||
84 | * Also called if found_codec returned 0 but | ||
85 | * the codec couldn't initialise. */ | ||
86 | void (*remove_codec)(struct aoa_codec *codec); | ||
87 | /* If found_codec returned 0, and the codec | ||
88 | * could be initialised, this is called. */ | ||
89 | void (*attached_codec)(struct aoa_codec *codec); | ||
90 | }; | ||
91 | |||
92 | /* return 0 on success, -EEXIST if another fabric is | ||
93 | * registered, -EALREADY if the same fabric is registered. | ||
94 | * Passing NULL can be used to test for the presence | ||
95 | * of another fabric, if -EALREADY is returned there is | ||
96 | * no other fabric present. | ||
97 | * In the case that the function returns -EALREADY | ||
98 | * and the fabric passed is not NULL, all codecs | ||
99 | * that are not assigned yet are passed to the fabric | ||
100 | * again for reconsideration. */ | ||
101 | extern int | ||
102 | aoa_fabric_register(struct aoa_fabric *fabric); | ||
103 | |||
104 | /* it is vital to call this when the fabric exits! | ||
105 | * When calling, the remove_codec will be called | ||
106 | * for all codecs, unless it is NULL. */ | ||
107 | extern void | ||
108 | aoa_fabric_unregister(struct aoa_fabric *fabric); | ||
109 | |||
110 | /* if for some reason you want to get rid of a codec | ||
111 | * before the fabric is removed, use this. | ||
112 | * Note that remove_codec is called for it! */ | ||
113 | extern void | ||
114 | aoa_fabric_unlink_codec(struct aoa_codec *codec); | ||
115 | |||
116 | /* alsa help methods */ | ||
117 | struct aoa_card { | ||
118 | struct snd_card *alsa_card; | ||
119 | }; | ||
120 | |||
121 | extern int aoa_snd_device_new(snd_device_type_t type, | ||
122 | void * device_data, struct snd_device_ops * ops); | ||
123 | extern struct snd_card *aoa_get_card(void); | ||
124 | extern int aoa_snd_ctl_add(struct snd_kcontrol* control); | ||
125 | |||
126 | /* GPIO stuff */ | ||
127 | extern struct gpio_methods *pmf_gpio_methods; | ||
128 | extern struct gpio_methods *ftr_gpio_methods; | ||
129 | /* extern struct gpio_methods *map_gpio_methods; */ | ||
130 | |||
131 | #endif /* __AOA_H */ | ||
diff --git a/sound/aoa/codecs/Kconfig b/sound/aoa/codecs/Kconfig new file mode 100644 index 000000000000..90cf58f68630 --- /dev/null +++ b/sound/aoa/codecs/Kconfig | |||
@@ -0,0 +1,32 @@ | |||
1 | config SND_AOA_ONYX | ||
2 | tristate "support Onyx chip" | ||
3 | depends on SND_AOA | ||
4 | ---help--- | ||
5 | This option enables support for the Onyx (pcm3052) | ||
6 | codec chip found in the latest Apple machines | ||
7 | (most of those with digital audio output). | ||
8 | |||
9 | #config SND_AOA_TOPAZ | ||
10 | # tristate "support Topaz chips" | ||
11 | # depends on SND_AOA | ||
12 | # ---help--- | ||
13 | # This option enables support for the Topaz (CS84xx) | ||
14 | # codec chips found in the latest Apple machines, | ||
15 | # these chips do the digital input and output on | ||
16 | # some PowerMacs. | ||
17 | |||
18 | config SND_AOA_TAS | ||
19 | tristate "support TAS chips" | ||
20 | depends on SND_AOA | ||
21 | ---help--- | ||
22 | This option enables support for the tas chips | ||
23 | found in a lot of Apple Machines, especially | ||
24 | iBooks and PowerBooks without digital. | ||
25 | |||
26 | config SND_AOA_TOONIE | ||
27 | tristate "support Toonie chip" | ||
28 | depends on SND_AOA | ||
29 | ---help--- | ||
30 | This option enables support for the toonie codec | ||
31 | found in the Mac Mini. If you have a Mac Mini and | ||
32 | want to hear sound, select this option. | ||
diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile new file mode 100644 index 000000000000..31cbe68fd42f --- /dev/null +++ b/sound/aoa/codecs/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o | ||
2 | obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o | ||
3 | obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o | ||
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c new file mode 100644 index 000000000000..0b7650788f1f --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c | |||
@@ -0,0 +1,1113 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio driver for Onyx codec | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | * | ||
8 | * | ||
9 | * This is a driver for the pcm3052 codec chip (codenamed Onyx) | ||
10 | * that is present in newer Apple hardware (with digital output). | ||
11 | * | ||
12 | * The Onyx codec has the following connections (listed by the bit | ||
13 | * to be used in aoa_codec.connected): | ||
14 | * 0: analog output | ||
15 | * 1: digital output | ||
16 | * 2: line input | ||
17 | * 3: microphone input | ||
18 | * Note that even though I know of no machine that has for example | ||
19 | * the digital output connected but not the analog, I have handled | ||
20 | * all the different cases in the code so that this driver may serve | ||
21 | * as a good example of what to do. | ||
22 | * | ||
23 | * NOTE: This driver assumes that there's at most one chip to be | ||
24 | * used with one alsa card, in form of creating all kinds | ||
25 | * of mixer elements without regard for their existence. | ||
26 | * But snd-aoa assumes that there's at most one card, so | ||
27 | * this means you can only have one onyx on a system. This | ||
28 | * should probably be fixed by changing the assumption of | ||
29 | * having just a single card on a system, and making the | ||
30 | * 'card' pointer accessible to anyone who needs it instead | ||
31 | * of hiding it in the aoa_snd_* functions... | ||
32 | * | ||
33 | */ | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/module.h> | ||
36 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
37 | MODULE_LICENSE("GPL"); | ||
38 | MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); | ||
39 | |||
40 | #include "snd-aoa-codec-onyx.h" | ||
41 | #include "../aoa.h" | ||
42 | #include "../soundbus/soundbus.h" | ||
43 | |||
44 | |||
45 | #define PFX "snd-aoa-codec-onyx: " | ||
46 | |||
47 | struct onyx { | ||
48 | /* cache registers 65 to 80, they are write-only! */ | ||
49 | u8 cache[16]; | ||
50 | struct i2c_client i2c; | ||
51 | struct aoa_codec codec; | ||
52 | u32 initialised:1, | ||
53 | spdif_locked:1, | ||
54 | analog_locked:1, | ||
55 | original_mute:2; | ||
56 | int open_count; | ||
57 | struct codec_info *codec_info; | ||
58 | |||
59 | /* mutex serializes concurrent access to the device | ||
60 | * and this structure. | ||
61 | */ | ||
62 | struct mutex mutex; | ||
63 | }; | ||
64 | #define codec_to_onyx(c) container_of(c, struct onyx, codec) | ||
65 | |||
66 | /* both return 0 if all ok, else on error */ | ||
67 | static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) | ||
68 | { | ||
69 | s32 v; | ||
70 | |||
71 | if (reg != ONYX_REG_CONTROL) { | ||
72 | *value = onyx->cache[reg-FIRSTREGISTER]; | ||
73 | return 0; | ||
74 | } | ||
75 | v = i2c_smbus_read_byte_data(&onyx->i2c, reg); | ||
76 | if (v < 0) | ||
77 | return -1; | ||
78 | *value = (u8)v; | ||
79 | onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value) | ||
84 | { | ||
85 | int result; | ||
86 | |||
87 | result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value); | ||
88 | if (!result) | ||
89 | onyx->cache[reg-FIRSTREGISTER] = value; | ||
90 | return result; | ||
91 | } | ||
92 | |||
93 | /* alsa stuff */ | ||
94 | |||
95 | static int onyx_dev_register(struct snd_device *dev) | ||
96 | { | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static struct snd_device_ops ops = { | ||
101 | .dev_register = onyx_dev_register, | ||
102 | }; | ||
103 | |||
104 | /* this is necessary because most alsa mixer programs | ||
105 | * can't properly handle the negative range */ | ||
106 | #define VOLUME_RANGE_SHIFT 128 | ||
107 | |||
108 | static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol, | ||
109 | struct snd_ctl_elem_info *uinfo) | ||
110 | { | ||
111 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
112 | uinfo->count = 2; | ||
113 | uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT; | ||
114 | uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT; | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol, | ||
119 | struct snd_ctl_elem_value *ucontrol) | ||
120 | { | ||
121 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
122 | s8 l, r; | ||
123 | |||
124 | mutex_lock(&onyx->mutex); | ||
125 | onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); | ||
126 | onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); | ||
127 | mutex_unlock(&onyx->mutex); | ||
128 | |||
129 | ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; | ||
130 | ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, | ||
136 | struct snd_ctl_elem_value *ucontrol) | ||
137 | { | ||
138 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
139 | s8 l, r; | ||
140 | |||
141 | mutex_lock(&onyx->mutex); | ||
142 | onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); | ||
143 | onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); | ||
144 | |||
145 | if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && | ||
146 | r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { | ||
147 | mutex_unlock(&onyx->mutex); | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, | ||
152 | ucontrol->value.integer.value[0] | ||
153 | - VOLUME_RANGE_SHIFT); | ||
154 | onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, | ||
155 | ucontrol->value.integer.value[1] | ||
156 | - VOLUME_RANGE_SHIFT); | ||
157 | mutex_unlock(&onyx->mutex); | ||
158 | |||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | static struct snd_kcontrol_new volume_control = { | ||
163 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
164 | .name = "Master Playback Volume", | ||
165 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
166 | .info = onyx_snd_vol_info, | ||
167 | .get = onyx_snd_vol_get, | ||
168 | .put = onyx_snd_vol_put, | ||
169 | }; | ||
170 | |||
171 | /* like above, this is necessary because a lot | ||
172 | * of alsa mixer programs don't handle ranges | ||
173 | * that don't start at 0 properly. | ||
174 | * even alsamixer is one of them... */ | ||
175 | #define INPUTGAIN_RANGE_SHIFT (-3) | ||
176 | |||
177 | static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol, | ||
178 | struct snd_ctl_elem_info *uinfo) | ||
179 | { | ||
180 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
181 | uinfo->count = 1; | ||
182 | uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT; | ||
183 | uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT; | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol, | ||
188 | struct snd_ctl_elem_value *ucontrol) | ||
189 | { | ||
190 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
191 | u8 ig; | ||
192 | |||
193 | mutex_lock(&onyx->mutex); | ||
194 | onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig); | ||
195 | mutex_unlock(&onyx->mutex); | ||
196 | |||
197 | ucontrol->value.integer.value[0] = | ||
198 | (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT; | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol, | ||
204 | struct snd_ctl_elem_value *ucontrol) | ||
205 | { | ||
206 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
207 | u8 v, n; | ||
208 | |||
209 | mutex_lock(&onyx->mutex); | ||
210 | onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); | ||
211 | n = v; | ||
212 | n &= ~ONYX_ADC_PGA_GAIN_MASK; | ||
213 | n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) | ||
214 | & ONYX_ADC_PGA_GAIN_MASK; | ||
215 | onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n); | ||
216 | mutex_unlock(&onyx->mutex); | ||
217 | |||
218 | return n != v; | ||
219 | } | ||
220 | |||
221 | static struct snd_kcontrol_new inputgain_control = { | ||
222 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
223 | .name = "Master Capture Volume", | ||
224 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
225 | .info = onyx_snd_inputgain_info, | ||
226 | .get = onyx_snd_inputgain_get, | ||
227 | .put = onyx_snd_inputgain_put, | ||
228 | }; | ||
229 | |||
230 | static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol, | ||
231 | struct snd_ctl_elem_info *uinfo) | ||
232 | { | ||
233 | static char *texts[] = { "Line-In", "Microphone" }; | ||
234 | |||
235 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
236 | uinfo->count = 1; | ||
237 | uinfo->value.enumerated.items = 2; | ||
238 | if (uinfo->value.enumerated.item > 1) | ||
239 | uinfo->value.enumerated.item = 1; | ||
240 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol, | ||
245 | struct snd_ctl_elem_value *ucontrol) | ||
246 | { | ||
247 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
248 | s8 v; | ||
249 | |||
250 | mutex_lock(&onyx->mutex); | ||
251 | onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); | ||
252 | mutex_unlock(&onyx->mutex); | ||
253 | |||
254 | ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static void onyx_set_capture_source(struct onyx *onyx, int mic) | ||
260 | { | ||
261 | s8 v; | ||
262 | |||
263 | mutex_lock(&onyx->mutex); | ||
264 | onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); | ||
265 | v &= ~ONYX_ADC_INPUT_MIC; | ||
266 | if (mic) | ||
267 | v |= ONYX_ADC_INPUT_MIC; | ||
268 | onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); | ||
269 | mutex_unlock(&onyx->mutex); | ||
270 | } | ||
271 | |||
272 | static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, | ||
273 | struct snd_ctl_elem_value *ucontrol) | ||
274 | { | ||
275 | onyx_set_capture_source(snd_kcontrol_chip(kcontrol), | ||
276 | ucontrol->value.enumerated.item[0]); | ||
277 | return 1; | ||
278 | } | ||
279 | |||
280 | static struct snd_kcontrol_new capture_source_control = { | ||
281 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
282 | /* If we name this 'Input Source', it properly shows up in | ||
283 | * alsamixer as a selection, * but it's shown under the | ||
284 | * 'Playback' category. | ||
285 | * If I name it 'Capture Source', it shows up in strange | ||
286 | * ways (two bools of which one can be selected at a | ||
287 | * time) but at least it's shown in the 'Capture' | ||
288 | * category. | ||
289 | * I was told that this was due to backward compatibility, | ||
290 | * but I don't understand then why the mangling is *not* | ||
291 | * done when I name it "Input Source"..... | ||
292 | */ | ||
293 | .name = "Capture Source", | ||
294 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
295 | .info = onyx_snd_capture_source_info, | ||
296 | .get = onyx_snd_capture_source_get, | ||
297 | .put = onyx_snd_capture_source_put, | ||
298 | }; | ||
299 | |||
300 | static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol, | ||
301 | struct snd_ctl_elem_info *uinfo) | ||
302 | { | ||
303 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
304 | uinfo->count = 2; | ||
305 | uinfo->value.integer.min = 0; | ||
306 | uinfo->value.integer.max = 1; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, | ||
311 | struct snd_ctl_elem_value *ucontrol) | ||
312 | { | ||
313 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
314 | u8 c; | ||
315 | |||
316 | mutex_lock(&onyx->mutex); | ||
317 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c); | ||
318 | mutex_unlock(&onyx->mutex); | ||
319 | |||
320 | ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); | ||
321 | ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, | ||
327 | struct snd_ctl_elem_value *ucontrol) | ||
328 | { | ||
329 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
330 | u8 v = 0, c = 0; | ||
331 | int err = -EBUSY; | ||
332 | |||
333 | mutex_lock(&onyx->mutex); | ||
334 | if (onyx->analog_locked) | ||
335 | goto out_unlock; | ||
336 | |||
337 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); | ||
338 | c = v; | ||
339 | c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT); | ||
340 | if (!ucontrol->value.integer.value[0]) | ||
341 | c |= ONYX_MUTE_LEFT; | ||
342 | if (!ucontrol->value.integer.value[1]) | ||
343 | c |= ONYX_MUTE_RIGHT; | ||
344 | err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c); | ||
345 | |||
346 | out_unlock: | ||
347 | mutex_unlock(&onyx->mutex); | ||
348 | |||
349 | return !err ? (v != c) : err; | ||
350 | } | ||
351 | |||
352 | static struct snd_kcontrol_new mute_control = { | ||
353 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
354 | .name = "Master Playback Switch", | ||
355 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
356 | .info = onyx_snd_mute_info, | ||
357 | .get = onyx_snd_mute_get, | ||
358 | .put = onyx_snd_mute_put, | ||
359 | }; | ||
360 | |||
361 | |||
362 | static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol, | ||
363 | struct snd_ctl_elem_info *uinfo) | ||
364 | { | ||
365 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
366 | uinfo->count = 1; | ||
367 | uinfo->value.integer.min = 0; | ||
368 | uinfo->value.integer.max = 1; | ||
369 | return 0; | ||
370 | } | ||
371 | |||
372 | #define FLAG_POLARITY_INVERT 1 | ||
373 | #define FLAG_SPDIFLOCK 2 | ||
374 | |||
375 | static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol, | ||
376 | struct snd_ctl_elem_value *ucontrol) | ||
377 | { | ||
378 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
379 | u8 c; | ||
380 | long int pv = kcontrol->private_value; | ||
381 | u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; | ||
382 | u8 address = (pv >> 8) & 0xff; | ||
383 | u8 mask = pv & 0xff; | ||
384 | |||
385 | mutex_lock(&onyx->mutex); | ||
386 | onyx_read_register(onyx, address, &c); | ||
387 | mutex_unlock(&onyx->mutex); | ||
388 | |||
389 | ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, | ||
395 | struct snd_ctl_elem_value *ucontrol) | ||
396 | { | ||
397 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
398 | u8 v = 0, c = 0; | ||
399 | int err; | ||
400 | long int pv = kcontrol->private_value; | ||
401 | u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; | ||
402 | u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK; | ||
403 | u8 address = (pv >> 8) & 0xff; | ||
404 | u8 mask = pv & 0xff; | ||
405 | |||
406 | mutex_lock(&onyx->mutex); | ||
407 | if (spdiflock && onyx->spdif_locked) { | ||
408 | /* even if alsamixer doesn't care.. */ | ||
409 | err = -EBUSY; | ||
410 | goto out_unlock; | ||
411 | } | ||
412 | onyx_read_register(onyx, address, &v); | ||
413 | c = v; | ||
414 | c &= ~(mask); | ||
415 | if (!!ucontrol->value.integer.value[0] ^ polarity) | ||
416 | c |= mask; | ||
417 | err = onyx_write_register(onyx, address, c); | ||
418 | |||
419 | out_unlock: | ||
420 | mutex_unlock(&onyx->mutex); | ||
421 | |||
422 | return !err ? (v != c) : err; | ||
423 | } | ||
424 | |||
425 | #define SINGLE_BIT(n, type, description, address, mask, flags) \ | ||
426 | static struct snd_kcontrol_new n##_control = { \ | ||
427 | .iface = SNDRV_CTL_ELEM_IFACE_##type, \ | ||
428 | .name = description, \ | ||
429 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
430 | .info = onyx_snd_single_bit_info, \ | ||
431 | .get = onyx_snd_single_bit_get, \ | ||
432 | .put = onyx_snd_single_bit_put, \ | ||
433 | .private_value = (flags << 16) | (address << 8) | mask \ | ||
434 | } | ||
435 | |||
436 | SINGLE_BIT(spdif, | ||
437 | MIXER, | ||
438 | SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), | ||
439 | ONYX_REG_DIG_INFO4, | ||
440 | ONYX_SPDIF_ENABLE, | ||
441 | FLAG_SPDIFLOCK); | ||
442 | SINGLE_BIT(ovr1, | ||
443 | MIXER, | ||
444 | "Oversampling Rate", | ||
445 | ONYX_REG_DAC_CONTROL, | ||
446 | ONYX_OVR1, | ||
447 | 0); | ||
448 | SINGLE_BIT(flt0, | ||
449 | MIXER, | ||
450 | "Fast Digital Filter Rolloff", | ||
451 | ONYX_REG_DAC_FILTER, | ||
452 | ONYX_ROLLOFF_FAST, | ||
453 | FLAG_POLARITY_INVERT); | ||
454 | SINGLE_BIT(hpf, | ||
455 | MIXER, | ||
456 | "Highpass Filter", | ||
457 | ONYX_REG_ADC_HPF_BYPASS, | ||
458 | ONYX_HPF_DISABLE, | ||
459 | FLAG_POLARITY_INVERT); | ||
460 | SINGLE_BIT(dm12, | ||
461 | MIXER, | ||
462 | "Digital De-Emphasis", | ||
463 | ONYX_REG_DAC_DEEMPH, | ||
464 | ONYX_DIGDEEMPH_CTRL, | ||
465 | 0); | ||
466 | |||
467 | static int onyx_spdif_info(struct snd_kcontrol *kcontrol, | ||
468 | struct snd_ctl_elem_info *uinfo) | ||
469 | { | ||
470 | uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; | ||
471 | uinfo->count = 1; | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol, | ||
476 | struct snd_ctl_elem_value *ucontrol) | ||
477 | { | ||
478 | /* datasheet page 30, all others are 0 */ | ||
479 | ucontrol->value.iec958.status[0] = 0x3e; | ||
480 | ucontrol->value.iec958.status[1] = 0xff; | ||
481 | |||
482 | ucontrol->value.iec958.status[3] = 0x3f; | ||
483 | ucontrol->value.iec958.status[4] = 0x0f; | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static struct snd_kcontrol_new onyx_spdif_mask = { | ||
489 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
490 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
491 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), | ||
492 | .info = onyx_spdif_info, | ||
493 | .get = onyx_spdif_mask_get, | ||
494 | }; | ||
495 | |||
496 | static int onyx_spdif_get(struct snd_kcontrol *kcontrol, | ||
497 | struct snd_ctl_elem_value *ucontrol) | ||
498 | { | ||
499 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
500 | u8 v; | ||
501 | |||
502 | mutex_lock(&onyx->mutex); | ||
503 | onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); | ||
504 | ucontrol->value.iec958.status[0] = v & 0x3e; | ||
505 | |||
506 | onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v); | ||
507 | ucontrol->value.iec958.status[1] = v; | ||
508 | |||
509 | onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); | ||
510 | ucontrol->value.iec958.status[3] = v & 0x3f; | ||
511 | |||
512 | onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); | ||
513 | ucontrol->value.iec958.status[4] = v & 0x0f; | ||
514 | mutex_unlock(&onyx->mutex); | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static int onyx_spdif_put(struct snd_kcontrol *kcontrol, | ||
520 | struct snd_ctl_elem_value *ucontrol) | ||
521 | { | ||
522 | struct onyx *onyx = snd_kcontrol_chip(kcontrol); | ||
523 | u8 v; | ||
524 | |||
525 | mutex_lock(&onyx->mutex); | ||
526 | onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); | ||
527 | v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); | ||
528 | onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); | ||
529 | |||
530 | v = ucontrol->value.iec958.status[1]; | ||
531 | onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v); | ||
532 | |||
533 | onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); | ||
534 | v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f); | ||
535 | onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v); | ||
536 | |||
537 | onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); | ||
538 | v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); | ||
539 | onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); | ||
540 | mutex_unlock(&onyx->mutex); | ||
541 | |||
542 | return 1; | ||
543 | } | ||
544 | |||
545 | static struct snd_kcontrol_new onyx_spdif_ctrl = { | ||
546 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
547 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
548 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | ||
549 | .info = onyx_spdif_info, | ||
550 | .get = onyx_spdif_get, | ||
551 | .put = onyx_spdif_put, | ||
552 | }; | ||
553 | |||
554 | /* our registers */ | ||
555 | |||
556 | static u8 register_map[] = { | ||
557 | ONYX_REG_DAC_ATTEN_LEFT, | ||
558 | ONYX_REG_DAC_ATTEN_RIGHT, | ||
559 | ONYX_REG_CONTROL, | ||
560 | ONYX_REG_DAC_CONTROL, | ||
561 | ONYX_REG_DAC_DEEMPH, | ||
562 | ONYX_REG_DAC_FILTER, | ||
563 | ONYX_REG_DAC_OUTPHASE, | ||
564 | ONYX_REG_ADC_CONTROL, | ||
565 | ONYX_REG_ADC_HPF_BYPASS, | ||
566 | ONYX_REG_DIG_INFO1, | ||
567 | ONYX_REG_DIG_INFO2, | ||
568 | ONYX_REG_DIG_INFO3, | ||
569 | ONYX_REG_DIG_INFO4 | ||
570 | }; | ||
571 | |||
572 | static u8 initial_values[ARRAY_SIZE(register_map)] = { | ||
573 | 0x80, 0x80, /* muted */ | ||
574 | ONYX_MRST | ONYX_SRST, /* but handled specially! */ | ||
575 | ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT, | ||
576 | 0, /* no deemphasis */ | ||
577 | ONYX_DAC_FILTER_ALWAYS, | ||
578 | ONYX_OUTPHASE_INVERTED, | ||
579 | (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/ | ||
580 | ONYX_ADC_HPF_ALWAYS, | ||
581 | (1<<2), /* pcm audio */ | ||
582 | 2, /* category: pcm coder */ | ||
583 | 0, /* sampling frequency 44.1 kHz, clock accuracy level II */ | ||
584 | 1 /* 24 bit depth */ | ||
585 | }; | ||
586 | |||
587 | /* reset registers of chip, either to initial or to previous values */ | ||
588 | static int onyx_register_init(struct onyx *onyx) | ||
589 | { | ||
590 | int i; | ||
591 | u8 val; | ||
592 | u8 regs[sizeof(initial_values)]; | ||
593 | |||
594 | if (!onyx->initialised) { | ||
595 | memcpy(regs, initial_values, sizeof(initial_values)); | ||
596 | if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val)) | ||
597 | return -1; | ||
598 | val &= ~ONYX_SILICONVERSION; | ||
599 | val |= initial_values[3]; | ||
600 | regs[3] = val; | ||
601 | } else { | ||
602 | for (i=0; i<sizeof(register_map); i++) | ||
603 | regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER]; | ||
604 | } | ||
605 | |||
606 | for (i=0; i<sizeof(register_map); i++) { | ||
607 | if (onyx_write_register(onyx, register_map[i], regs[i])) | ||
608 | return -1; | ||
609 | } | ||
610 | onyx->initialised = 1; | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | static struct transfer_info onyx_transfers[] = { | ||
615 | /* this is first so we can skip it if no input is present... | ||
616 | * No hardware exists with that, but it's here as an example | ||
617 | * of what to do :) */ | ||
618 | { | ||
619 | /* analog input */ | ||
620 | .formats = SNDRV_PCM_FMTBIT_S8 | | ||
621 | SNDRV_PCM_FMTBIT_S16_BE | | ||
622 | SNDRV_PCM_FMTBIT_S24_BE, | ||
623 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
624 | .transfer_in = 1, | ||
625 | .must_be_clock_source = 0, | ||
626 | .tag = 0, | ||
627 | }, | ||
628 | { | ||
629 | /* if analog and digital are currently off, anything should go, | ||
630 | * so this entry describes everything we can do... */ | ||
631 | .formats = SNDRV_PCM_FMTBIT_S8 | | ||
632 | SNDRV_PCM_FMTBIT_S16_BE | | ||
633 | SNDRV_PCM_FMTBIT_S24_BE | ||
634 | #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE | ||
635 | | SNDRV_PCM_FMTBIT_COMPRESSED_16BE | ||
636 | #endif | ||
637 | , | ||
638 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
639 | .tag = 0, | ||
640 | }, | ||
641 | { | ||
642 | /* analog output */ | ||
643 | .formats = SNDRV_PCM_FMTBIT_S8 | | ||
644 | SNDRV_PCM_FMTBIT_S16_BE | | ||
645 | SNDRV_PCM_FMTBIT_S24_BE, | ||
646 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
647 | .transfer_in = 0, | ||
648 | .must_be_clock_source = 0, | ||
649 | .tag = 1, | ||
650 | }, | ||
651 | { | ||
652 | /* digital pcm output, also possible for analog out */ | ||
653 | .formats = SNDRV_PCM_FMTBIT_S8 | | ||
654 | SNDRV_PCM_FMTBIT_S16_BE | | ||
655 | SNDRV_PCM_FMTBIT_S24_BE, | ||
656 | .rates = SNDRV_PCM_RATE_32000 | | ||
657 | SNDRV_PCM_RATE_44100 | | ||
658 | SNDRV_PCM_RATE_48000, | ||
659 | .transfer_in = 0, | ||
660 | .must_be_clock_source = 0, | ||
661 | .tag = 2, | ||
662 | }, | ||
663 | #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE | ||
664 | Once alsa gets supports for this kind of thing we can add it... | ||
665 | { | ||
666 | /* digital compressed output */ | ||
667 | .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE, | ||
668 | .rates = SNDRV_PCM_RATE_32000 | | ||
669 | SNDRV_PCM_RATE_44100 | | ||
670 | SNDRV_PCM_RATE_48000, | ||
671 | .tag = 2, | ||
672 | }, | ||
673 | #endif | ||
674 | {} | ||
675 | }; | ||
676 | |||
677 | static int onyx_usable(struct codec_info_item *cii, | ||
678 | struct transfer_info *ti, | ||
679 | struct transfer_info *out) | ||
680 | { | ||
681 | u8 v; | ||
682 | struct onyx *onyx = cii->codec_data; | ||
683 | int spdif_enabled, analog_enabled; | ||
684 | |||
685 | mutex_lock(&onyx->mutex); | ||
686 | onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); | ||
687 | spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); | ||
688 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); | ||
689 | analog_enabled = | ||
690 | (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) | ||
691 | != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); | ||
692 | mutex_unlock(&onyx->mutex); | ||
693 | |||
694 | switch (ti->tag) { | ||
695 | case 0: return 1; | ||
696 | case 1: return analog_enabled; | ||
697 | case 2: return spdif_enabled; | ||
698 | } | ||
699 | return 1; | ||
700 | } | ||
701 | |||
702 | static int onyx_prepare(struct codec_info_item *cii, | ||
703 | struct bus_info *bi, | ||
704 | struct snd_pcm_substream *substream) | ||
705 | { | ||
706 | u8 v; | ||
707 | struct onyx *onyx = cii->codec_data; | ||
708 | int err = -EBUSY; | ||
709 | |||
710 | mutex_lock(&onyx->mutex); | ||
711 | |||
712 | #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE | ||
713 | if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { | ||
714 | /* mute and lock analog output */ | ||
715 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); | ||
716 | if (onyx_write_register(onyx | ||
717 | ONYX_REG_DAC_CONTROL, | ||
718 | v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) | ||
719 | goto out_unlock; | ||
720 | onyx->analog_locked = 1; | ||
721 | err = 0; | ||
722 | goto out_unlock; | ||
723 | } | ||
724 | #endif | ||
725 | switch (substream->runtime->rate) { | ||
726 | case 32000: | ||
727 | case 44100: | ||
728 | case 48000: | ||
729 | /* these rates are ok for all outputs */ | ||
730 | /* FIXME: program spdif channel control bits here so that | ||
731 | * userspace doesn't have to if it only plays pcm! */ | ||
732 | err = 0; | ||
733 | goto out_unlock; | ||
734 | default: | ||
735 | /* got some rate that the digital output can't do, | ||
736 | * so disable and lock it */ | ||
737 | onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v); | ||
738 | if (onyx_write_register(onyx, | ||
739 | ONYX_REG_DIG_INFO4, | ||
740 | v & ~ONYX_SPDIF_ENABLE)) | ||
741 | goto out_unlock; | ||
742 | onyx->spdif_locked = 1; | ||
743 | err = 0; | ||
744 | goto out_unlock; | ||
745 | } | ||
746 | |||
747 | out_unlock: | ||
748 | mutex_unlock(&onyx->mutex); | ||
749 | |||
750 | return err; | ||
751 | } | ||
752 | |||
753 | static int onyx_open(struct codec_info_item *cii, | ||
754 | struct snd_pcm_substream *substream) | ||
755 | { | ||
756 | struct onyx *onyx = cii->codec_data; | ||
757 | |||
758 | mutex_lock(&onyx->mutex); | ||
759 | onyx->open_count++; | ||
760 | mutex_unlock(&onyx->mutex); | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | static int onyx_close(struct codec_info_item *cii, | ||
766 | struct snd_pcm_substream *substream) | ||
767 | { | ||
768 | struct onyx *onyx = cii->codec_data; | ||
769 | |||
770 | mutex_lock(&onyx->mutex); | ||
771 | onyx->open_count--; | ||
772 | if (!onyx->open_count) | ||
773 | onyx->spdif_locked = onyx->analog_locked = 0; | ||
774 | mutex_unlock(&onyx->mutex); | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static int onyx_switch_clock(struct codec_info_item *cii, | ||
780 | enum clock_switch what) | ||
781 | { | ||
782 | struct onyx *onyx = cii->codec_data; | ||
783 | |||
784 | mutex_lock(&onyx->mutex); | ||
785 | /* this *MUST* be more elaborate later... */ | ||
786 | switch (what) { | ||
787 | case CLOCK_SWITCH_PREPARE_SLAVE: | ||
788 | onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio); | ||
789 | break; | ||
790 | case CLOCK_SWITCH_SLAVE: | ||
791 | onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio); | ||
792 | break; | ||
793 | default: /* silence warning */ | ||
794 | break; | ||
795 | } | ||
796 | mutex_unlock(&onyx->mutex); | ||
797 | |||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | #ifdef CONFIG_PM | ||
802 | |||
803 | static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) | ||
804 | { | ||
805 | struct onyx *onyx = cii->codec_data; | ||
806 | u8 v; | ||
807 | int err = -ENXIO; | ||
808 | |||
809 | mutex_lock(&onyx->mutex); | ||
810 | if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) | ||
811 | goto out_unlock; | ||
812 | onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); | ||
813 | /* Apple does a sleep here but the datasheet says to do it on resume */ | ||
814 | err = 0; | ||
815 | out_unlock: | ||
816 | mutex_unlock(&onyx->mutex); | ||
817 | |||
818 | return err; | ||
819 | } | ||
820 | |||
821 | static int onyx_resume(struct codec_info_item *cii) | ||
822 | { | ||
823 | struct onyx *onyx = cii->codec_data; | ||
824 | u8 v; | ||
825 | int err = -ENXIO; | ||
826 | |||
827 | mutex_lock(&onyx->mutex); | ||
828 | /* take codec out of suspend */ | ||
829 | if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) | ||
830 | goto out_unlock; | ||
831 | onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); | ||
832 | /* FIXME: should divide by sample rate, but 8k is the lowest we go */ | ||
833 | msleep(2205000/8000); | ||
834 | /* reset all values */ | ||
835 | onyx_register_init(onyx); | ||
836 | err = 0; | ||
837 | out_unlock: | ||
838 | mutex_unlock(&onyx->mutex); | ||
839 | |||
840 | return err; | ||
841 | } | ||
842 | |||
843 | #endif /* CONFIG_PM */ | ||
844 | |||
845 | static struct codec_info onyx_codec_info = { | ||
846 | .transfers = onyx_transfers, | ||
847 | .sysclock_factor = 256, | ||
848 | .bus_factor = 64, | ||
849 | .owner = THIS_MODULE, | ||
850 | .usable = onyx_usable, | ||
851 | .prepare = onyx_prepare, | ||
852 | .open = onyx_open, | ||
853 | .close = onyx_close, | ||
854 | .switch_clock = onyx_switch_clock, | ||
855 | #ifdef CONFIG_PM | ||
856 | .suspend = onyx_suspend, | ||
857 | .resume = onyx_resume, | ||
858 | #endif | ||
859 | }; | ||
860 | |||
861 | static int onyx_init_codec(struct aoa_codec *codec) | ||
862 | { | ||
863 | struct onyx *onyx = codec_to_onyx(codec); | ||
864 | struct snd_kcontrol *ctl; | ||
865 | struct codec_info *ci = &onyx_codec_info; | ||
866 | u8 v; | ||
867 | int err; | ||
868 | |||
869 | if (!onyx->codec.gpio || !onyx->codec.gpio->methods) { | ||
870 | printk(KERN_ERR PFX "gpios not assigned!!\n"); | ||
871 | return -EINVAL; | ||
872 | } | ||
873 | |||
874 | onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); | ||
875 | msleep(1); | ||
876 | onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1); | ||
877 | msleep(1); | ||
878 | onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); | ||
879 | msleep(1); | ||
880 | |||
881 | if (onyx_register_init(onyx)) { | ||
882 | printk(KERN_ERR PFX "failed to initialise onyx registers\n"); | ||
883 | return -ENODEV; | ||
884 | } | ||
885 | |||
886 | if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) { | ||
887 | printk(KERN_ERR PFX "failed to create onyx snd device!\n"); | ||
888 | return -ENODEV; | ||
889 | } | ||
890 | |||
891 | /* nothing connected? what a joke! */ | ||
892 | if ((onyx->codec.connected & 0xF) == 0) | ||
893 | return -ENOTCONN; | ||
894 | |||
895 | /* if no inputs are present... */ | ||
896 | if ((onyx->codec.connected & 0xC) == 0) { | ||
897 | if (!onyx->codec_info) | ||
898 | onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); | ||
899 | if (!onyx->codec_info) | ||
900 | return -ENOMEM; | ||
901 | ci = onyx->codec_info; | ||
902 | *ci = onyx_codec_info; | ||
903 | ci->transfers++; | ||
904 | } | ||
905 | |||
906 | /* if no outputs are present... */ | ||
907 | if ((onyx->codec.connected & 3) == 0) { | ||
908 | if (!onyx->codec_info) | ||
909 | onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); | ||
910 | if (!onyx->codec_info) | ||
911 | return -ENOMEM; | ||
912 | ci = onyx->codec_info; | ||
913 | /* this is fine as there have to be inputs | ||
914 | * if we end up in this part of the code */ | ||
915 | *ci = onyx_codec_info; | ||
916 | ci->transfers[1].formats = 0; | ||
917 | } | ||
918 | |||
919 | if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev, | ||
920 | aoa_get_card(), | ||
921 | ci, onyx)) { | ||
922 | printk(KERN_ERR PFX "error creating onyx pcm\n"); | ||
923 | return -ENODEV; | ||
924 | } | ||
925 | #define ADDCTL(n) \ | ||
926 | do { \ | ||
927 | ctl = snd_ctl_new1(&n, onyx); \ | ||
928 | if (ctl) { \ | ||
929 | ctl->id.device = \ | ||
930 | onyx->codec.soundbus_dev->pcm->device; \ | ||
931 | err = aoa_snd_ctl_add(ctl); \ | ||
932 | if (err) \ | ||
933 | goto error; \ | ||
934 | } \ | ||
935 | } while (0) | ||
936 | |||
937 | if (onyx->codec.soundbus_dev->pcm) { | ||
938 | /* give the user appropriate controls | ||
939 | * depending on what inputs are connected */ | ||
940 | if ((onyx->codec.connected & 0xC) == 0xC) | ||
941 | ADDCTL(capture_source_control); | ||
942 | else if (onyx->codec.connected & 4) | ||
943 | onyx_set_capture_source(onyx, 0); | ||
944 | else | ||
945 | onyx_set_capture_source(onyx, 1); | ||
946 | if (onyx->codec.connected & 0xC) | ||
947 | ADDCTL(inputgain_control); | ||
948 | |||
949 | /* depending on what output is connected, | ||
950 | * give the user appropriate controls */ | ||
951 | if (onyx->codec.connected & 1) { | ||
952 | ADDCTL(volume_control); | ||
953 | ADDCTL(mute_control); | ||
954 | ADDCTL(ovr1_control); | ||
955 | ADDCTL(flt0_control); | ||
956 | ADDCTL(hpf_control); | ||
957 | ADDCTL(dm12_control); | ||
958 | /* spdif control defaults to off */ | ||
959 | } | ||
960 | if (onyx->codec.connected & 2) { | ||
961 | ADDCTL(onyx_spdif_mask); | ||
962 | ADDCTL(onyx_spdif_ctrl); | ||
963 | } | ||
964 | if ((onyx->codec.connected & 3) == 3) | ||
965 | ADDCTL(spdif_control); | ||
966 | /* if only S/PDIF is connected, enable it unconditionally */ | ||
967 | if ((onyx->codec.connected & 3) == 2) { | ||
968 | onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); | ||
969 | v |= ONYX_SPDIF_ENABLE; | ||
970 | onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); | ||
971 | } | ||
972 | } | ||
973 | #undef ADDCTL | ||
974 | printk(KERN_INFO PFX "attached to onyx codec via i2c\n"); | ||
975 | |||
976 | return 0; | ||
977 | error: | ||
978 | onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); | ||
979 | snd_device_free(aoa_get_card(), onyx); | ||
980 | return err; | ||
981 | } | ||
982 | |||
983 | static void onyx_exit_codec(struct aoa_codec *codec) | ||
984 | { | ||
985 | struct onyx *onyx = codec_to_onyx(codec); | ||
986 | |||
987 | if (!onyx->codec.soundbus_dev) { | ||
988 | printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n"); | ||
989 | return; | ||
990 | } | ||
991 | onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); | ||
992 | } | ||
993 | |||
994 | static struct i2c_driver onyx_driver; | ||
995 | |||
996 | static int onyx_create(struct i2c_adapter *adapter, | ||
997 | struct device_node *node, | ||
998 | int addr) | ||
999 | { | ||
1000 | struct onyx *onyx; | ||
1001 | u8 dummy; | ||
1002 | |||
1003 | onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL); | ||
1004 | |||
1005 | if (!onyx) | ||
1006 | return -ENOMEM; | ||
1007 | |||
1008 | mutex_init(&onyx->mutex); | ||
1009 | onyx->i2c.driver = &onyx_driver; | ||
1010 | onyx->i2c.adapter = adapter; | ||
1011 | onyx->i2c.addr = addr & 0x7f; | ||
1012 | strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1); | ||
1013 | |||
1014 | if (i2c_attach_client(&onyx->i2c)) { | ||
1015 | printk(KERN_ERR PFX "failed to attach to i2c\n"); | ||
1016 | goto fail; | ||
1017 | } | ||
1018 | |||
1019 | /* we try to read from register ONYX_REG_CONTROL | ||
1020 | * to check if the codec is present */ | ||
1021 | if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) { | ||
1022 | i2c_detach_client(&onyx->i2c); | ||
1023 | printk(KERN_ERR PFX "failed to read control register\n"); | ||
1024 | goto fail; | ||
1025 | } | ||
1026 | |||
1027 | strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1); | ||
1028 | onyx->codec.owner = THIS_MODULE; | ||
1029 | onyx->codec.init = onyx_init_codec; | ||
1030 | onyx->codec.exit = onyx_exit_codec; | ||
1031 | onyx->codec.node = of_node_get(node); | ||
1032 | |||
1033 | if (aoa_codec_register(&onyx->codec)) { | ||
1034 | i2c_detach_client(&onyx->i2c); | ||
1035 | goto fail; | ||
1036 | } | ||
1037 | printk(KERN_DEBUG PFX "created and attached onyx instance\n"); | ||
1038 | return 0; | ||
1039 | fail: | ||
1040 | kfree(onyx); | ||
1041 | return -EINVAL; | ||
1042 | } | ||
1043 | |||
1044 | static int onyx_i2c_attach(struct i2c_adapter *adapter) | ||
1045 | { | ||
1046 | struct device_node *busnode, *dev = NULL; | ||
1047 | struct pmac_i2c_bus *bus; | ||
1048 | |||
1049 | bus = pmac_i2c_adapter_to_bus(adapter); | ||
1050 | if (bus == NULL) | ||
1051 | return -ENODEV; | ||
1052 | busnode = pmac_i2c_get_bus_node(bus); | ||
1053 | |||
1054 | while ((dev = of_get_next_child(busnode, dev)) != NULL) { | ||
1055 | if (device_is_compatible(dev, "pcm3052")) { | ||
1056 | u32 *addr; | ||
1057 | printk(KERN_DEBUG PFX "found pcm3052\n"); | ||
1058 | addr = (u32 *) get_property(dev, "reg", NULL); | ||
1059 | if (!addr) | ||
1060 | return -ENODEV; | ||
1061 | return onyx_create(adapter, dev, (*addr)>>1); | ||
1062 | } | ||
1063 | } | ||
1064 | |||
1065 | /* if that didn't work, try desperate mode for older | ||
1066 | * machines that have stuff missing from the device tree */ | ||
1067 | |||
1068 | if (!device_is_compatible(busnode, "k2-i2c")) | ||
1069 | return -ENODEV; | ||
1070 | |||
1071 | printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n"); | ||
1072 | /* probe both possible addresses for the onyx chip */ | ||
1073 | if (onyx_create(adapter, NULL, 0x46) == 0) | ||
1074 | return 0; | ||
1075 | return onyx_create(adapter, NULL, 0x47); | ||
1076 | } | ||
1077 | |||
1078 | static int onyx_i2c_detach(struct i2c_client *client) | ||
1079 | { | ||
1080 | struct onyx *onyx = container_of(client, struct onyx, i2c); | ||
1081 | int err; | ||
1082 | |||
1083 | if ((err = i2c_detach_client(client))) | ||
1084 | return err; | ||
1085 | aoa_codec_unregister(&onyx->codec); | ||
1086 | of_node_put(onyx->codec.node); | ||
1087 | if (onyx->codec_info) | ||
1088 | kfree(onyx->codec_info); | ||
1089 | kfree(onyx); | ||
1090 | return 0; | ||
1091 | } | ||
1092 | |||
1093 | static struct i2c_driver onyx_driver = { | ||
1094 | .driver = { | ||
1095 | .name = "aoa_codec_onyx", | ||
1096 | .owner = THIS_MODULE, | ||
1097 | }, | ||
1098 | .attach_adapter = onyx_i2c_attach, | ||
1099 | .detach_client = onyx_i2c_detach, | ||
1100 | }; | ||
1101 | |||
1102 | static int __init onyx_init(void) | ||
1103 | { | ||
1104 | return i2c_add_driver(&onyx_driver); | ||
1105 | } | ||
1106 | |||
1107 | static void __exit onyx_exit(void) | ||
1108 | { | ||
1109 | i2c_del_driver(&onyx_driver); | ||
1110 | } | ||
1111 | |||
1112 | module_init(onyx_init); | ||
1113 | module_exit(onyx_exit); | ||
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h new file mode 100644 index 000000000000..aeedda773699 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio driver for Onyx codec (header) | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | #ifndef __SND_AOA_CODEC_ONYX_H | ||
9 | #define __SND_AOA_CODEC_ONYX_H | ||
10 | #include <stddef.h> | ||
11 | #include <linux/i2c.h> | ||
12 | #include <linux/i2c-dev.h> | ||
13 | #include <asm/pmac_low_i2c.h> | ||
14 | #include <asm/prom.h> | ||
15 | |||
16 | /* PCM3052 register definitions */ | ||
17 | |||
18 | /* the attenuation registers take values from | ||
19 | * -1 (0dB) to -127 (-63.0 dB) or others (muted) */ | ||
20 | #define ONYX_REG_DAC_ATTEN_LEFT 65 | ||
21 | #define FIRSTREGISTER ONYX_REG_DAC_ATTEN_LEFT | ||
22 | #define ONYX_REG_DAC_ATTEN_RIGHT 66 | ||
23 | |||
24 | #define ONYX_REG_CONTROL 67 | ||
25 | # define ONYX_MRST (1<<7) | ||
26 | # define ONYX_SRST (1<<6) | ||
27 | # define ONYX_ADPSV (1<<5) | ||
28 | # define ONYX_DAPSV (1<<4) | ||
29 | # define ONYX_SILICONVERSION (1<<0) | ||
30 | /* all others reserved */ | ||
31 | |||
32 | #define ONYX_REG_DAC_CONTROL 68 | ||
33 | # define ONYX_OVR1 (1<<6) | ||
34 | # define ONYX_MUTE_RIGHT (1<<1) | ||
35 | # define ONYX_MUTE_LEFT (1<<0) | ||
36 | |||
37 | #define ONYX_REG_DAC_DEEMPH 69 | ||
38 | # define ONYX_DIGDEEMPH_SHIFT 5 | ||
39 | # define ONYX_DIGDEEMPH_MASK (3<<ONYX_DIGDEEMPH_SHIFT) | ||
40 | # define ONYX_DIGDEEMPH_CTRL (1<<4) | ||
41 | |||
42 | #define ONYX_REG_DAC_FILTER 70 | ||
43 | # define ONYX_ROLLOFF_FAST (1<<5) | ||
44 | # define ONYX_DAC_FILTER_ALWAYS (1<<2) | ||
45 | |||
46 | #define ONYX_REG_DAC_OUTPHASE 71 | ||
47 | # define ONYX_OUTPHASE_INVERTED (1<<0) | ||
48 | |||
49 | #define ONYX_REG_ADC_CONTROL 72 | ||
50 | # define ONYX_ADC_INPUT_MIC (1<<5) | ||
51 | /* 8 + input gain in dB, valid range for input gain is -4 .. 20 dB */ | ||
52 | # define ONYX_ADC_PGA_GAIN_MASK 0x1f | ||
53 | |||
54 | #define ONYX_REG_ADC_HPF_BYPASS 75 | ||
55 | # define ONYX_HPF_DISABLE (1<<3) | ||
56 | # define ONYX_ADC_HPF_ALWAYS (1<<2) | ||
57 | |||
58 | #define ONYX_REG_DIG_INFO1 77 | ||
59 | # define ONYX_MASK_DIN_TO_BPZ (1<<7) | ||
60 | /* bits 1-5 control channel bits 1-5 */ | ||
61 | # define ONYX_DIGOUT_DISABLE (1<<0) | ||
62 | |||
63 | #define ONYX_REG_DIG_INFO2 78 | ||
64 | /* controls channel bits 8-15 */ | ||
65 | |||
66 | #define ONYX_REG_DIG_INFO3 79 | ||
67 | /* control channel bits 24-29, high 2 bits reserved */ | ||
68 | |||
69 | #define ONYX_REG_DIG_INFO4 80 | ||
70 | # define ONYX_VALIDL (1<<7) | ||
71 | # define ONYX_VALIDR (1<<6) | ||
72 | # define ONYX_SPDIF_ENABLE (1<<5) | ||
73 | /* lower 4 bits control bits 32-35 of channel control and word length */ | ||
74 | # define ONYX_WORDLEN_MASK (0xF) | ||
75 | |||
76 | #endif /* __SND_AOA_CODEC_ONYX_H */ | ||
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h new file mode 100644 index 000000000000..4cfa6757715e --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | This is the program used to generate below table. | ||
3 | |||
4 | #include <stdio.h> | ||
5 | #include <math.h> | ||
6 | int main() { | ||
7 | int dB2; | ||
8 | printf("/" "* This file is only included exactly once!\n"); | ||
9 | printf(" *\n"); | ||
10 | printf(" * If they'd only tell us that generating this table was\n"); | ||
11 | printf(" * as easy as calculating\n"); | ||
12 | printf(" * hwvalue = 1048576.0*exp(0.057564628*dB*2)\n"); | ||
13 | printf(" * :) *" "/\n"); | ||
14 | printf("static int tas_gaintable[] = {\n"); | ||
15 | printf(" 0x000000, /" "* -infinity dB *" "/\n"); | ||
16 | for (dB2=-140;dB2<=36;dB2++) | ||
17 | printf(" 0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0); | ||
18 | printf("};\n\n"); | ||
19 | } | ||
20 | |||
21 | */ | ||
22 | |||
23 | /* This file is only included exactly once! | ||
24 | * | ||
25 | * If they'd only tell us that generating this table was | ||
26 | * as easy as calculating | ||
27 | * hwvalue = 1048576.0*exp(0.057564628*dB*2) | ||
28 | * :) */ | ||
29 | static int tas_gaintable[] = { | ||
30 | 0x000000, /* -infinity dB */ | ||
31 | 0x00014b, /* -70.0 dB */ | ||
32 | 0x00015f, /* -69.5 dB */ | ||
33 | 0x000174, /* -69.0 dB */ | ||
34 | 0x00018a, /* -68.5 dB */ | ||
35 | 0x0001a1, /* -68.0 dB */ | ||
36 | 0x0001ba, /* -67.5 dB */ | ||
37 | 0x0001d4, /* -67.0 dB */ | ||
38 | 0x0001f0, /* -66.5 dB */ | ||
39 | 0x00020d, /* -66.0 dB */ | ||
40 | 0x00022c, /* -65.5 dB */ | ||
41 | 0x00024d, /* -65.0 dB */ | ||
42 | 0x000270, /* -64.5 dB */ | ||
43 | 0x000295, /* -64.0 dB */ | ||
44 | 0x0002bc, /* -63.5 dB */ | ||
45 | 0x0002e6, /* -63.0 dB */ | ||
46 | 0x000312, /* -62.5 dB */ | ||
47 | 0x000340, /* -62.0 dB */ | ||
48 | 0x000372, /* -61.5 dB */ | ||
49 | 0x0003a6, /* -61.0 dB */ | ||
50 | 0x0003dd, /* -60.5 dB */ | ||
51 | 0x000418, /* -60.0 dB */ | ||
52 | 0x000456, /* -59.5 dB */ | ||
53 | 0x000498, /* -59.0 dB */ | ||
54 | 0x0004de, /* -58.5 dB */ | ||
55 | 0x000528, /* -58.0 dB */ | ||
56 | 0x000576, /* -57.5 dB */ | ||
57 | 0x0005c9, /* -57.0 dB */ | ||
58 | 0x000620, /* -56.5 dB */ | ||
59 | 0x00067d, /* -56.0 dB */ | ||
60 | 0x0006e0, /* -55.5 dB */ | ||
61 | 0x000748, /* -55.0 dB */ | ||
62 | 0x0007b7, /* -54.5 dB */ | ||
63 | 0x00082c, /* -54.0 dB */ | ||
64 | 0x0008a8, /* -53.5 dB */ | ||
65 | 0x00092b, /* -53.0 dB */ | ||
66 | 0x0009b6, /* -52.5 dB */ | ||
67 | 0x000a49, /* -52.0 dB */ | ||
68 | 0x000ae5, /* -51.5 dB */ | ||
69 | 0x000b8b, /* -51.0 dB */ | ||
70 | 0x000c3a, /* -50.5 dB */ | ||
71 | 0x000cf3, /* -50.0 dB */ | ||
72 | 0x000db8, /* -49.5 dB */ | ||
73 | 0x000e88, /* -49.0 dB */ | ||
74 | 0x000f64, /* -48.5 dB */ | ||
75 | 0x00104e, /* -48.0 dB */ | ||
76 | 0x001145, /* -47.5 dB */ | ||
77 | 0x00124b, /* -47.0 dB */ | ||
78 | 0x001361, /* -46.5 dB */ | ||
79 | 0x001487, /* -46.0 dB */ | ||
80 | 0x0015be, /* -45.5 dB */ | ||
81 | 0x001708, /* -45.0 dB */ | ||
82 | 0x001865, /* -44.5 dB */ | ||
83 | 0x0019d8, /* -44.0 dB */ | ||
84 | 0x001b60, /* -43.5 dB */ | ||
85 | 0x001cff, /* -43.0 dB */ | ||
86 | 0x001eb7, /* -42.5 dB */ | ||
87 | 0x002089, /* -42.0 dB */ | ||
88 | 0x002276, /* -41.5 dB */ | ||
89 | 0x002481, /* -41.0 dB */ | ||
90 | 0x0026ab, /* -40.5 dB */ | ||
91 | 0x0028f5, /* -40.0 dB */ | ||
92 | 0x002b63, /* -39.5 dB */ | ||
93 | 0x002df5, /* -39.0 dB */ | ||
94 | 0x0030ae, /* -38.5 dB */ | ||
95 | 0x003390, /* -38.0 dB */ | ||
96 | 0x00369e, /* -37.5 dB */ | ||
97 | 0x0039db, /* -37.0 dB */ | ||
98 | 0x003d49, /* -36.5 dB */ | ||
99 | 0x0040ea, /* -36.0 dB */ | ||
100 | 0x0044c3, /* -35.5 dB */ | ||
101 | 0x0048d6, /* -35.0 dB */ | ||
102 | 0x004d27, /* -34.5 dB */ | ||
103 | 0x0051b9, /* -34.0 dB */ | ||
104 | 0x005691, /* -33.5 dB */ | ||
105 | 0x005bb2, /* -33.0 dB */ | ||
106 | 0x006121, /* -32.5 dB */ | ||
107 | 0x0066e3, /* -32.0 dB */ | ||
108 | 0x006cfb, /* -31.5 dB */ | ||
109 | 0x007370, /* -31.0 dB */ | ||
110 | 0x007a48, /* -30.5 dB */ | ||
111 | 0x008186, /* -30.0 dB */ | ||
112 | 0x008933, /* -29.5 dB */ | ||
113 | 0x009154, /* -29.0 dB */ | ||
114 | 0x0099f1, /* -28.5 dB */ | ||
115 | 0x00a310, /* -28.0 dB */ | ||
116 | 0x00acba, /* -27.5 dB */ | ||
117 | 0x00b6f6, /* -27.0 dB */ | ||
118 | 0x00c1cd, /* -26.5 dB */ | ||
119 | 0x00cd49, /* -26.0 dB */ | ||
120 | 0x00d973, /* -25.5 dB */ | ||
121 | 0x00e655, /* -25.0 dB */ | ||
122 | 0x00f3fb, /* -24.5 dB */ | ||
123 | 0x010270, /* -24.0 dB */ | ||
124 | 0x0111c0, /* -23.5 dB */ | ||
125 | 0x0121f9, /* -23.0 dB */ | ||
126 | 0x013328, /* -22.5 dB */ | ||
127 | 0x01455b, /* -22.0 dB */ | ||
128 | 0x0158a2, /* -21.5 dB */ | ||
129 | 0x016d0e, /* -21.0 dB */ | ||
130 | 0x0182af, /* -20.5 dB */ | ||
131 | 0x019999, /* -20.0 dB */ | ||
132 | 0x01b1de, /* -19.5 dB */ | ||
133 | 0x01cb94, /* -19.0 dB */ | ||
134 | 0x01e6cf, /* -18.5 dB */ | ||
135 | 0x0203a7, /* -18.0 dB */ | ||
136 | 0x022235, /* -17.5 dB */ | ||
137 | 0x024293, /* -17.0 dB */ | ||
138 | 0x0264db, /* -16.5 dB */ | ||
139 | 0x02892c, /* -16.0 dB */ | ||
140 | 0x02afa3, /* -15.5 dB */ | ||
141 | 0x02d862, /* -15.0 dB */ | ||
142 | 0x03038a, /* -14.5 dB */ | ||
143 | 0x033142, /* -14.0 dB */ | ||
144 | 0x0361af, /* -13.5 dB */ | ||
145 | 0x0394fa, /* -13.0 dB */ | ||
146 | 0x03cb50, /* -12.5 dB */ | ||
147 | 0x0404de, /* -12.0 dB */ | ||
148 | 0x0441d5, /* -11.5 dB */ | ||
149 | 0x048268, /* -11.0 dB */ | ||
150 | 0x04c6d0, /* -10.5 dB */ | ||
151 | 0x050f44, /* -10.0 dB */ | ||
152 | 0x055c04, /* -9.5 dB */ | ||
153 | 0x05ad50, /* -9.0 dB */ | ||
154 | 0x06036e, /* -8.5 dB */ | ||
155 | 0x065ea5, /* -8.0 dB */ | ||
156 | 0x06bf44, /* -7.5 dB */ | ||
157 | 0x07259d, /* -7.0 dB */ | ||
158 | 0x079207, /* -6.5 dB */ | ||
159 | 0x0804dc, /* -6.0 dB */ | ||
160 | 0x087e80, /* -5.5 dB */ | ||
161 | 0x08ff59, /* -5.0 dB */ | ||
162 | 0x0987d5, /* -4.5 dB */ | ||
163 | 0x0a1866, /* -4.0 dB */ | ||
164 | 0x0ab189, /* -3.5 dB */ | ||
165 | 0x0b53be, /* -3.0 dB */ | ||
166 | 0x0bff91, /* -2.5 dB */ | ||
167 | 0x0cb591, /* -2.0 dB */ | ||
168 | 0x0d765a, /* -1.5 dB */ | ||
169 | 0x0e4290, /* -1.0 dB */ | ||
170 | 0x0f1adf, /* -0.5 dB */ | ||
171 | 0x100000, /* 0.0 dB */ | ||
172 | 0x10f2b4, /* 0.5 dB */ | ||
173 | 0x11f3c9, /* 1.0 dB */ | ||
174 | 0x13041a, /* 1.5 dB */ | ||
175 | 0x14248e, /* 2.0 dB */ | ||
176 | 0x15561a, /* 2.5 dB */ | ||
177 | 0x1699c0, /* 3.0 dB */ | ||
178 | 0x17f094, /* 3.5 dB */ | ||
179 | 0x195bb8, /* 4.0 dB */ | ||
180 | 0x1adc61, /* 4.5 dB */ | ||
181 | 0x1c73d5, /* 5.0 dB */ | ||
182 | 0x1e236d, /* 5.5 dB */ | ||
183 | 0x1fec98, /* 6.0 dB */ | ||
184 | 0x21d0d9, /* 6.5 dB */ | ||
185 | 0x23d1cd, /* 7.0 dB */ | ||
186 | 0x25f125, /* 7.5 dB */ | ||
187 | 0x2830af, /* 8.0 dB */ | ||
188 | 0x2a9254, /* 8.5 dB */ | ||
189 | 0x2d1818, /* 9.0 dB */ | ||
190 | 0x2fc420, /* 9.5 dB */ | ||
191 | 0x3298b0, /* 10.0 dB */ | ||
192 | 0x35982f, /* 10.5 dB */ | ||
193 | 0x38c528, /* 11.0 dB */ | ||
194 | 0x3c224c, /* 11.5 dB */ | ||
195 | 0x3fb278, /* 12.0 dB */ | ||
196 | 0x4378b0, /* 12.5 dB */ | ||
197 | 0x477829, /* 13.0 dB */ | ||
198 | 0x4bb446, /* 13.5 dB */ | ||
199 | 0x5030a1, /* 14.0 dB */ | ||
200 | 0x54f106, /* 14.5 dB */ | ||
201 | 0x59f980, /* 15.0 dB */ | ||
202 | 0x5f4e52, /* 15.5 dB */ | ||
203 | 0x64f403, /* 16.0 dB */ | ||
204 | 0x6aef5e, /* 16.5 dB */ | ||
205 | 0x714575, /* 17.0 dB */ | ||
206 | 0x77fbaa, /* 17.5 dB */ | ||
207 | 0x7f17af, /* 18.0 dB */ | ||
208 | }; | ||
209 | |||
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c new file mode 100644 index 000000000000..2e39ff6ee349 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c | |||
@@ -0,0 +1,654 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio driver for tas codec | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | * | ||
8 | * Open questions: | ||
9 | * - How to distinguish between 3004 and versions? | ||
10 | * | ||
11 | * FIXMEs: | ||
12 | * - This codec driver doesn't honour the 'connected' | ||
13 | * property of the aoa_codec struct, hence if | ||
14 | * it is used in machines where not everything is | ||
15 | * connected it will display wrong mixer elements. | ||
16 | * - Driver assumes that the microphone is always | ||
17 | * monaureal and connected to the right channel of | ||
18 | * the input. This should also be a codec-dependent | ||
19 | * flag, maybe the codec should have 3 different | ||
20 | * bits for the three different possibilities how | ||
21 | * it can be hooked up... | ||
22 | * But as long as I don't see any hardware hooked | ||
23 | * up that way... | ||
24 | * - As Apple notes in their code, the tas3004 seems | ||
25 | * to delay the right channel by one sample. You can | ||
26 | * see this when for example recording stereo in | ||
27 | * audacity, or recording the tas output via cable | ||
28 | * on another machine (use a sinus generator or so). | ||
29 | * I tried programming the BiQuads but couldn't | ||
30 | * make the delay work, maybe someone can read the | ||
31 | * datasheet and fix it. The relevant Apple comment | ||
32 | * is in AppleTAS3004Audio.cpp lines 1637 ff. Note | ||
33 | * that their comment describing how they program | ||
34 | * the filters sucks... | ||
35 | * | ||
36 | * Other things: | ||
37 | * - this should actually register *two* aoa_codec | ||
38 | * structs since it has two inputs. Then it must | ||
39 | * use the prepare callback to forbid running the | ||
40 | * secondary output on a different clock. | ||
41 | * Also, whatever bus knows how to do this must | ||
42 | * provide two soundbus_dev devices and the fabric | ||
43 | * must be able to link them correctly. | ||
44 | * | ||
45 | * I don't even know if Apple ever uses the second | ||
46 | * port on the tas3004 though, I don't think their | ||
47 | * i2s controllers can even do it. OTOH, they all | ||
48 | * derive the clocks from common clocks, so it | ||
49 | * might just be possible. The framework allows the | ||
50 | * codec to refine the transfer_info items in the | ||
51 | * usable callback, so we can simply remove the | ||
52 | * rates the second instance is not using when it | ||
53 | * actually is in use. | ||
54 | * Maybe we'll need to make the sound busses have | ||
55 | * a 'clock group id' value so the codec can | ||
56 | * determine if the two outputs can be driven at | ||
57 | * the same time. But that is likely overkill, up | ||
58 | * to the fabric to not link them up incorrectly, | ||
59 | * and up to the hardware designer to not wire | ||
60 | * them up in some weird unusable way. | ||
61 | */ | ||
62 | #include <stddef.h> | ||
63 | #include <linux/i2c.h> | ||
64 | #include <linux/i2c-dev.h> | ||
65 | #include <asm/pmac_low_i2c.h> | ||
66 | #include <asm/prom.h> | ||
67 | #include <linux/delay.h> | ||
68 | #include <linux/module.h> | ||
69 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
70 | MODULE_LICENSE("GPL"); | ||
71 | MODULE_DESCRIPTION("tas codec driver for snd-aoa"); | ||
72 | |||
73 | #include "snd-aoa-codec-tas.h" | ||
74 | #include "snd-aoa-codec-tas-gain-table.h" | ||
75 | #include "../aoa.h" | ||
76 | #include "../soundbus/soundbus.h" | ||
77 | |||
78 | |||
79 | #define PFX "snd-aoa-codec-tas: " | ||
80 | |||
81 | struct tas { | ||
82 | struct aoa_codec codec; | ||
83 | struct i2c_client i2c; | ||
84 | u32 muted_l:1, muted_r:1, | ||
85 | controls_created:1; | ||
86 | u8 cached_volume_l, cached_volume_r; | ||
87 | u8 mixer_l[3], mixer_r[3]; | ||
88 | u8 acr; | ||
89 | }; | ||
90 | |||
91 | static struct tas *codec_to_tas(struct aoa_codec *codec) | ||
92 | { | ||
93 | return container_of(codec, struct tas, codec); | ||
94 | } | ||
95 | |||
96 | static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data) | ||
97 | { | ||
98 | if (len == 1) | ||
99 | return i2c_smbus_write_byte_data(&tas->i2c, reg, *data); | ||
100 | else | ||
101 | return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); | ||
102 | } | ||
103 | |||
104 | static void tas_set_volume(struct tas *tas) | ||
105 | { | ||
106 | u8 block[6]; | ||
107 | int tmp; | ||
108 | u8 left, right; | ||
109 | |||
110 | left = tas->cached_volume_l; | ||
111 | right = tas->cached_volume_r; | ||
112 | |||
113 | if (left > 177) left = 177; | ||
114 | if (right > 177) right = 177; | ||
115 | |||
116 | if (tas->muted_l) left = 0; | ||
117 | if (tas->muted_r) right = 0; | ||
118 | |||
119 | /* analysing the volume and mixer tables shows | ||
120 | * that they are similar enough when we shift | ||
121 | * the mixer table down by 4 bits. The error | ||
122 | * is miniscule, in just one item the error | ||
123 | * is 1, at a value of 0x07f17b (mixer table | ||
124 | * value is 0x07f17a) */ | ||
125 | tmp = tas_gaintable[left]; | ||
126 | block[0] = tmp>>20; | ||
127 | block[1] = tmp>>12; | ||
128 | block[2] = tmp>>4; | ||
129 | tmp = tas_gaintable[right]; | ||
130 | block[3] = tmp>>20; | ||
131 | block[4] = tmp>>12; | ||
132 | block[5] = tmp>>4; | ||
133 | tas_write_reg(tas, TAS_REG_VOL, 6, block); | ||
134 | } | ||
135 | |||
136 | static void tas_set_mixer(struct tas *tas) | ||
137 | { | ||
138 | u8 block[9]; | ||
139 | int tmp, i; | ||
140 | u8 val; | ||
141 | |||
142 | for (i=0;i<3;i++) { | ||
143 | val = tas->mixer_l[i]; | ||
144 | if (val > 177) val = 177; | ||
145 | tmp = tas_gaintable[val]; | ||
146 | block[3*i+0] = tmp>>16; | ||
147 | block[3*i+1] = tmp>>8; | ||
148 | block[3*i+2] = tmp; | ||
149 | } | ||
150 | tas_write_reg(tas, TAS_REG_LMIX, 9, block); | ||
151 | |||
152 | for (i=0;i<3;i++) { | ||
153 | val = tas->mixer_r[i]; | ||
154 | if (val > 177) val = 177; | ||
155 | tmp = tas_gaintable[val]; | ||
156 | block[3*i+0] = tmp>>16; | ||
157 | block[3*i+1] = tmp>>8; | ||
158 | block[3*i+2] = tmp; | ||
159 | } | ||
160 | tas_write_reg(tas, TAS_REG_RMIX, 9, block); | ||
161 | } | ||
162 | |||
163 | /* alsa stuff */ | ||
164 | |||
165 | static int tas_dev_register(struct snd_device *dev) | ||
166 | { | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static struct snd_device_ops ops = { | ||
171 | .dev_register = tas_dev_register, | ||
172 | }; | ||
173 | |||
174 | static int tas_snd_vol_info(struct snd_kcontrol *kcontrol, | ||
175 | struct snd_ctl_elem_info *uinfo) | ||
176 | { | ||
177 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
178 | uinfo->count = 2; | ||
179 | uinfo->value.integer.min = 0; | ||
180 | uinfo->value.integer.max = 177; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, | ||
185 | struct snd_ctl_elem_value *ucontrol) | ||
186 | { | ||
187 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
188 | |||
189 | ucontrol->value.integer.value[0] = tas->cached_volume_l; | ||
190 | ucontrol->value.integer.value[1] = tas->cached_volume_r; | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, | ||
195 | struct snd_ctl_elem_value *ucontrol) | ||
196 | { | ||
197 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
198 | |||
199 | if (tas->cached_volume_l == ucontrol->value.integer.value[0] | ||
200 | && tas->cached_volume_r == ucontrol->value.integer.value[1]) | ||
201 | return 0; | ||
202 | |||
203 | tas->cached_volume_l = ucontrol->value.integer.value[0]; | ||
204 | tas->cached_volume_r = ucontrol->value.integer.value[1]; | ||
205 | tas_set_volume(tas); | ||
206 | return 1; | ||
207 | } | ||
208 | |||
209 | static struct snd_kcontrol_new volume_control = { | ||
210 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
211 | .name = "Master Playback Volume", | ||
212 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
213 | .info = tas_snd_vol_info, | ||
214 | .get = tas_snd_vol_get, | ||
215 | .put = tas_snd_vol_put, | ||
216 | }; | ||
217 | |||
218 | static int tas_snd_mute_info(struct snd_kcontrol *kcontrol, | ||
219 | struct snd_ctl_elem_info *uinfo) | ||
220 | { | ||
221 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
222 | uinfo->count = 2; | ||
223 | uinfo->value.integer.min = 0; | ||
224 | uinfo->value.integer.max = 1; | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, | ||
229 | struct snd_ctl_elem_value *ucontrol) | ||
230 | { | ||
231 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
232 | |||
233 | ucontrol->value.integer.value[0] = !tas->muted_l; | ||
234 | ucontrol->value.integer.value[1] = !tas->muted_r; | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, | ||
239 | struct snd_ctl_elem_value *ucontrol) | ||
240 | { | ||
241 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
242 | |||
243 | if (tas->muted_l == !ucontrol->value.integer.value[0] | ||
244 | && tas->muted_r == !ucontrol->value.integer.value[1]) | ||
245 | return 0; | ||
246 | |||
247 | tas->muted_l = !ucontrol->value.integer.value[0]; | ||
248 | tas->muted_r = !ucontrol->value.integer.value[1]; | ||
249 | tas_set_volume(tas); | ||
250 | return 1; | ||
251 | } | ||
252 | |||
253 | static struct snd_kcontrol_new mute_control = { | ||
254 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
255 | .name = "Master Playback Switch", | ||
256 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
257 | .info = tas_snd_mute_info, | ||
258 | .get = tas_snd_mute_get, | ||
259 | .put = tas_snd_mute_put, | ||
260 | }; | ||
261 | |||
262 | static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol, | ||
263 | struct snd_ctl_elem_info *uinfo) | ||
264 | { | ||
265 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
266 | uinfo->count = 2; | ||
267 | uinfo->value.integer.min = 0; | ||
268 | uinfo->value.integer.max = 177; | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, | ||
273 | struct snd_ctl_elem_value *ucontrol) | ||
274 | { | ||
275 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
276 | int idx = kcontrol->private_value; | ||
277 | |||
278 | ucontrol->value.integer.value[0] = tas->mixer_l[idx]; | ||
279 | ucontrol->value.integer.value[1] = tas->mixer_r[idx]; | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, | ||
285 | struct snd_ctl_elem_value *ucontrol) | ||
286 | { | ||
287 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
288 | int idx = kcontrol->private_value; | ||
289 | |||
290 | if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] | ||
291 | && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) | ||
292 | return 0; | ||
293 | |||
294 | tas->mixer_l[idx] = ucontrol->value.integer.value[0]; | ||
295 | tas->mixer_r[idx] = ucontrol->value.integer.value[1]; | ||
296 | |||
297 | tas_set_mixer(tas); | ||
298 | return 1; | ||
299 | } | ||
300 | |||
301 | #define MIXER_CONTROL(n,descr,idx) \ | ||
302 | static struct snd_kcontrol_new n##_control = { \ | ||
303 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
304 | .name = descr " Playback Volume", \ | ||
305 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
306 | .info = tas_snd_mixer_info, \ | ||
307 | .get = tas_snd_mixer_get, \ | ||
308 | .put = tas_snd_mixer_put, \ | ||
309 | .private_value = idx, \ | ||
310 | } | ||
311 | |||
312 | MIXER_CONTROL(pcm1, "PCM1", 0); | ||
313 | MIXER_CONTROL(monitor, "Monitor", 2); | ||
314 | |||
315 | static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, | ||
316 | struct snd_ctl_elem_info *uinfo) | ||
317 | { | ||
318 | static char *texts[] = { "Line-In", "Microphone" }; | ||
319 | |||
320 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
321 | uinfo->count = 1; | ||
322 | uinfo->value.enumerated.items = 2; | ||
323 | if (uinfo->value.enumerated.item > 1) | ||
324 | uinfo->value.enumerated.item = 1; | ||
325 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, | ||
330 | struct snd_ctl_elem_value *ucontrol) | ||
331 | { | ||
332 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
333 | |||
334 | ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, | ||
339 | struct snd_ctl_elem_value *ucontrol) | ||
340 | { | ||
341 | struct tas *tas = snd_kcontrol_chip(kcontrol); | ||
342 | int oldacr = tas->acr; | ||
343 | |||
344 | tas->acr &= ~TAS_ACR_INPUT_B; | ||
345 | if (ucontrol->value.enumerated.item[0]) | ||
346 | tas->acr |= TAS_ACR_INPUT_B; | ||
347 | if (oldacr == tas->acr) | ||
348 | return 0; | ||
349 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); | ||
350 | return 1; | ||
351 | } | ||
352 | |||
353 | static struct snd_kcontrol_new capture_source_control = { | ||
354 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
355 | /* If we name this 'Input Source', it properly shows up in | ||
356 | * alsamixer as a selection, * but it's shown under the | ||
357 | * 'Playback' category. | ||
358 | * If I name it 'Capture Source', it shows up in strange | ||
359 | * ways (two bools of which one can be selected at a | ||
360 | * time) but at least it's shown in the 'Capture' | ||
361 | * category. | ||
362 | * I was told that this was due to backward compatibility, | ||
363 | * but I don't understand then why the mangling is *not* | ||
364 | * done when I name it "Input Source"..... | ||
365 | */ | ||
366 | .name = "Capture Source", | ||
367 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
368 | .info = tas_snd_capture_source_info, | ||
369 | .get = tas_snd_capture_source_get, | ||
370 | .put = tas_snd_capture_source_put, | ||
371 | }; | ||
372 | |||
373 | |||
374 | static struct transfer_info tas_transfers[] = { | ||
375 | { | ||
376 | /* input */ | ||
377 | .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | | ||
378 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, | ||
379 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | ||
380 | .transfer_in = 1, | ||
381 | }, | ||
382 | { | ||
383 | /* output */ | ||
384 | .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | | ||
385 | SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, | ||
386 | .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, | ||
387 | .transfer_in = 0, | ||
388 | }, | ||
389 | {} | ||
390 | }; | ||
391 | |||
392 | static int tas_usable(struct codec_info_item *cii, | ||
393 | struct transfer_info *ti, | ||
394 | struct transfer_info *out) | ||
395 | { | ||
396 | return 1; | ||
397 | } | ||
398 | |||
399 | static int tas_reset_init(struct tas *tas) | ||
400 | { | ||
401 | u8 tmp; | ||
402 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); | ||
403 | msleep(1); | ||
404 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); | ||
405 | msleep(1); | ||
406 | tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); | ||
407 | msleep(1); | ||
408 | |||
409 | tas->acr &= ~TAS_ACR_ANALOG_PDOWN; | ||
410 | tas->acr |= TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT; | ||
411 | if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) | ||
412 | return -ENODEV; | ||
413 | |||
414 | tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; | ||
415 | if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) | ||
416 | return -ENODEV; | ||
417 | |||
418 | tmp = 0; | ||
419 | if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) | ||
420 | return -ENODEV; | ||
421 | |||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | /* we are controlled via i2c and assume that is always up | ||
426 | * If that wasn't the case, we'd have to suspend once | ||
427 | * our i2c device is suspended, and then take note of that! */ | ||
428 | static int tas_suspend(struct tas *tas) | ||
429 | { | ||
430 | tas->acr |= TAS_ACR_ANALOG_PDOWN; | ||
431 | tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int tas_resume(struct tas *tas) | ||
436 | { | ||
437 | /* reset codec */ | ||
438 | tas_reset_init(tas); | ||
439 | tas_set_volume(tas); | ||
440 | tas_set_mixer(tas); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | #ifdef CONFIG_PM | ||
445 | static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) | ||
446 | { | ||
447 | return tas_suspend(cii->codec_data); | ||
448 | } | ||
449 | |||
450 | static int _tas_resume(struct codec_info_item *cii) | ||
451 | { | ||
452 | return tas_resume(cii->codec_data); | ||
453 | } | ||
454 | #endif | ||
455 | |||
456 | static struct codec_info tas_codec_info = { | ||
457 | .transfers = tas_transfers, | ||
458 | /* in theory, we can drive it at 512 too... | ||
459 | * but so far the framework doesn't allow | ||
460 | * for that and I don't see much point in it. */ | ||
461 | .sysclock_factor = 256, | ||
462 | /* same here, could be 32 for just one 16 bit format */ | ||
463 | .bus_factor = 64, | ||
464 | .owner = THIS_MODULE, | ||
465 | .usable = tas_usable, | ||
466 | #ifdef CONFIG_PM | ||
467 | .suspend = _tas_suspend, | ||
468 | .resume = _tas_resume, | ||
469 | #endif | ||
470 | }; | ||
471 | |||
472 | static int tas_init_codec(struct aoa_codec *codec) | ||
473 | { | ||
474 | struct tas *tas = codec_to_tas(codec); | ||
475 | int err; | ||
476 | |||
477 | if (!tas->codec.gpio || !tas->codec.gpio->methods) { | ||
478 | printk(KERN_ERR PFX "gpios not assigned!!\n"); | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | |||
482 | if (tas_reset_init(tas)) { | ||
483 | printk(KERN_ERR PFX "tas failed to initialise\n"); | ||
484 | return -ENXIO; | ||
485 | } | ||
486 | |||
487 | if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, | ||
488 | aoa_get_card(), | ||
489 | &tas_codec_info, tas)) { | ||
490 | printk(KERN_ERR PFX "error attaching tas to soundbus\n"); | ||
491 | return -ENODEV; | ||
492 | } | ||
493 | |||
494 | if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) { | ||
495 | printk(KERN_ERR PFX "failed to create tas snd device!\n"); | ||
496 | return -ENODEV; | ||
497 | } | ||
498 | err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas)); | ||
499 | if (err) | ||
500 | goto error; | ||
501 | |||
502 | err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas)); | ||
503 | if (err) | ||
504 | goto error; | ||
505 | |||
506 | err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas)); | ||
507 | if (err) | ||
508 | goto error; | ||
509 | |||
510 | err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas)); | ||
511 | if (err) | ||
512 | goto error; | ||
513 | |||
514 | err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas)); | ||
515 | if (err) | ||
516 | goto error; | ||
517 | |||
518 | return 0; | ||
519 | error: | ||
520 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); | ||
521 | snd_device_free(aoa_get_card(), tas); | ||
522 | return err; | ||
523 | } | ||
524 | |||
525 | static void tas_exit_codec(struct aoa_codec *codec) | ||
526 | { | ||
527 | struct tas *tas = codec_to_tas(codec); | ||
528 | |||
529 | if (!tas->codec.soundbus_dev) | ||
530 | return; | ||
531 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); | ||
532 | } | ||
533 | |||
534 | |||
535 | static struct i2c_driver tas_driver; | ||
536 | |||
537 | static int tas_create(struct i2c_adapter *adapter, | ||
538 | struct device_node *node, | ||
539 | int addr) | ||
540 | { | ||
541 | struct tas *tas; | ||
542 | |||
543 | tas = kzalloc(sizeof(struct tas), GFP_KERNEL); | ||
544 | |||
545 | if (!tas) | ||
546 | return -ENOMEM; | ||
547 | |||
548 | tas->i2c.driver = &tas_driver; | ||
549 | tas->i2c.adapter = adapter; | ||
550 | tas->i2c.addr = addr; | ||
551 | strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); | ||
552 | |||
553 | if (i2c_attach_client(&tas->i2c)) { | ||
554 | printk(KERN_ERR PFX "failed to attach to i2c\n"); | ||
555 | goto fail; | ||
556 | } | ||
557 | |||
558 | strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1); | ||
559 | tas->codec.owner = THIS_MODULE; | ||
560 | tas->codec.init = tas_init_codec; | ||
561 | tas->codec.exit = tas_exit_codec; | ||
562 | tas->codec.node = of_node_get(node); | ||
563 | |||
564 | if (aoa_codec_register(&tas->codec)) { | ||
565 | goto detach; | ||
566 | } | ||
567 | printk(KERN_DEBUG "snd-aoa-codec-tas: created and attached tas instance\n"); | ||
568 | return 0; | ||
569 | detach: | ||
570 | i2c_detach_client(&tas->i2c); | ||
571 | fail: | ||
572 | kfree(tas); | ||
573 | return -EINVAL; | ||
574 | } | ||
575 | |||
576 | static int tas_i2c_attach(struct i2c_adapter *adapter) | ||
577 | { | ||
578 | struct device_node *busnode, *dev = NULL; | ||
579 | struct pmac_i2c_bus *bus; | ||
580 | |||
581 | bus = pmac_i2c_adapter_to_bus(adapter); | ||
582 | if (bus == NULL) | ||
583 | return -ENODEV; | ||
584 | busnode = pmac_i2c_get_bus_node(bus); | ||
585 | |||
586 | while ((dev = of_get_next_child(busnode, dev)) != NULL) { | ||
587 | if (device_is_compatible(dev, "tas3004")) { | ||
588 | u32 *addr; | ||
589 | printk(KERN_DEBUG PFX "found tas3004\n"); | ||
590 | addr = (u32 *) get_property(dev, "reg", NULL); | ||
591 | if (!addr) | ||
592 | continue; | ||
593 | return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); | ||
594 | } | ||
595 | /* older machines have no 'codec' node with a 'compatible' | ||
596 | * property that says 'tas3004', they just have a 'deq' | ||
597 | * node without any such property... */ | ||
598 | if (strcmp(dev->name, "deq") == 0) { | ||
599 | u32 *_addr, addr; | ||
600 | printk(KERN_DEBUG PFX "found 'deq' node\n"); | ||
601 | _addr = (u32 *) get_property(dev, "i2c-address", NULL); | ||
602 | if (!_addr) | ||
603 | continue; | ||
604 | addr = ((*_addr) >> 1) & 0x7f; | ||
605 | /* now, if the address doesn't match any of the two | ||
606 | * that a tas3004 can have, we cannot handle this. | ||
607 | * I doubt it ever happens but hey. */ | ||
608 | if (addr != 0x34 && addr != 0x35) | ||
609 | continue; | ||
610 | return tas_create(adapter, dev, addr); | ||
611 | } | ||
612 | } | ||
613 | return -ENODEV; | ||
614 | } | ||
615 | |||
616 | static int tas_i2c_detach(struct i2c_client *client) | ||
617 | { | ||
618 | struct tas *tas = container_of(client, struct tas, i2c); | ||
619 | int err; | ||
620 | u8 tmp = TAS_ACR_ANALOG_PDOWN; | ||
621 | |||
622 | if ((err = i2c_detach_client(client))) | ||
623 | return err; | ||
624 | aoa_codec_unregister(&tas->codec); | ||
625 | of_node_put(tas->codec.node); | ||
626 | |||
627 | /* power down codec chip */ | ||
628 | tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); | ||
629 | |||
630 | kfree(tas); | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | static struct i2c_driver tas_driver = { | ||
635 | .driver = { | ||
636 | .name = "aoa_codec_tas", | ||
637 | .owner = THIS_MODULE, | ||
638 | }, | ||
639 | .attach_adapter = tas_i2c_attach, | ||
640 | .detach_client = tas_i2c_detach, | ||
641 | }; | ||
642 | |||
643 | static int __init tas_init(void) | ||
644 | { | ||
645 | return i2c_add_driver(&tas_driver); | ||
646 | } | ||
647 | |||
648 | static void __exit tas_exit(void) | ||
649 | { | ||
650 | i2c_del_driver(&tas_driver); | ||
651 | } | ||
652 | |||
653 | module_init(tas_init); | ||
654 | module_exit(tas_exit); | ||
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h new file mode 100644 index 000000000000..daf81f45d83a --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio driver for tas codec (header) | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | #ifndef __SND_AOA_CODECTASH | ||
9 | #define __SND_AOA_CODECTASH | ||
10 | |||
11 | #define TAS_REG_MCS 0x01 /* main control */ | ||
12 | # define TAS_MCS_FASTLOAD (1<<7) | ||
13 | # define TAS_MCS_SCLK64 (1<<6) | ||
14 | # define TAS_MCS_SPORT_MODE_MASK (3<<4) | ||
15 | # define TAS_MCS_SPORT_MODE_I2S (2<<4) | ||
16 | # define TAS_MCS_SPORT_MODE_RJ (1<<4) | ||
17 | # define TAS_MCS_SPORT_MODE_LJ (0<<4) | ||
18 | # define TAS_MCS_SPORT_WL_MASK (3<<0) | ||
19 | # define TAS_MCS_SPORT_WL_16BIT (0<<0) | ||
20 | # define TAS_MCS_SPORT_WL_18BIT (1<<0) | ||
21 | # define TAS_MCS_SPORT_WL_20BIT (2<<0) | ||
22 | # define TAS_MCS_SPORT_WL_24BIT (3<<0) | ||
23 | |||
24 | #define TAS_REG_DRC 0x02 | ||
25 | #define TAS_REG_VOL 0x04 | ||
26 | #define TAS_REG_TREBLE 0x05 | ||
27 | #define TAS_REG_BASS 0x06 | ||
28 | #define TAS_REG_LMIX 0x07 | ||
29 | #define TAS_REG_RMIX 0x08 | ||
30 | |||
31 | #define TAS_REG_ACR 0x40 /* analog control */ | ||
32 | # define TAS_ACR_B_MONAUREAL (1<<7) | ||
33 | # define TAS_ACR_B_MON_SEL_RIGHT (1<<6) | ||
34 | # define TAS_ACR_DEEMPH_MASK (3<<2) | ||
35 | # define TAS_ACR_DEEMPH_OFF (0<<2) | ||
36 | # define TAS_ACR_DEEMPH_48KHz (1<<2) | ||
37 | # define TAS_ACR_DEEMPH_44KHz (2<<2) | ||
38 | # define TAS_ACR_INPUT_B (1<<1) | ||
39 | # define TAS_ACR_ANALOG_PDOWN (1<<0) | ||
40 | |||
41 | #define TAS_REG_MCS2 0x43 /* main control 2 */ | ||
42 | # define TAS_MCS2_ALLPASS (1<<1) | ||
43 | |||
44 | #define TAS_REG_LEFT_BIQUAD6 0x10 | ||
45 | #define TAS_REG_RIGHT_BIQUAD6 0x19 | ||
46 | |||
47 | #endif /* __SND_AOA_CODECTASH */ | ||
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c new file mode 100644 index 000000000000..bcc555647e79 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c | |||
@@ -0,0 +1,141 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio driver for Toonie codec | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | * | ||
8 | * | ||
9 | * This is a driver for the toonie codec chip. This chip is present | ||
10 | * on the Mac Mini and is nothing but a DAC. | ||
11 | */ | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/module.h> | ||
14 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
15 | MODULE_LICENSE("GPL"); | ||
16 | MODULE_DESCRIPTION("toonie codec driver for snd-aoa"); | ||
17 | |||
18 | #include "../aoa.h" | ||
19 | #include "../soundbus/soundbus.h" | ||
20 | |||
21 | |||
22 | #define PFX "snd-aoa-codec-toonie: " | ||
23 | |||
24 | struct toonie { | ||
25 | struct aoa_codec codec; | ||
26 | }; | ||
27 | #define codec_to_toonie(c) container_of(c, struct toonie, codec) | ||
28 | |||
29 | static int toonie_dev_register(struct snd_device *dev) | ||
30 | { | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | static struct snd_device_ops ops = { | ||
35 | .dev_register = toonie_dev_register, | ||
36 | }; | ||
37 | |||
38 | static struct transfer_info toonie_transfers[] = { | ||
39 | /* This thing *only* has analog output, | ||
40 | * the rates are taken from Info.plist | ||
41 | * from Darwin. */ | ||
42 | { | ||
43 | .formats = SNDRV_PCM_FMTBIT_S16_BE | | ||
44 | SNDRV_PCM_FMTBIT_S24_BE, | ||
45 | .rates = SNDRV_PCM_RATE_32000 | | ||
46 | SNDRV_PCM_RATE_44100 | | ||
47 | SNDRV_PCM_RATE_48000 | | ||
48 | SNDRV_PCM_RATE_88200 | | ||
49 | SNDRV_PCM_RATE_96000, | ||
50 | }, | ||
51 | {} | ||
52 | }; | ||
53 | |||
54 | #ifdef CONFIG_PM | ||
55 | static int toonie_suspend(struct codec_info_item *cii, pm_message_t state) | ||
56 | { | ||
57 | /* can we turn it off somehow? */ | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int toonie_resume(struct codec_info_item *cii) | ||
62 | { | ||
63 | return 0; | ||
64 | } | ||
65 | #endif /* CONFIG_PM */ | ||
66 | |||
67 | static struct codec_info toonie_codec_info = { | ||
68 | .transfers = toonie_transfers, | ||
69 | .sysclock_factor = 256, | ||
70 | .bus_factor = 64, | ||
71 | .owner = THIS_MODULE, | ||
72 | #ifdef CONFIG_PM | ||
73 | .suspend = toonie_suspend, | ||
74 | .resume = toonie_resume, | ||
75 | #endif | ||
76 | }; | ||
77 | |||
78 | static int toonie_init_codec(struct aoa_codec *codec) | ||
79 | { | ||
80 | struct toonie *toonie = codec_to_toonie(codec); | ||
81 | |||
82 | if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) { | ||
83 | printk(KERN_ERR PFX "failed to create toonie snd device!\n"); | ||
84 | return -ENODEV; | ||
85 | } | ||
86 | |||
87 | /* nothing connected? what a joke! */ | ||
88 | if (toonie->codec.connected != 1) | ||
89 | return -ENOTCONN; | ||
90 | |||
91 | if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev, | ||
92 | aoa_get_card(), | ||
93 | &toonie_codec_info, toonie)) { | ||
94 | printk(KERN_ERR PFX "error creating toonie pcm\n"); | ||
95 | return -ENODEV; | ||
96 | } | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static void toonie_exit_codec(struct aoa_codec *codec) | ||
102 | { | ||
103 | struct toonie *toonie = codec_to_toonie(codec); | ||
104 | |||
105 | if (!toonie->codec.soundbus_dev) { | ||
106 | printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n"); | ||
107 | return; | ||
108 | } | ||
109 | toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie); | ||
110 | } | ||
111 | |||
112 | static struct toonie *toonie; | ||
113 | |||
114 | static int __init toonie_init(void) | ||
115 | { | ||
116 | toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL); | ||
117 | |||
118 | if (!toonie) | ||
119 | return -ENOMEM; | ||
120 | |||
121 | strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); | ||
122 | toonie->codec.owner = THIS_MODULE; | ||
123 | toonie->codec.init = toonie_init_codec; | ||
124 | toonie->codec.exit = toonie_exit_codec; | ||
125 | |||
126 | if (aoa_codec_register(&toonie->codec)) { | ||
127 | kfree(toonie); | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static void __exit toonie_exit(void) | ||
135 | { | ||
136 | aoa_codec_unregister(&toonie->codec); | ||
137 | kfree(toonie); | ||
138 | } | ||
139 | |||
140 | module_init(toonie_init); | ||
141 | module_exit(toonie_exit); | ||
diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile new file mode 100644 index 000000000000..62dc7287f663 --- /dev/null +++ b/sound/aoa/core/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | obj-$(CONFIG_SND_AOA) += snd-aoa.o | ||
2 | snd-aoa-objs := snd-aoa-core.o \ | ||
3 | snd-aoa-alsa.o \ | ||
4 | snd-aoa-gpio-pmf.o \ | ||
5 | snd-aoa-gpio-feature.o | ||
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c new file mode 100644 index 000000000000..b42fdea77ed0 --- /dev/null +++ b/sound/aoa/core/snd-aoa-alsa.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio Alsa helpers | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | #include <linux/module.h> | ||
9 | #include "snd-aoa-alsa.h" | ||
10 | |||
11 | static int index = -1; | ||
12 | module_param(index, int, 0444); | ||
13 | MODULE_PARM_DESC(index, "index for AOA sound card."); | ||
14 | |||
15 | static struct aoa_card *aoa_card; | ||
16 | |||
17 | int aoa_alsa_init(char *name, struct module *mod) | ||
18 | { | ||
19 | struct snd_card *alsa_card; | ||
20 | int err; | ||
21 | |||
22 | if (aoa_card) | ||
23 | /* cannot be EEXIST due to usage in aoa_fabric_register */ | ||
24 | return -EBUSY; | ||
25 | |||
26 | alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card)); | ||
27 | if (!alsa_card) | ||
28 | return -ENOMEM; | ||
29 | aoa_card = alsa_card->private_data; | ||
30 | aoa_card->alsa_card = alsa_card; | ||
31 | strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); | ||
32 | strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); | ||
33 | strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); | ||
34 | strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); | ||
35 | err = snd_card_register(aoa_card->alsa_card); | ||
36 | if (err < 0) { | ||
37 | printk(KERN_ERR "snd-aoa: couldn't register alsa card\n"); | ||
38 | snd_card_free(aoa_card->alsa_card); | ||
39 | aoa_card = NULL; | ||
40 | return err; | ||
41 | } | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | struct snd_card *aoa_get_card(void) | ||
46 | { | ||
47 | if (aoa_card) | ||
48 | return aoa_card->alsa_card; | ||
49 | return NULL; | ||
50 | } | ||
51 | EXPORT_SYMBOL_GPL(aoa_get_card); | ||
52 | |||
53 | void aoa_alsa_cleanup(void) | ||
54 | { | ||
55 | if (aoa_card) { | ||
56 | snd_card_free(aoa_card->alsa_card); | ||
57 | aoa_card = NULL; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | int aoa_snd_device_new(snd_device_type_t type, | ||
62 | void * device_data, struct snd_device_ops * ops) | ||
63 | { | ||
64 | struct snd_card *card = aoa_get_card(); | ||
65 | int err; | ||
66 | |||
67 | if (!card) return -ENOMEM; | ||
68 | |||
69 | err = snd_device_new(card, type, device_data, ops); | ||
70 | if (err) { | ||
71 | printk(KERN_ERR "snd-aoa: failed to create snd device (%d)\n", err); | ||
72 | return err; | ||
73 | } | ||
74 | err = snd_device_register(card, device_data); | ||
75 | if (err) { | ||
76 | printk(KERN_ERR "snd-aoa: failed to register " | ||
77 | "snd device (%d)\n", err); | ||
78 | printk(KERN_ERR "snd-aoa: have you forgotten the " | ||
79 | "dev_register callback?\n"); | ||
80 | snd_device_free(card, device_data); | ||
81 | } | ||
82 | return err; | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(aoa_snd_device_new); | ||
85 | |||
86 | int aoa_snd_ctl_add(struct snd_kcontrol* control) | ||
87 | { | ||
88 | int err; | ||
89 | |||
90 | if (!aoa_card) return -ENODEV; | ||
91 | |||
92 | err = snd_ctl_add(aoa_card->alsa_card, control); | ||
93 | if (err) | ||
94 | printk(KERN_ERR "snd-aoa: failed to add alsa control (%d)\n", | ||
95 | err); | ||
96 | return err; | ||
97 | } | ||
98 | EXPORT_SYMBOL_GPL(aoa_snd_ctl_add); | ||
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h new file mode 100644 index 000000000000..660d2f1793bb --- /dev/null +++ b/sound/aoa/core/snd-aoa-alsa.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio Alsa private helpers | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #ifndef __SND_AOA_ALSA_H | ||
10 | #define __SND_AOA_ALSA_H | ||
11 | #include "../aoa.h" | ||
12 | |||
13 | extern int aoa_alsa_init(char *name, struct module *mod); | ||
14 | extern void aoa_alsa_cleanup(void); | ||
15 | |||
16 | #endif /* __SND_AOA_ALSA_H */ | ||
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c new file mode 100644 index 000000000000..ecd2d8263f2d --- /dev/null +++ b/sound/aoa/core/snd-aoa-core.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio driver core | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/list.h> | ||
12 | #include "../aoa.h" | ||
13 | #include "snd-aoa-alsa.h" | ||
14 | |||
15 | MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver"); | ||
16 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
17 | MODULE_LICENSE("GPL"); | ||
18 | |||
19 | /* We allow only one fabric. This simplifies things, | ||
20 | * and more don't really make that much sense */ | ||
21 | static struct aoa_fabric *fabric; | ||
22 | static LIST_HEAD(codec_list); | ||
23 | |||
24 | static int attach_codec_to_fabric(struct aoa_codec *c) | ||
25 | { | ||
26 | int err; | ||
27 | |||
28 | if (!try_module_get(c->owner)) | ||
29 | return -EBUSY; | ||
30 | /* found_codec has to be assigned */ | ||
31 | err = -ENOENT; | ||
32 | if (fabric->found_codec) | ||
33 | err = fabric->found_codec(c); | ||
34 | if (err) { | ||
35 | module_put(c->owner); | ||
36 | printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n", | ||
37 | c->name); | ||
38 | return err; | ||
39 | } | ||
40 | c->fabric = fabric; | ||
41 | |||
42 | err = 0; | ||
43 | if (c->init) | ||
44 | err = c->init(c); | ||
45 | if (err) { | ||
46 | printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name); | ||
47 | c->fabric = NULL; | ||
48 | if (fabric->remove_codec) | ||
49 | fabric->remove_codec(c); | ||
50 | module_put(c->owner); | ||
51 | return err; | ||
52 | } | ||
53 | if (fabric->attached_codec) | ||
54 | fabric->attached_codec(c); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | int aoa_codec_register(struct aoa_codec *codec) | ||
59 | { | ||
60 | int err = 0; | ||
61 | |||
62 | /* if there's a fabric already, we can tell if we | ||
63 | * will want to have this codec, so propagate error | ||
64 | * through. Otherwise, this will happen later... */ | ||
65 | if (fabric) | ||
66 | err = attach_codec_to_fabric(codec); | ||
67 | if (!err) | ||
68 | list_add(&codec->list, &codec_list); | ||
69 | return err; | ||
70 | } | ||
71 | EXPORT_SYMBOL_GPL(aoa_codec_register); | ||
72 | |||
73 | void aoa_codec_unregister(struct aoa_codec *codec) | ||
74 | { | ||
75 | list_del(&codec->list); | ||
76 | if (codec->fabric && codec->exit) | ||
77 | codec->exit(codec); | ||
78 | if (fabric && fabric->remove_codec) | ||
79 | fabric->remove_codec(codec); | ||
80 | codec->fabric = NULL; | ||
81 | module_put(codec->owner); | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(aoa_codec_unregister); | ||
84 | |||
85 | int aoa_fabric_register(struct aoa_fabric *new_fabric) | ||
86 | { | ||
87 | struct aoa_codec *c; | ||
88 | int err; | ||
89 | |||
90 | /* allow querying for presence of fabric | ||
91 | * (i.e. do this test first!) */ | ||
92 | if (new_fabric == fabric) { | ||
93 | err = -EALREADY; | ||
94 | goto attach; | ||
95 | } | ||
96 | if (fabric) | ||
97 | return -EEXIST; | ||
98 | if (!new_fabric) | ||
99 | return -EINVAL; | ||
100 | |||
101 | err = aoa_alsa_init(new_fabric->name, new_fabric->owner); | ||
102 | if (err) | ||
103 | return err; | ||
104 | |||
105 | fabric = new_fabric; | ||
106 | |||
107 | attach: | ||
108 | list_for_each_entry(c, &codec_list, list) { | ||
109 | if (c->fabric != fabric) | ||
110 | attach_codec_to_fabric(c); | ||
111 | } | ||
112 | return err; | ||
113 | } | ||
114 | EXPORT_SYMBOL_GPL(aoa_fabric_register); | ||
115 | |||
116 | void aoa_fabric_unregister(struct aoa_fabric *old_fabric) | ||
117 | { | ||
118 | struct aoa_codec *c; | ||
119 | |||
120 | if (fabric != old_fabric) | ||
121 | return; | ||
122 | |||
123 | list_for_each_entry(c, &codec_list, list) { | ||
124 | if (c->fabric) | ||
125 | aoa_fabric_unlink_codec(c); | ||
126 | } | ||
127 | |||
128 | aoa_alsa_cleanup(); | ||
129 | |||
130 | fabric = NULL; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(aoa_fabric_unregister); | ||
133 | |||
134 | void aoa_fabric_unlink_codec(struct aoa_codec *codec) | ||
135 | { | ||
136 | if (!codec->fabric) { | ||
137 | printk(KERN_ERR "snd-aoa: fabric unassigned " | ||
138 | "in aoa_fabric_unlink_codec\n"); | ||
139 | dump_stack(); | ||
140 | return; | ||
141 | } | ||
142 | if (codec->exit) | ||
143 | codec->exit(codec); | ||
144 | if (codec->fabric->remove_codec) | ||
145 | codec->fabric->remove_codec(codec); | ||
146 | codec->fabric = NULL; | ||
147 | module_put(codec->owner); | ||
148 | } | ||
149 | EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec); | ||
150 | |||
151 | static int __init aoa_init(void) | ||
152 | { | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static void __exit aoa_exit(void) | ||
157 | { | ||
158 | aoa_alsa_cleanup(); | ||
159 | } | ||
160 | |||
161 | module_init(aoa_init); | ||
162 | module_exit(aoa_exit); | ||
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c new file mode 100644 index 000000000000..2c6eb7784cc9 --- /dev/null +++ b/sound/aoa/core/snd-aoa-gpio-feature.c | |||
@@ -0,0 +1,399 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio feature call GPIO control | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | * | ||
8 | * This file contains the GPIO control routines for | ||
9 | * direct (through feature calls) access to the GPIO | ||
10 | * registers. | ||
11 | */ | ||
12 | |||
13 | #include <asm/pmac_feature.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include "../aoa.h" | ||
16 | |||
17 | /* TODO: these are 20 global variables | ||
18 | * that aren't used on most machines... | ||
19 | * Move them into a dynamically allocated | ||
20 | * structure and use that. | ||
21 | */ | ||
22 | |||
23 | /* these are the GPIO numbers (register addresses as offsets into | ||
24 | * the GPIO space) */ | ||
25 | static int headphone_mute_gpio; | ||
26 | static int amp_mute_gpio; | ||
27 | static int lineout_mute_gpio; | ||
28 | static int hw_reset_gpio; | ||
29 | static int lineout_detect_gpio; | ||
30 | static int headphone_detect_gpio; | ||
31 | static int linein_detect_gpio; | ||
32 | |||
33 | /* see the SWITCH_GPIO macro */ | ||
34 | static int headphone_mute_gpio_activestate; | ||
35 | static int amp_mute_gpio_activestate; | ||
36 | static int lineout_mute_gpio_activestate; | ||
37 | static int hw_reset_gpio_activestate; | ||
38 | static int lineout_detect_gpio_activestate; | ||
39 | static int headphone_detect_gpio_activestate; | ||
40 | static int linein_detect_gpio_activestate; | ||
41 | |||
42 | /* node pointers that we save when getting the GPIO number | ||
43 | * to get the interrupt later */ | ||
44 | static struct device_node *lineout_detect_node; | ||
45 | static struct device_node *linein_detect_node; | ||
46 | static struct device_node *headphone_detect_node; | ||
47 | |||
48 | static int lineout_detect_irq; | ||
49 | static int linein_detect_irq; | ||
50 | static int headphone_detect_irq; | ||
51 | |||
52 | static struct device_node *get_gpio(char *name, | ||
53 | char *altname, | ||
54 | int *gpioptr, | ||
55 | int *gpioactiveptr) | ||
56 | { | ||
57 | struct device_node *np, *gpio; | ||
58 | u32 *reg; | ||
59 | char *audio_gpio; | ||
60 | |||
61 | *gpioptr = -1; | ||
62 | |||
63 | /* check if we can get it the easy way ... */ | ||
64 | np = of_find_node_by_name(NULL, name); | ||
65 | if (!np) { | ||
66 | /* some machines have only gpioX/extint-gpioX nodes, | ||
67 | * and an audio-gpio property saying what it is ... | ||
68 | * So what we have to do is enumerate all children | ||
69 | * of the gpio node and check them all. */ | ||
70 | gpio = of_find_node_by_name(NULL, "gpio"); | ||
71 | if (!gpio) | ||
72 | return NULL; | ||
73 | while ((np = of_get_next_child(gpio, np))) { | ||
74 | audio_gpio = get_property(np, "audio-gpio", NULL); | ||
75 | if (!audio_gpio) | ||
76 | continue; | ||
77 | if (strcmp(audio_gpio, name) == 0) | ||
78 | break; | ||
79 | if (altname && (strcmp(audio_gpio, altname) == 0)) | ||
80 | break; | ||
81 | } | ||
82 | /* still not found, assume not there */ | ||
83 | if (!np) | ||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | reg = (u32 *)get_property(np, "reg", NULL); | ||
88 | if (!reg) | ||
89 | return NULL; | ||
90 | |||
91 | *gpioptr = *reg; | ||
92 | |||
93 | /* this is a hack, usually the GPIOs 'reg' property | ||
94 | * should have the offset based from the GPIO space | ||
95 | * which is at 0x50, but apparently not always... */ | ||
96 | if (*gpioptr < 0x50) | ||
97 | *gpioptr += 0x50; | ||
98 | |||
99 | reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL); | ||
100 | if (!reg) | ||
101 | /* Apple seems to default to 1, but | ||
102 | * that doesn't seem right at least on most | ||
103 | * machines. So until proven that the opposite | ||
104 | * is necessary, we default to 0 | ||
105 | * (which, incidentally, snd-powermac also does...) */ | ||
106 | *gpioactiveptr = 0; | ||
107 | else | ||
108 | *gpioactiveptr = *reg; | ||
109 | |||
110 | return np; | ||
111 | } | ||
112 | |||
113 | static void get_irq(struct device_node * np, int *irqptr) | ||
114 | { | ||
115 | *irqptr = -1; | ||
116 | if (!np) | ||
117 | return; | ||
118 | if (np->n_intrs != 1) | ||
119 | return; | ||
120 | *irqptr = np->intrs[0].line; | ||
121 | } | ||
122 | |||
123 | /* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ | ||
124 | #define SWITCH_GPIO(name, v, on) \ | ||
125 | (((v)&~1) | ((on)? \ | ||
126 | (name##_gpio_activestate==0?4:5): \ | ||
127 | (name##_gpio_activestate==0?5:4))) | ||
128 | |||
129 | #define FTR_GPIO(name, bit) \ | ||
130 | static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\ | ||
131 | { \ | ||
132 | int v; \ | ||
133 | \ | ||
134 | if (unlikely(!rt)) return; \ | ||
135 | \ | ||
136 | if (name##_mute_gpio < 0) \ | ||
137 | return; \ | ||
138 | \ | ||
139 | v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, \ | ||
140 | name##_mute_gpio, \ | ||
141 | 0); \ | ||
142 | \ | ||
143 | /* muted = !on... */ \ | ||
144 | v = SWITCH_GPIO(name##_mute, v, !on); \ | ||
145 | \ | ||
146 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, \ | ||
147 | name##_mute_gpio, v); \ | ||
148 | \ | ||
149 | rt->implementation_private &= ~(1<<bit); \ | ||
150 | rt->implementation_private |= (!!on << bit); \ | ||
151 | } \ | ||
152 | static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ | ||
153 | { \ | ||
154 | if (unlikely(!rt)) return 0; \ | ||
155 | return (rt->implementation_private>>bit)&1; \ | ||
156 | } | ||
157 | |||
158 | FTR_GPIO(headphone, 0); | ||
159 | FTR_GPIO(amp, 1); | ||
160 | FTR_GPIO(lineout, 2); | ||
161 | |||
162 | static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) | ||
163 | { | ||
164 | int v; | ||
165 | |||
166 | if (unlikely(!rt)) return; | ||
167 | if (hw_reset_gpio < 0) | ||
168 | return; | ||
169 | |||
170 | v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, | ||
171 | hw_reset_gpio, 0); | ||
172 | v = SWITCH_GPIO(hw_reset, v, on); | ||
173 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, | ||
174 | hw_reset_gpio, v); | ||
175 | } | ||
176 | |||
177 | static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) | ||
178 | { | ||
179 | int saved; | ||
180 | |||
181 | if (unlikely(!rt)) return; | ||
182 | saved = rt->implementation_private; | ||
183 | ftr_gpio_set_headphone(rt, 0); | ||
184 | ftr_gpio_set_amp(rt, 0); | ||
185 | ftr_gpio_set_lineout(rt, 0); | ||
186 | rt->implementation_private = saved; | ||
187 | } | ||
188 | |||
189 | static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) | ||
190 | { | ||
191 | int s; | ||
192 | |||
193 | if (unlikely(!rt)) return; | ||
194 | s = rt->implementation_private; | ||
195 | ftr_gpio_set_headphone(rt, (s>>0)&1); | ||
196 | ftr_gpio_set_amp(rt, (s>>1)&1); | ||
197 | ftr_gpio_set_lineout(rt, (s>>2)&1); | ||
198 | } | ||
199 | |||
200 | static void ftr_handle_notify(void *data) | ||
201 | { | ||
202 | struct gpio_notification *notif = data; | ||
203 | |||
204 | mutex_lock(¬if->mutex); | ||
205 | if (notif->notify) | ||
206 | notif->notify(notif->data); | ||
207 | mutex_unlock(¬if->mutex); | ||
208 | } | ||
209 | |||
210 | static void ftr_gpio_init(struct gpio_runtime *rt) | ||
211 | { | ||
212 | get_gpio("headphone-mute", NULL, | ||
213 | &headphone_mute_gpio, | ||
214 | &headphone_mute_gpio_activestate); | ||
215 | get_gpio("amp-mute", NULL, | ||
216 | &_mute_gpio, | ||
217 | &_mute_gpio_activestate); | ||
218 | get_gpio("lineout-mute", NULL, | ||
219 | &lineout_mute_gpio, | ||
220 | &lineout_mute_gpio_activestate); | ||
221 | get_gpio("hw-reset", "audio-hw-reset", | ||
222 | &hw_reset_gpio, | ||
223 | &hw_reset_gpio_activestate); | ||
224 | |||
225 | headphone_detect_node = get_gpio("headphone-detect", NULL, | ||
226 | &headphone_detect_gpio, | ||
227 | &headphone_detect_gpio_activestate); | ||
228 | /* go Apple, and thanks for giving these different names | ||
229 | * across the board... */ | ||
230 | lineout_detect_node = get_gpio("lineout-detect", "line-output-detect", | ||
231 | &lineout_detect_gpio, | ||
232 | &lineout_detect_gpio_activestate); | ||
233 | linein_detect_node = get_gpio("linein-detect", "line-input-detect", | ||
234 | &linein_detect_gpio, | ||
235 | &linein_detect_gpio_activestate); | ||
236 | |||
237 | get_irq(headphone_detect_node, &headphone_detect_irq); | ||
238 | get_irq(lineout_detect_node, &lineout_detect_irq); | ||
239 | get_irq(linein_detect_node, &linein_detect_irq); | ||
240 | |||
241 | ftr_gpio_all_amps_off(rt); | ||
242 | rt->implementation_private = 0; | ||
243 | INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify, | ||
244 | &rt->headphone_notify); | ||
245 | INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify, | ||
246 | &rt->line_in_notify); | ||
247 | INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify, | ||
248 | &rt->line_out_notify); | ||
249 | mutex_init(&rt->headphone_notify.mutex); | ||
250 | mutex_init(&rt->line_in_notify.mutex); | ||
251 | mutex_init(&rt->line_out_notify.mutex); | ||
252 | } | ||
253 | |||
254 | static void ftr_gpio_exit(struct gpio_runtime *rt) | ||
255 | { | ||
256 | ftr_gpio_all_amps_off(rt); | ||
257 | rt->implementation_private = 0; | ||
258 | if (rt->headphone_notify.notify) | ||
259 | free_irq(headphone_detect_irq, &rt->headphone_notify); | ||
260 | if (rt->line_in_notify.gpio_private) | ||
261 | free_irq(linein_detect_irq, &rt->line_in_notify); | ||
262 | if (rt->line_out_notify.gpio_private) | ||
263 | free_irq(lineout_detect_irq, &rt->line_out_notify); | ||
264 | cancel_delayed_work(&rt->headphone_notify.work); | ||
265 | cancel_delayed_work(&rt->line_in_notify.work); | ||
266 | cancel_delayed_work(&rt->line_out_notify.work); | ||
267 | flush_scheduled_work(); | ||
268 | mutex_destroy(&rt->headphone_notify.mutex); | ||
269 | mutex_destroy(&rt->line_in_notify.mutex); | ||
270 | mutex_destroy(&rt->line_out_notify.mutex); | ||
271 | } | ||
272 | |||
273 | static irqreturn_t ftr_handle_notify_irq(int xx, | ||
274 | void *data, | ||
275 | struct pt_regs *regs) | ||
276 | { | ||
277 | struct gpio_notification *notif = data; | ||
278 | |||
279 | schedule_work(¬if->work); | ||
280 | |||
281 | return IRQ_HANDLED; | ||
282 | } | ||
283 | |||
284 | static int ftr_set_notify(struct gpio_runtime *rt, | ||
285 | enum notify_type type, | ||
286 | notify_func_t notify, | ||
287 | void *data) | ||
288 | { | ||
289 | struct gpio_notification *notif; | ||
290 | notify_func_t old; | ||
291 | int irq; | ||
292 | char *name; | ||
293 | int err = -EBUSY; | ||
294 | |||
295 | switch (type) { | ||
296 | case AOA_NOTIFY_HEADPHONE: | ||
297 | notif = &rt->headphone_notify; | ||
298 | name = "headphone-detect"; | ||
299 | irq = headphone_detect_irq; | ||
300 | break; | ||
301 | case AOA_NOTIFY_LINE_IN: | ||
302 | notif = &rt->line_in_notify; | ||
303 | name = "linein-detect"; | ||
304 | irq = linein_detect_irq; | ||
305 | break; | ||
306 | case AOA_NOTIFY_LINE_OUT: | ||
307 | notif = &rt->line_out_notify; | ||
308 | name = "lineout-detect"; | ||
309 | irq = lineout_detect_irq; | ||
310 | break; | ||
311 | default: | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | if (irq == -1) | ||
316 | return -ENODEV; | ||
317 | |||
318 | mutex_lock(¬if->mutex); | ||
319 | |||
320 | old = notif->notify; | ||
321 | |||
322 | if (!old && !notify) { | ||
323 | err = 0; | ||
324 | goto out_unlock; | ||
325 | } | ||
326 | |||
327 | if (old && notify) { | ||
328 | if (old == notify && notif->data == data) | ||
329 | err = 0; | ||
330 | goto out_unlock; | ||
331 | } | ||
332 | |||
333 | if (old && !notify) | ||
334 | free_irq(irq, notif); | ||
335 | |||
336 | if (!old && notify) { | ||
337 | err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif); | ||
338 | if (err) | ||
339 | goto out_unlock; | ||
340 | } | ||
341 | |||
342 | notif->notify = notify; | ||
343 | notif->data = data; | ||
344 | |||
345 | err = 0; | ||
346 | out_unlock: | ||
347 | mutex_unlock(¬if->mutex); | ||
348 | return err; | ||
349 | } | ||
350 | |||
351 | static int ftr_get_detect(struct gpio_runtime *rt, | ||
352 | enum notify_type type) | ||
353 | { | ||
354 | int gpio, ret, active; | ||
355 | |||
356 | switch (type) { | ||
357 | case AOA_NOTIFY_HEADPHONE: | ||
358 | gpio = headphone_detect_gpio; | ||
359 | active = headphone_detect_gpio_activestate; | ||
360 | break; | ||
361 | case AOA_NOTIFY_LINE_IN: | ||
362 | gpio = linein_detect_gpio; | ||
363 | active = linein_detect_gpio_activestate; | ||
364 | break; | ||
365 | case AOA_NOTIFY_LINE_OUT: | ||
366 | gpio = lineout_detect_gpio; | ||
367 | active = lineout_detect_gpio_activestate; | ||
368 | break; | ||
369 | default: | ||
370 | return -EINVAL; | ||
371 | } | ||
372 | |||
373 | if (gpio == -1) | ||
374 | return -ENODEV; | ||
375 | |||
376 | ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0); | ||
377 | if (ret < 0) | ||
378 | return ret; | ||
379 | return ((ret >> 1) & 1) == active; | ||
380 | } | ||
381 | |||
382 | static struct gpio_methods methods = { | ||
383 | .init = ftr_gpio_init, | ||
384 | .exit = ftr_gpio_exit, | ||
385 | .all_amps_off = ftr_gpio_all_amps_off, | ||
386 | .all_amps_restore = ftr_gpio_all_amps_restore, | ||
387 | .set_headphone = ftr_gpio_set_headphone, | ||
388 | .set_speakers = ftr_gpio_set_amp, | ||
389 | .set_lineout = ftr_gpio_set_lineout, | ||
390 | .set_hw_reset = ftr_gpio_set_hw_reset, | ||
391 | .get_headphone = ftr_gpio_get_headphone, | ||
392 | .get_speakers = ftr_gpio_get_amp, | ||
393 | .get_lineout = ftr_gpio_get_lineout, | ||
394 | .set_notify = ftr_set_notify, | ||
395 | .get_detect = ftr_get_detect, | ||
396 | }; | ||
397 | |||
398 | struct gpio_methods *ftr_gpio_methods = &methods; | ||
399 | EXPORT_SYMBOL_GPL(ftr_gpio_methods); | ||
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c new file mode 100644 index 000000000000..0e9b9bb2a6de --- /dev/null +++ b/sound/aoa/core/snd-aoa-gpio-pmf.c | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio pmf GPIOs | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #include <asm/pmac_feature.h> | ||
10 | #include <asm/pmac_pfunc.h> | ||
11 | #include "../aoa.h" | ||
12 | |||
13 | #define PMF_GPIO(name, bit) \ | ||
14 | static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\ | ||
15 | { \ | ||
16 | struct pmf_args args = { .count = 1, .u[0].v = !on }; \ | ||
17 | \ | ||
18 | if (unlikely(!rt)) return; \ | ||
19 | pmf_call_function(rt->node, #name "-mute", &args); \ | ||
20 | rt->implementation_private &= ~(1<<bit); \ | ||
21 | rt->implementation_private |= (!!on << bit); \ | ||
22 | } \ | ||
23 | static int pmf_gpio_get_##name(struct gpio_runtime *rt) \ | ||
24 | { \ | ||
25 | if (unlikely(!rt)) return 0; \ | ||
26 | return (rt->implementation_private>>bit)&1; \ | ||
27 | } | ||
28 | |||
29 | PMF_GPIO(headphone, 0); | ||
30 | PMF_GPIO(amp, 1); | ||
31 | PMF_GPIO(lineout, 2); | ||
32 | |||
33 | static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on) | ||
34 | { | ||
35 | struct pmf_args args = { .count = 1, .u[0].v = !!on }; | ||
36 | |||
37 | if (unlikely(!rt)) return; | ||
38 | pmf_call_function(rt->node, "hw-reset", &args); | ||
39 | } | ||
40 | |||
41 | static void pmf_gpio_all_amps_off(struct gpio_runtime *rt) | ||
42 | { | ||
43 | int saved; | ||
44 | |||
45 | if (unlikely(!rt)) return; | ||
46 | saved = rt->implementation_private; | ||
47 | pmf_gpio_set_headphone(rt, 0); | ||
48 | pmf_gpio_set_amp(rt, 0); | ||
49 | pmf_gpio_set_lineout(rt, 0); | ||
50 | rt->implementation_private = saved; | ||
51 | } | ||
52 | |||
53 | static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt) | ||
54 | { | ||
55 | int s; | ||
56 | |||
57 | if (unlikely(!rt)) return; | ||
58 | s = rt->implementation_private; | ||
59 | pmf_gpio_set_headphone(rt, (s>>0)&1); | ||
60 | pmf_gpio_set_amp(rt, (s>>1)&1); | ||
61 | pmf_gpio_set_lineout(rt, (s>>2)&1); | ||
62 | } | ||
63 | |||
64 | static void pmf_handle_notify(void *data) | ||
65 | { | ||
66 | struct gpio_notification *notif = data; | ||
67 | |||
68 | mutex_lock(¬if->mutex); | ||
69 | if (notif->notify) | ||
70 | notif->notify(notif->data); | ||
71 | mutex_unlock(¬if->mutex); | ||
72 | } | ||
73 | |||
74 | static void pmf_gpio_init(struct gpio_runtime *rt) | ||
75 | { | ||
76 | pmf_gpio_all_amps_off(rt); | ||
77 | rt->implementation_private = 0; | ||
78 | INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify, | ||
79 | &rt->headphone_notify); | ||
80 | INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify, | ||
81 | &rt->line_in_notify); | ||
82 | INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify, | ||
83 | &rt->line_out_notify); | ||
84 | mutex_init(&rt->headphone_notify.mutex); | ||
85 | mutex_init(&rt->line_in_notify.mutex); | ||
86 | mutex_init(&rt->line_out_notify.mutex); | ||
87 | } | ||
88 | |||
89 | static void pmf_gpio_exit(struct gpio_runtime *rt) | ||
90 | { | ||
91 | pmf_gpio_all_amps_off(rt); | ||
92 | rt->implementation_private = 0; | ||
93 | |||
94 | if (rt->headphone_notify.gpio_private) | ||
95 | pmf_unregister_irq_client(rt->headphone_notify.gpio_private); | ||
96 | if (rt->line_in_notify.gpio_private) | ||
97 | pmf_unregister_irq_client(rt->line_in_notify.gpio_private); | ||
98 | if (rt->line_out_notify.gpio_private) | ||
99 | pmf_unregister_irq_client(rt->line_out_notify.gpio_private); | ||
100 | |||
101 | /* make sure no work is pending before freeing | ||
102 | * all things */ | ||
103 | cancel_delayed_work(&rt->headphone_notify.work); | ||
104 | cancel_delayed_work(&rt->line_in_notify.work); | ||
105 | cancel_delayed_work(&rt->line_out_notify.work); | ||
106 | flush_scheduled_work(); | ||
107 | |||
108 | mutex_destroy(&rt->headphone_notify.mutex); | ||
109 | mutex_destroy(&rt->line_in_notify.mutex); | ||
110 | mutex_destroy(&rt->line_out_notify.mutex); | ||
111 | |||
112 | if (rt->headphone_notify.gpio_private) | ||
113 | kfree(rt->headphone_notify.gpio_private); | ||
114 | if (rt->line_in_notify.gpio_private) | ||
115 | kfree(rt->line_in_notify.gpio_private); | ||
116 | if (rt->line_out_notify.gpio_private) | ||
117 | kfree(rt->line_out_notify.gpio_private); | ||
118 | } | ||
119 | |||
120 | static void pmf_handle_notify_irq(void *data) | ||
121 | { | ||
122 | struct gpio_notification *notif = data; | ||
123 | |||
124 | schedule_work(¬if->work); | ||
125 | } | ||
126 | |||
127 | static int pmf_set_notify(struct gpio_runtime *rt, | ||
128 | enum notify_type type, | ||
129 | notify_func_t notify, | ||
130 | void *data) | ||
131 | { | ||
132 | struct gpio_notification *notif; | ||
133 | notify_func_t old; | ||
134 | struct pmf_irq_client *irq_client; | ||
135 | char *name; | ||
136 | int err = -EBUSY; | ||
137 | |||
138 | switch (type) { | ||
139 | case AOA_NOTIFY_HEADPHONE: | ||
140 | notif = &rt->headphone_notify; | ||
141 | name = "headphone-detect"; | ||
142 | break; | ||
143 | case AOA_NOTIFY_LINE_IN: | ||
144 | notif = &rt->line_in_notify; | ||
145 | name = "linein-detect"; | ||
146 | break; | ||
147 | case AOA_NOTIFY_LINE_OUT: | ||
148 | notif = &rt->line_out_notify; | ||
149 | name = "lineout-detect"; | ||
150 | break; | ||
151 | default: | ||
152 | return -EINVAL; | ||
153 | } | ||
154 | |||
155 | mutex_lock(¬if->mutex); | ||
156 | |||
157 | old = notif->notify; | ||
158 | |||
159 | if (!old && !notify) { | ||
160 | err = 0; | ||
161 | goto out_unlock; | ||
162 | } | ||
163 | |||
164 | if (old && notify) { | ||
165 | if (old == notify && notif->data == data) | ||
166 | err = 0; | ||
167 | goto out_unlock; | ||
168 | } | ||
169 | |||
170 | if (old && !notify) { | ||
171 | irq_client = notif->gpio_private; | ||
172 | pmf_unregister_irq_client(irq_client); | ||
173 | kfree(irq_client); | ||
174 | notif->gpio_private = NULL; | ||
175 | } | ||
176 | if (!old && notify) { | ||
177 | irq_client = kzalloc(sizeof(struct pmf_irq_client), | ||
178 | GFP_KERNEL); | ||
179 | irq_client->data = notif; | ||
180 | irq_client->handler = pmf_handle_notify_irq; | ||
181 | irq_client->owner = THIS_MODULE; | ||
182 | err = pmf_register_irq_client(rt->node, | ||
183 | name, | ||
184 | irq_client); | ||
185 | if (err) { | ||
186 | printk(KERN_ERR "snd-aoa: gpio layer failed to" | ||
187 | " register %s irq (%d)\n", name, err); | ||
188 | kfree(irq_client); | ||
189 | goto out_unlock; | ||
190 | } | ||
191 | notif->gpio_private = irq_client; | ||
192 | } | ||
193 | notif->notify = notify; | ||
194 | notif->data = data; | ||
195 | |||
196 | err = 0; | ||
197 | out_unlock: | ||
198 | mutex_unlock(¬if->mutex); | ||
199 | return err; | ||
200 | } | ||
201 | |||
202 | static int pmf_get_detect(struct gpio_runtime *rt, | ||
203 | enum notify_type type) | ||
204 | { | ||
205 | char *name; | ||
206 | int err = -EBUSY, ret; | ||
207 | struct pmf_args args = { .count = 1, .u[0].p = &ret }; | ||
208 | |||
209 | switch (type) { | ||
210 | case AOA_NOTIFY_HEADPHONE: | ||
211 | name = "headphone-detect"; | ||
212 | break; | ||
213 | case AOA_NOTIFY_LINE_IN: | ||
214 | name = "linein-detect"; | ||
215 | break; | ||
216 | case AOA_NOTIFY_LINE_OUT: | ||
217 | name = "lineout-detect"; | ||
218 | break; | ||
219 | default: | ||
220 | return -EINVAL; | ||
221 | } | ||
222 | |||
223 | err = pmf_call_function(rt->node, name, &args); | ||
224 | if (err) | ||
225 | return err; | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static struct gpio_methods methods = { | ||
230 | .init = pmf_gpio_init, | ||
231 | .exit = pmf_gpio_exit, | ||
232 | .all_amps_off = pmf_gpio_all_amps_off, | ||
233 | .all_amps_restore = pmf_gpio_all_amps_restore, | ||
234 | .set_headphone = pmf_gpio_set_headphone, | ||
235 | .set_speakers = pmf_gpio_set_amp, | ||
236 | .set_lineout = pmf_gpio_set_lineout, | ||
237 | .set_hw_reset = pmf_gpio_set_hw_reset, | ||
238 | .get_headphone = pmf_gpio_get_headphone, | ||
239 | .get_speakers = pmf_gpio_get_amp, | ||
240 | .get_lineout = pmf_gpio_get_lineout, | ||
241 | .set_notify = pmf_set_notify, | ||
242 | .get_detect = pmf_get_detect, | ||
243 | }; | ||
244 | |||
245 | struct gpio_methods *pmf_gpio_methods = &methods; | ||
246 | EXPORT_SYMBOL_GPL(pmf_gpio_methods); | ||
diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig new file mode 100644 index 000000000000..c3bc7705c86a --- /dev/null +++ b/sound/aoa/fabrics/Kconfig | |||
@@ -0,0 +1,12 @@ | |||
1 | config SND_AOA_FABRIC_LAYOUT | ||
2 | tristate "layout-id fabric" | ||
3 | depends SND_AOA | ||
4 | select SND_AOA_SOUNDBUS | ||
5 | select SND_AOA_SOUNDBUS_I2S | ||
6 | ---help--- | ||
7 | This enables the layout-id fabric for the Apple Onboard | ||
8 | Audio driver, the module holding it all together | ||
9 | based on the device-tree's layout-id property. | ||
10 | |||
11 | If you are unsure and have a later Apple machine, | ||
12 | compile it as a module. | ||
diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile new file mode 100644 index 000000000000..55fc5e7e52cf --- /dev/null +++ b/sound/aoa/fabrics/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o | |||
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c new file mode 100644 index 000000000000..04a7238e9494 --- /dev/null +++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c | |||
@@ -0,0 +1,1109 @@ | |||
1 | /* | ||
2 | * Apple Onboard Audio driver -- layout fabric | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | * | ||
8 | * | ||
9 | * This fabric module looks for sound codecs | ||
10 | * based on the layout-id property in the device tree. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <asm/prom.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/module.h> | ||
17 | #include "../aoa.h" | ||
18 | #include "../soundbus/soundbus.h" | ||
19 | |||
20 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
21 | MODULE_LICENSE("GPL"); | ||
22 | MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa"); | ||
23 | |||
24 | #define MAX_CODECS_PER_BUS 2 | ||
25 | |||
26 | /* These are the connections the layout fabric | ||
27 | * knows about. It doesn't really care about the | ||
28 | * input ones, but I thought I'd separate them | ||
29 | * to give them proper names. The thing is that | ||
30 | * Apple usually will distinguish the active output | ||
31 | * by GPIOs, while the active input is set directly | ||
32 | * on the codec. Hence we here tell the codec what | ||
33 | * we think is connected. This information is hard- | ||
34 | * coded below ... */ | ||
35 | #define CC_SPEAKERS (1<<0) | ||
36 | #define CC_HEADPHONE (1<<1) | ||
37 | #define CC_LINEOUT (1<<2) | ||
38 | #define CC_DIGITALOUT (1<<3) | ||
39 | #define CC_LINEIN (1<<4) | ||
40 | #define CC_MICROPHONE (1<<5) | ||
41 | #define CC_DIGITALIN (1<<6) | ||
42 | /* pretty bogus but users complain... | ||
43 | * This is a flag saying that the LINEOUT | ||
44 | * should be renamed to HEADPHONE. | ||
45 | * be careful with input detection! */ | ||
46 | #define CC_LINEOUT_LABELLED_HEADPHONE (1<<7) | ||
47 | |||
48 | struct codec_connection { | ||
49 | /* CC_ flags from above */ | ||
50 | int connected; | ||
51 | /* codec dependent bit to be set in the aoa_codec.connected field. | ||
52 | * This intentionally doesn't have any generic flags because the | ||
53 | * fabric has to know the codec anyway and all codecs might have | ||
54 | * different connectors */ | ||
55 | int codec_bit; | ||
56 | }; | ||
57 | |||
58 | struct codec_connect_info { | ||
59 | char *name; | ||
60 | struct codec_connection *connections; | ||
61 | }; | ||
62 | |||
63 | #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) | ||
64 | |||
65 | struct layout { | ||
66 | unsigned int layout_id; | ||
67 | struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; | ||
68 | int flags; | ||
69 | |||
70 | /* if busname is not assigned, we use 'Master' below, | ||
71 | * so that our layout table doesn't need to be filled | ||
72 | * too much. | ||
73 | * We only assign these two if we expect to find more | ||
74 | * than one soundbus, i.e. on those machines with | ||
75 | * multiple layout-ids */ | ||
76 | char *busname; | ||
77 | int pcmid; | ||
78 | }; | ||
79 | |||
80 | MODULE_ALIAS("sound-layout-41"); | ||
81 | MODULE_ALIAS("sound-layout-45"); | ||
82 | MODULE_ALIAS("sound-layout-51"); | ||
83 | MODULE_ALIAS("sound-layout-58"); | ||
84 | MODULE_ALIAS("sound-layout-60"); | ||
85 | MODULE_ALIAS("sound-layout-61"); | ||
86 | MODULE_ALIAS("sound-layout-64"); | ||
87 | MODULE_ALIAS("sound-layout-65"); | ||
88 | MODULE_ALIAS("sound-layout-68"); | ||
89 | MODULE_ALIAS("sound-layout-69"); | ||
90 | MODULE_ALIAS("sound-layout-70"); | ||
91 | MODULE_ALIAS("sound-layout-72"); | ||
92 | MODULE_ALIAS("sound-layout-80"); | ||
93 | MODULE_ALIAS("sound-layout-82"); | ||
94 | MODULE_ALIAS("sound-layout-84"); | ||
95 | MODULE_ALIAS("sound-layout-86"); | ||
96 | MODULE_ALIAS("sound-layout-92"); | ||
97 | |||
98 | /* onyx with all but microphone connected */ | ||
99 | static struct codec_connection onyx_connections_nomic[] = { | ||
100 | { | ||
101 | .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, | ||
102 | .codec_bit = 0, | ||
103 | }, | ||
104 | { | ||
105 | .connected = CC_DIGITALOUT, | ||
106 | .codec_bit = 1, | ||
107 | }, | ||
108 | { | ||
109 | .connected = CC_LINEIN, | ||
110 | .codec_bit = 2, | ||
111 | }, | ||
112 | {} /* terminate array by .connected == 0 */ | ||
113 | }; | ||
114 | |||
115 | /* onyx on machines without headphone */ | ||
116 | static struct codec_connection onyx_connections_noheadphones[] = { | ||
117 | { | ||
118 | .connected = CC_SPEAKERS | CC_LINEOUT | | ||
119 | CC_LINEOUT_LABELLED_HEADPHONE, | ||
120 | .codec_bit = 0, | ||
121 | }, | ||
122 | { | ||
123 | .connected = CC_DIGITALOUT, | ||
124 | .codec_bit = 1, | ||
125 | }, | ||
126 | /* FIXME: are these correct? probably not for all the machines | ||
127 | * below ... If not this will need separating. */ | ||
128 | { | ||
129 | .connected = CC_LINEIN, | ||
130 | .codec_bit = 2, | ||
131 | }, | ||
132 | { | ||
133 | .connected = CC_MICROPHONE, | ||
134 | .codec_bit = 3, | ||
135 | }, | ||
136 | {} /* terminate array by .connected == 0 */ | ||
137 | }; | ||
138 | |||
139 | /* onyx on machines with real line-out */ | ||
140 | static struct codec_connection onyx_connections_reallineout[] = { | ||
141 | { | ||
142 | .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE, | ||
143 | .codec_bit = 0, | ||
144 | }, | ||
145 | { | ||
146 | .connected = CC_DIGITALOUT, | ||
147 | .codec_bit = 1, | ||
148 | }, | ||
149 | { | ||
150 | .connected = CC_LINEIN, | ||
151 | .codec_bit = 2, | ||
152 | }, | ||
153 | {} /* terminate array by .connected == 0 */ | ||
154 | }; | ||
155 | |||
156 | /* tas on machines without line out */ | ||
157 | static struct codec_connection tas_connections_nolineout[] = { | ||
158 | { | ||
159 | .connected = CC_SPEAKERS | CC_HEADPHONE, | ||
160 | .codec_bit = 0, | ||
161 | }, | ||
162 | { | ||
163 | .connected = CC_LINEIN, | ||
164 | .codec_bit = 2, | ||
165 | }, | ||
166 | { | ||
167 | .connected = CC_MICROPHONE, | ||
168 | .codec_bit = 3, | ||
169 | }, | ||
170 | {} /* terminate array by .connected == 0 */ | ||
171 | }; | ||
172 | |||
173 | /* tas on machines with neither line out nor line in */ | ||
174 | static struct codec_connection tas_connections_noline[] = { | ||
175 | { | ||
176 | .connected = CC_SPEAKERS | CC_HEADPHONE, | ||
177 | .codec_bit = 0, | ||
178 | }, | ||
179 | { | ||
180 | .connected = CC_MICROPHONE, | ||
181 | .codec_bit = 3, | ||
182 | }, | ||
183 | {} /* terminate array by .connected == 0 */ | ||
184 | }; | ||
185 | |||
186 | /* tas on machines without microphone */ | ||
187 | static struct codec_connection tas_connections_nomic[] = { | ||
188 | { | ||
189 | .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, | ||
190 | .codec_bit = 0, | ||
191 | }, | ||
192 | { | ||
193 | .connected = CC_LINEIN, | ||
194 | .codec_bit = 2, | ||
195 | }, | ||
196 | {} /* terminate array by .connected == 0 */ | ||
197 | }; | ||
198 | |||
199 | /* tas on machines with everything connected */ | ||
200 | static struct codec_connection tas_connections_all[] = { | ||
201 | { | ||
202 | .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, | ||
203 | .codec_bit = 0, | ||
204 | }, | ||
205 | { | ||
206 | .connected = CC_LINEIN, | ||
207 | .codec_bit = 2, | ||
208 | }, | ||
209 | { | ||
210 | .connected = CC_MICROPHONE, | ||
211 | .codec_bit = 3, | ||
212 | }, | ||
213 | {} /* terminate array by .connected == 0 */ | ||
214 | }; | ||
215 | |||
216 | static struct codec_connection toonie_connections[] = { | ||
217 | { | ||
218 | .connected = CC_SPEAKERS | CC_HEADPHONE, | ||
219 | .codec_bit = 0, | ||
220 | }, | ||
221 | {} /* terminate array by .connected == 0 */ | ||
222 | }; | ||
223 | |||
224 | static struct codec_connection topaz_input[] = { | ||
225 | { | ||
226 | .connected = CC_DIGITALIN, | ||
227 | .codec_bit = 0, | ||
228 | }, | ||
229 | {} /* terminate array by .connected == 0 */ | ||
230 | }; | ||
231 | |||
232 | static struct codec_connection topaz_output[] = { | ||
233 | { | ||
234 | .connected = CC_DIGITALOUT, | ||
235 | .codec_bit = 1, | ||
236 | }, | ||
237 | {} /* terminate array by .connected == 0 */ | ||
238 | }; | ||
239 | |||
240 | static struct codec_connection topaz_inout[] = { | ||
241 | { | ||
242 | .connected = CC_DIGITALIN, | ||
243 | .codec_bit = 0, | ||
244 | }, | ||
245 | { | ||
246 | .connected = CC_DIGITALOUT, | ||
247 | .codec_bit = 1, | ||
248 | }, | ||
249 | {} /* terminate array by .connected == 0 */ | ||
250 | }; | ||
251 | |||
252 | static struct layout layouts[] = { | ||
253 | /* last PowerBooks (15" Oct 2005) */ | ||
254 | { .layout_id = 82, | ||
255 | .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, | ||
256 | .codecs[0] = { | ||
257 | .name = "onyx", | ||
258 | .connections = onyx_connections_noheadphones, | ||
259 | }, | ||
260 | .codecs[1] = { | ||
261 | .name = "topaz", | ||
262 | .connections = topaz_input, | ||
263 | }, | ||
264 | }, | ||
265 | /* PowerMac9,1 */ | ||
266 | { .layout_id = 60, | ||
267 | .codecs[0] = { | ||
268 | .name = "onyx", | ||
269 | .connections = onyx_connections_reallineout, | ||
270 | }, | ||
271 | }, | ||
272 | /* PowerMac9,1 */ | ||
273 | { .layout_id = 61, | ||
274 | .codecs[0] = { | ||
275 | .name = "topaz", | ||
276 | .connections = topaz_input, | ||
277 | }, | ||
278 | }, | ||
279 | /* PowerBook5,7 */ | ||
280 | { .layout_id = 64, | ||
281 | .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, | ||
282 | .codecs[0] = { | ||
283 | .name = "onyx", | ||
284 | .connections = onyx_connections_noheadphones, | ||
285 | }, | ||
286 | }, | ||
287 | /* PowerBook5,7 */ | ||
288 | { .layout_id = 65, | ||
289 | .codecs[0] = { | ||
290 | .name = "topaz", | ||
291 | .connections = topaz_input, | ||
292 | }, | ||
293 | }, | ||
294 | /* PowerBook5,9 [17" Oct 2005] */ | ||
295 | { .layout_id = 84, | ||
296 | .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, | ||
297 | .codecs[0] = { | ||
298 | .name = "onyx", | ||
299 | .connections = onyx_connections_noheadphones, | ||
300 | }, | ||
301 | .codecs[1] = { | ||
302 | .name = "topaz", | ||
303 | .connections = topaz_input, | ||
304 | }, | ||
305 | }, | ||
306 | /* PowerMac8,1 */ | ||
307 | { .layout_id = 45, | ||
308 | .codecs[0] = { | ||
309 | .name = "onyx", | ||
310 | .connections = onyx_connections_noheadphones, | ||
311 | }, | ||
312 | .codecs[1] = { | ||
313 | .name = "topaz", | ||
314 | .connections = topaz_input, | ||
315 | }, | ||
316 | }, | ||
317 | /* Quad PowerMac (analog in, analog/digital out) */ | ||
318 | { .layout_id = 68, | ||
319 | .codecs[0] = { | ||
320 | .name = "onyx", | ||
321 | .connections = onyx_connections_nomic, | ||
322 | }, | ||
323 | }, | ||
324 | /* Quad PowerMac (digital in) */ | ||
325 | { .layout_id = 69, | ||
326 | .codecs[0] = { | ||
327 | .name = "topaz", | ||
328 | .connections = topaz_input, | ||
329 | }, | ||
330 | .busname = "digital in", .pcmid = 1 }, | ||
331 | /* Early 2005 PowerBook (PowerBook 5,6) */ | ||
332 | { .layout_id = 70, | ||
333 | .codecs[0] = { | ||
334 | .name = "tas", | ||
335 | .connections = tas_connections_nolineout, | ||
336 | }, | ||
337 | }, | ||
338 | /* PowerBook 5,4 */ | ||
339 | { .layout_id = 51, | ||
340 | .codecs[0] = { | ||
341 | .name = "tas", | ||
342 | .connections = tas_connections_nolineout, | ||
343 | }, | ||
344 | }, | ||
345 | /* PowerBook6,7 */ | ||
346 | { .layout_id = 80, | ||
347 | .codecs[0] = { | ||
348 | .name = "tas", | ||
349 | .connections = tas_connections_noline, | ||
350 | }, | ||
351 | }, | ||
352 | /* PowerBook6,8 */ | ||
353 | { .layout_id = 72, | ||
354 | .codecs[0] = { | ||
355 | .name = "tas", | ||
356 | .connections = tas_connections_nolineout, | ||
357 | }, | ||
358 | }, | ||
359 | /* PowerMac8,2 */ | ||
360 | { .layout_id = 86, | ||
361 | .codecs[0] = { | ||
362 | .name = "onyx", | ||
363 | .connections = onyx_connections_nomic, | ||
364 | }, | ||
365 | .codecs[1] = { | ||
366 | .name = "topaz", | ||
367 | .connections = topaz_input, | ||
368 | }, | ||
369 | }, | ||
370 | /* PowerBook6,7 */ | ||
371 | { .layout_id = 92, | ||
372 | .codecs[0] = { | ||
373 | .name = "tas", | ||
374 | .connections = tas_connections_nolineout, | ||
375 | }, | ||
376 | }, | ||
377 | /* PowerMac10,1 (Mac Mini) */ | ||
378 | { .layout_id = 58, | ||
379 | .codecs[0] = { | ||
380 | .name = "toonie", | ||
381 | .connections = toonie_connections, | ||
382 | }, | ||
383 | }, | ||
384 | /* unknown, untested, but this comes from Apple */ | ||
385 | { .layout_id = 41, | ||
386 | .codecs[0] = { | ||
387 | .name = "tas", | ||
388 | .connections = tas_connections_all, | ||
389 | }, | ||
390 | }, | ||
391 | { .layout_id = 36, | ||
392 | .codecs[0] = { | ||
393 | .name = "tas", | ||
394 | .connections = tas_connections_nomic, | ||
395 | }, | ||
396 | .codecs[1] = { | ||
397 | .name = "topaz", | ||
398 | .connections = topaz_inout, | ||
399 | }, | ||
400 | }, | ||
401 | { .layout_id = 47, | ||
402 | .codecs[0] = { | ||
403 | .name = "onyx", | ||
404 | .connections = onyx_connections_noheadphones, | ||
405 | }, | ||
406 | }, | ||
407 | { .layout_id = 48, | ||
408 | .codecs[0] = { | ||
409 | .name = "topaz", | ||
410 | .connections = topaz_input, | ||
411 | }, | ||
412 | }, | ||
413 | { .layout_id = 49, | ||
414 | .codecs[0] = { | ||
415 | .name = "onyx", | ||
416 | .connections = onyx_connections_nomic, | ||
417 | }, | ||
418 | }, | ||
419 | { .layout_id = 50, | ||
420 | .codecs[0] = { | ||
421 | .name = "topaz", | ||
422 | .connections = topaz_input, | ||
423 | }, | ||
424 | }, | ||
425 | { .layout_id = 56, | ||
426 | .codecs[0] = { | ||
427 | .name = "onyx", | ||
428 | .connections = onyx_connections_noheadphones, | ||
429 | }, | ||
430 | }, | ||
431 | { .layout_id = 57, | ||
432 | .codecs[0] = { | ||
433 | .name = "topaz", | ||
434 | .connections = topaz_input, | ||
435 | }, | ||
436 | }, | ||
437 | { .layout_id = 62, | ||
438 | .codecs[0] = { | ||
439 | .name = "onyx", | ||
440 | .connections = onyx_connections_noheadphones, | ||
441 | }, | ||
442 | .codecs[1] = { | ||
443 | .name = "topaz", | ||
444 | .connections = topaz_output, | ||
445 | }, | ||
446 | }, | ||
447 | { .layout_id = 66, | ||
448 | .codecs[0] = { | ||
449 | .name = "onyx", | ||
450 | .connections = onyx_connections_noheadphones, | ||
451 | }, | ||
452 | }, | ||
453 | { .layout_id = 67, | ||
454 | .codecs[0] = { | ||
455 | .name = "topaz", | ||
456 | .connections = topaz_input, | ||
457 | }, | ||
458 | }, | ||
459 | { .layout_id = 76, | ||
460 | .codecs[0] = { | ||
461 | .name = "tas", | ||
462 | .connections = tas_connections_nomic, | ||
463 | }, | ||
464 | .codecs[1] = { | ||
465 | .name = "topaz", | ||
466 | .connections = topaz_inout, | ||
467 | }, | ||
468 | }, | ||
469 | { .layout_id = 90, | ||
470 | .codecs[0] = { | ||
471 | .name = "tas", | ||
472 | .connections = tas_connections_noline, | ||
473 | }, | ||
474 | }, | ||
475 | { .layout_id = 94, | ||
476 | .codecs[0] = { | ||
477 | .name = "onyx", | ||
478 | /* but it has an external mic?? how to select? */ | ||
479 | .connections = onyx_connections_noheadphones, | ||
480 | }, | ||
481 | }, | ||
482 | { .layout_id = 96, | ||
483 | .codecs[0] = { | ||
484 | .name = "onyx", | ||
485 | .connections = onyx_connections_noheadphones, | ||
486 | }, | ||
487 | }, | ||
488 | { .layout_id = 98, | ||
489 | .codecs[0] = { | ||
490 | .name = "toonie", | ||
491 | .connections = toonie_connections, | ||
492 | }, | ||
493 | }, | ||
494 | { .layout_id = 100, | ||
495 | .codecs[0] = { | ||
496 | .name = "topaz", | ||
497 | .connections = topaz_input, | ||
498 | }, | ||
499 | .codecs[1] = { | ||
500 | .name = "onyx", | ||
501 | .connections = onyx_connections_noheadphones, | ||
502 | }, | ||
503 | }, | ||
504 | {} | ||
505 | }; | ||
506 | |||
507 | static struct layout *find_layout_by_id(unsigned int id) | ||
508 | { | ||
509 | struct layout *l; | ||
510 | |||
511 | l = layouts; | ||
512 | while (l->layout_id) { | ||
513 | if (l->layout_id == id) | ||
514 | return l; | ||
515 | l++; | ||
516 | } | ||
517 | return NULL; | ||
518 | } | ||
519 | |||
520 | static void use_layout(struct layout *l) | ||
521 | { | ||
522 | int i; | ||
523 | |||
524 | for (i=0; i<MAX_CODECS_PER_BUS; i++) { | ||
525 | if (l->codecs[i].name) { | ||
526 | request_module("snd-aoa-codec-%s", l->codecs[i].name); | ||
527 | } | ||
528 | } | ||
529 | /* now we wait for the codecs to call us back */ | ||
530 | } | ||
531 | |||
532 | struct layout_dev; | ||
533 | |||
534 | struct layout_dev_ptr { | ||
535 | struct layout_dev *ptr; | ||
536 | }; | ||
537 | |||
538 | struct layout_dev { | ||
539 | struct list_head list; | ||
540 | struct soundbus_dev *sdev; | ||
541 | struct device_node *sound; | ||
542 | struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; | ||
543 | struct layout *layout; | ||
544 | struct gpio_runtime gpio; | ||
545 | |||
546 | /* we need these for headphone/lineout detection */ | ||
547 | struct snd_kcontrol *headphone_ctrl; | ||
548 | struct snd_kcontrol *lineout_ctrl; | ||
549 | struct snd_kcontrol *speaker_ctrl; | ||
550 | struct snd_kcontrol *headphone_detected_ctrl; | ||
551 | struct snd_kcontrol *lineout_detected_ctrl; | ||
552 | |||
553 | struct layout_dev_ptr selfptr_headphone; | ||
554 | struct layout_dev_ptr selfptr_lineout; | ||
555 | |||
556 | u32 have_lineout_detect:1, | ||
557 | have_headphone_detect:1, | ||
558 | switch_on_headphone:1, | ||
559 | switch_on_lineout:1; | ||
560 | }; | ||
561 | |||
562 | static LIST_HEAD(layouts_list); | ||
563 | static int layouts_list_items; | ||
564 | /* this can go away but only if we allow multiple cards, | ||
565 | * make the fabric handle all the card stuff, etc... */ | ||
566 | static struct layout_dev *layout_device; | ||
567 | |||
568 | static int control_info(struct snd_kcontrol *kcontrol, | ||
569 | struct snd_ctl_elem_info *uinfo) | ||
570 | { | ||
571 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
572 | uinfo->count = 1; | ||
573 | uinfo->value.integer.min = 0; | ||
574 | uinfo->value.integer.max = 1; | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | #define AMP_CONTROL(n, description) \ | ||
579 | static int n##_control_get(struct snd_kcontrol *kcontrol, \ | ||
580 | struct snd_ctl_elem_value *ucontrol) \ | ||
581 | { \ | ||
582 | struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ | ||
583 | if (gpio->methods && gpio->methods->get_##n) \ | ||
584 | ucontrol->value.integer.value[0] = \ | ||
585 | gpio->methods->get_##n(gpio); \ | ||
586 | return 0; \ | ||
587 | } \ | ||
588 | static int n##_control_put(struct snd_kcontrol *kcontrol, \ | ||
589 | struct snd_ctl_elem_value *ucontrol) \ | ||
590 | { \ | ||
591 | struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ | ||
592 | if (gpio->methods && gpio->methods->get_##n) \ | ||
593 | gpio->methods->set_##n(gpio, \ | ||
594 | ucontrol->value.integer.value[0]); \ | ||
595 | return 1; \ | ||
596 | } \ | ||
597 | static struct snd_kcontrol_new n##_ctl = { \ | ||
598 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
599 | .name = description, \ | ||
600 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | ||
601 | .info = control_info, \ | ||
602 | .get = n##_control_get, \ | ||
603 | .put = n##_control_put, \ | ||
604 | } | ||
605 | |||
606 | AMP_CONTROL(headphone, "Headphone Switch"); | ||
607 | AMP_CONTROL(speakers, "Speakers Switch"); | ||
608 | AMP_CONTROL(lineout, "Line-Out Switch"); | ||
609 | |||
610 | static int detect_choice_get(struct snd_kcontrol *kcontrol, | ||
611 | struct snd_ctl_elem_value *ucontrol) | ||
612 | { | ||
613 | struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); | ||
614 | |||
615 | switch (kcontrol->private_value) { | ||
616 | case 0: | ||
617 | ucontrol->value.integer.value[0] = ldev->switch_on_headphone; | ||
618 | break; | ||
619 | case 1: | ||
620 | ucontrol->value.integer.value[0] = ldev->switch_on_lineout; | ||
621 | break; | ||
622 | default: | ||
623 | return -ENODEV; | ||
624 | } | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static int detect_choice_put(struct snd_kcontrol *kcontrol, | ||
629 | struct snd_ctl_elem_value *ucontrol) | ||
630 | { | ||
631 | struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); | ||
632 | |||
633 | switch (kcontrol->private_value) { | ||
634 | case 0: | ||
635 | ldev->switch_on_headphone = !!ucontrol->value.integer.value[0]; | ||
636 | break; | ||
637 | case 1: | ||
638 | ldev->switch_on_lineout = !!ucontrol->value.integer.value[0]; | ||
639 | break; | ||
640 | default: | ||
641 | return -ENODEV; | ||
642 | } | ||
643 | return 1; | ||
644 | } | ||
645 | |||
646 | static struct snd_kcontrol_new headphone_detect_choice = { | ||
647 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
648 | .name = "Headphone Detect Autoswitch", | ||
649 | .info = control_info, | ||
650 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
651 | .get = detect_choice_get, | ||
652 | .put = detect_choice_put, | ||
653 | .private_value = 0, | ||
654 | }; | ||
655 | |||
656 | static struct snd_kcontrol_new lineout_detect_choice = { | ||
657 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
658 | .name = "Line-Out Detect Autoswitch", | ||
659 | .info = control_info, | ||
660 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
661 | .get = detect_choice_get, | ||
662 | .put = detect_choice_put, | ||
663 | .private_value = 1, | ||
664 | }; | ||
665 | |||
666 | static int detected_get(struct snd_kcontrol *kcontrol, | ||
667 | struct snd_ctl_elem_value *ucontrol) | ||
668 | { | ||
669 | struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); | ||
670 | int v; | ||
671 | |||
672 | switch (kcontrol->private_value) { | ||
673 | case 0: | ||
674 | v = ldev->gpio.methods->get_detect(&ldev->gpio, | ||
675 | AOA_NOTIFY_HEADPHONE); | ||
676 | break; | ||
677 | case 1: | ||
678 | v = ldev->gpio.methods->get_detect(&ldev->gpio, | ||
679 | AOA_NOTIFY_LINE_OUT); | ||
680 | break; | ||
681 | default: | ||
682 | return -ENODEV; | ||
683 | } | ||
684 | ucontrol->value.integer.value[0] = v; | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static struct snd_kcontrol_new headphone_detected = { | ||
689 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
690 | .name = "Headphone Detected", | ||
691 | .info = control_info, | ||
692 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
693 | .get = detected_get, | ||
694 | .private_value = 0, | ||
695 | }; | ||
696 | |||
697 | static struct snd_kcontrol_new lineout_detected = { | ||
698 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
699 | .name = "Line-Out Detected", | ||
700 | .info = control_info, | ||
701 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | ||
702 | .get = detected_get, | ||
703 | .private_value = 1, | ||
704 | }; | ||
705 | |||
706 | static int check_codec(struct aoa_codec *codec, | ||
707 | struct layout_dev *ldev, | ||
708 | struct codec_connect_info *cci) | ||
709 | { | ||
710 | u32 *ref; | ||
711 | char propname[32]; | ||
712 | struct codec_connection *cc; | ||
713 | |||
714 | /* if the codec has a 'codec' node, we require a reference */ | ||
715 | if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { | ||
716 | snprintf(propname, sizeof(propname), | ||
717 | "platform-%s-codec-ref", codec->name); | ||
718 | ref = (u32*)get_property(ldev->sound, propname, NULL); | ||
719 | if (!ref) { | ||
720 | printk(KERN_INFO "snd-aoa-fabric-layout: " | ||
721 | "required property %s not present\n", propname); | ||
722 | return -ENODEV; | ||
723 | } | ||
724 | if (*ref != codec->node->linux_phandle) { | ||
725 | printk(KERN_INFO "snd-aoa-fabric-layout: " | ||
726 | "%s doesn't match!\n", propname); | ||
727 | return -ENODEV; | ||
728 | } | ||
729 | } else { | ||
730 | if (layouts_list_items != 1) { | ||
731 | printk(KERN_INFO "snd-aoa-fabric-layout: " | ||
732 | "more than one soundbus, but no references.\n"); | ||
733 | return -ENODEV; | ||
734 | } | ||
735 | } | ||
736 | codec->soundbus_dev = ldev->sdev; | ||
737 | codec->gpio = &ldev->gpio; | ||
738 | |||
739 | cc = cci->connections; | ||
740 | if (!cc) | ||
741 | return -EINVAL; | ||
742 | |||
743 | printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n"); | ||
744 | |||
745 | codec->connected = 0; | ||
746 | codec->fabric_data = cc; | ||
747 | |||
748 | while (cc->connected) { | ||
749 | codec->connected |= 1<<cc->codec_bit; | ||
750 | cc++; | ||
751 | } | ||
752 | |||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | static int layout_found_codec(struct aoa_codec *codec) | ||
757 | { | ||
758 | struct layout_dev *ldev; | ||
759 | int i; | ||
760 | |||
761 | list_for_each_entry(ldev, &layouts_list, list) { | ||
762 | for (i=0; i<MAX_CODECS_PER_BUS; i++) { | ||
763 | if (!ldev->layout->codecs[i].name) | ||
764 | continue; | ||
765 | if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) { | ||
766 | if (check_codec(codec, | ||
767 | ldev, | ||
768 | &ldev->layout->codecs[i]) == 0) | ||
769 | return 0; | ||
770 | } | ||
771 | } | ||
772 | } | ||
773 | return -ENODEV; | ||
774 | } | ||
775 | |||
776 | static void layout_remove_codec(struct aoa_codec *codec) | ||
777 | { | ||
778 | int i; | ||
779 | /* here remove the codec from the layout dev's | ||
780 | * codec reference */ | ||
781 | |||
782 | codec->soundbus_dev = NULL; | ||
783 | codec->gpio = NULL; | ||
784 | for (i=0; i<MAX_CODECS_PER_BUS; i++) { | ||
785 | } | ||
786 | } | ||
787 | |||
788 | static void layout_notify(void *data) | ||
789 | { | ||
790 | struct layout_dev_ptr *dptr = data; | ||
791 | struct layout_dev *ldev; | ||
792 | int v, update; | ||
793 | struct snd_kcontrol *detected, *c; | ||
794 | struct snd_card *card = aoa_get_card(); | ||
795 | |||
796 | ldev = dptr->ptr; | ||
797 | if (data == &ldev->selfptr_headphone) { | ||
798 | v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE); | ||
799 | detected = ldev->headphone_detected_ctrl; | ||
800 | update = ldev->switch_on_headphone; | ||
801 | if (update) { | ||
802 | ldev->gpio.methods->set_speakers(&ldev->gpio, !v); | ||
803 | ldev->gpio.methods->set_headphone(&ldev->gpio, v); | ||
804 | ldev->gpio.methods->set_lineout(&ldev->gpio, 0); | ||
805 | } | ||
806 | } else if (data == &ldev->selfptr_lineout) { | ||
807 | v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT); | ||
808 | detected = ldev->lineout_detected_ctrl; | ||
809 | update = ldev->switch_on_lineout; | ||
810 | if (update) { | ||
811 | ldev->gpio.methods->set_speakers(&ldev->gpio, !v); | ||
812 | ldev->gpio.methods->set_headphone(&ldev->gpio, 0); | ||
813 | ldev->gpio.methods->set_lineout(&ldev->gpio, v); | ||
814 | } | ||
815 | } else | ||
816 | return; | ||
817 | |||
818 | if (detected) | ||
819 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id); | ||
820 | if (update) { | ||
821 | c = ldev->headphone_ctrl; | ||
822 | if (c) | ||
823 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); | ||
824 | c = ldev->speaker_ctrl; | ||
825 | if (c) | ||
826 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); | ||
827 | c = ldev->lineout_ctrl; | ||
828 | if (c) | ||
829 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); | ||
830 | } | ||
831 | } | ||
832 | |||
833 | static void layout_attached_codec(struct aoa_codec *codec) | ||
834 | { | ||
835 | struct codec_connection *cc; | ||
836 | struct snd_kcontrol *ctl; | ||
837 | int headphones, lineout; | ||
838 | struct layout_dev *ldev = layout_device; | ||
839 | |||
840 | /* need to add this codec to our codec array! */ | ||
841 | |||
842 | cc = codec->fabric_data; | ||
843 | |||
844 | headphones = codec->gpio->methods->get_detect(codec->gpio, | ||
845 | AOA_NOTIFY_HEADPHONE); | ||
846 | lineout = codec->gpio->methods->get_detect(codec->gpio, | ||
847 | AOA_NOTIFY_LINE_OUT); | ||
848 | |||
849 | while (cc->connected) { | ||
850 | if (cc->connected & CC_SPEAKERS) { | ||
851 | if (headphones <= 0 && lineout <= 0) | ||
852 | ldev->gpio.methods->set_speakers(codec->gpio, 1); | ||
853 | ctl = snd_ctl_new1(&speakers_ctl, codec->gpio); | ||
854 | ldev->speaker_ctrl = ctl; | ||
855 | aoa_snd_ctl_add(ctl); | ||
856 | } | ||
857 | if (cc->connected & CC_HEADPHONE) { | ||
858 | if (headphones == 1) | ||
859 | ldev->gpio.methods->set_headphone(codec->gpio, 1); | ||
860 | ctl = snd_ctl_new1(&headphone_ctl, codec->gpio); | ||
861 | ldev->headphone_ctrl = ctl; | ||
862 | aoa_snd_ctl_add(ctl); | ||
863 | ldev->have_headphone_detect = | ||
864 | !ldev->gpio.methods | ||
865 | ->set_notify(&ldev->gpio, | ||
866 | AOA_NOTIFY_HEADPHONE, | ||
867 | layout_notify, | ||
868 | &ldev->selfptr_headphone); | ||
869 | if (ldev->have_headphone_detect) { | ||
870 | ctl = snd_ctl_new1(&headphone_detect_choice, | ||
871 | ldev); | ||
872 | aoa_snd_ctl_add(ctl); | ||
873 | ctl = snd_ctl_new1(&headphone_detected, | ||
874 | ldev); | ||
875 | ldev->headphone_detected_ctrl = ctl; | ||
876 | aoa_snd_ctl_add(ctl); | ||
877 | } | ||
878 | } | ||
879 | if (cc->connected & CC_LINEOUT) { | ||
880 | if (lineout == 1) | ||
881 | ldev->gpio.methods->set_lineout(codec->gpio, 1); | ||
882 | ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); | ||
883 | if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) | ||
884 | strlcpy(ctl->id.name, | ||
885 | "Headphone Switch", sizeof(ctl->id.name)); | ||
886 | ldev->lineout_ctrl = ctl; | ||
887 | aoa_snd_ctl_add(ctl); | ||
888 | ldev->have_lineout_detect = | ||
889 | !ldev->gpio.methods | ||
890 | ->set_notify(&ldev->gpio, | ||
891 | AOA_NOTIFY_LINE_OUT, | ||
892 | layout_notify, | ||
893 | &ldev->selfptr_lineout); | ||
894 | if (ldev->have_lineout_detect) { | ||
895 | ctl = snd_ctl_new1(&lineout_detect_choice, | ||
896 | ldev); | ||
897 | if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) | ||
898 | strlcpy(ctl->id.name, | ||
899 | "Headphone Detect Autoswitch", | ||
900 | sizeof(ctl->id.name)); | ||
901 | aoa_snd_ctl_add(ctl); | ||
902 | ctl = snd_ctl_new1(&lineout_detected, | ||
903 | ldev); | ||
904 | if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) | ||
905 | strlcpy(ctl->id.name, | ||
906 | "Headphone Detected", | ||
907 | sizeof(ctl->id.name)); | ||
908 | ldev->lineout_detected_ctrl = ctl; | ||
909 | aoa_snd_ctl_add(ctl); | ||
910 | } | ||
911 | } | ||
912 | cc++; | ||
913 | } | ||
914 | /* now update initial state */ | ||
915 | if (ldev->have_headphone_detect) | ||
916 | layout_notify(&ldev->selfptr_headphone); | ||
917 | if (ldev->have_lineout_detect) | ||
918 | layout_notify(&ldev->selfptr_lineout); | ||
919 | } | ||
920 | |||
921 | static struct aoa_fabric layout_fabric = { | ||
922 | .name = "SoundByLayout", | ||
923 | .owner = THIS_MODULE, | ||
924 | .found_codec = layout_found_codec, | ||
925 | .remove_codec = layout_remove_codec, | ||
926 | .attached_codec = layout_attached_codec, | ||
927 | }; | ||
928 | |||
929 | static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) | ||
930 | { | ||
931 | struct device_node *sound = NULL; | ||
932 | unsigned int *layout_id; | ||
933 | struct layout *layout; | ||
934 | struct layout_dev *ldev = NULL; | ||
935 | int err; | ||
936 | |||
937 | /* hm, currently we can only have one ... */ | ||
938 | if (layout_device) | ||
939 | return -ENODEV; | ||
940 | |||
941 | /* by breaking out we keep a reference */ | ||
942 | while ((sound = of_get_next_child(sdev->ofdev.node, sound))) { | ||
943 | if (sound->type && strcasecmp(sound->type, "soundchip") == 0) | ||
944 | break; | ||
945 | } | ||
946 | if (!sound) return -ENODEV; | ||
947 | |||
948 | layout_id = (unsigned int *) get_property(sound, "layout-id", NULL); | ||
949 | if (!layout_id) | ||
950 | goto outnodev; | ||
951 | printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d ", *layout_id); | ||
952 | |||
953 | layout = find_layout_by_id(*layout_id); | ||
954 | if (!layout) { | ||
955 | printk("(no idea how to handle)\n"); | ||
956 | goto outnodev; | ||
957 | } | ||
958 | |||
959 | ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL); | ||
960 | if (!ldev) | ||
961 | goto outnodev; | ||
962 | |||
963 | layout_device = ldev; | ||
964 | ldev->sdev = sdev; | ||
965 | ldev->sound = sound; | ||
966 | ldev->layout = layout; | ||
967 | ldev->gpio.node = sound->parent; | ||
968 | switch (layout->layout_id) { | ||
969 | case 41: /* that unknown machine no one seems to have */ | ||
970 | case 51: /* PowerBook5,4 */ | ||
971 | case 58: /* Mac Mini */ | ||
972 | ldev->gpio.methods = ftr_gpio_methods; | ||
973 | break; | ||
974 | default: | ||
975 | ldev->gpio.methods = pmf_gpio_methods; | ||
976 | } | ||
977 | ldev->selfptr_headphone.ptr = ldev; | ||
978 | ldev->selfptr_lineout.ptr = ldev; | ||
979 | sdev->ofdev.dev.driver_data = ldev; | ||
980 | |||
981 | printk("(using)\n"); | ||
982 | list_add(&ldev->list, &layouts_list); | ||
983 | layouts_list_items++; | ||
984 | |||
985 | /* assign these before registering ourselves, so | ||
986 | * callbacks that are done during registration | ||
987 | * already have the values */ | ||
988 | sdev->pcmid = ldev->layout->pcmid; | ||
989 | if (ldev->layout->busname) { | ||
990 | sdev->pcmname = ldev->layout->busname; | ||
991 | } else { | ||
992 | sdev->pcmname = "Master"; | ||
993 | } | ||
994 | |||
995 | ldev->gpio.methods->init(&ldev->gpio); | ||
996 | |||
997 | err = aoa_fabric_register(&layout_fabric); | ||
998 | if (err && err != -EALREADY) { | ||
999 | printk(KERN_INFO "snd-aoa-fabric-layout: can't use," | ||
1000 | " another fabric is active!\n"); | ||
1001 | goto outlistdel; | ||
1002 | } | ||
1003 | |||
1004 | use_layout(layout); | ||
1005 | ldev->switch_on_headphone = 1; | ||
1006 | ldev->switch_on_lineout = 1; | ||
1007 | return 0; | ||
1008 | outlistdel: | ||
1009 | /* we won't be using these then... */ | ||
1010 | ldev->gpio.methods->exit(&ldev->gpio); | ||
1011 | /* reset if we didn't use it */ | ||
1012 | sdev->pcmname = NULL; | ||
1013 | sdev->pcmid = -1; | ||
1014 | list_del(&ldev->list); | ||
1015 | layouts_list_items--; | ||
1016 | outnodev: | ||
1017 | if (sound) of_node_put(sound); | ||
1018 | layout_device = NULL; | ||
1019 | if (ldev) kfree(ldev); | ||
1020 | return -ENODEV; | ||
1021 | } | ||
1022 | |||
1023 | static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) | ||
1024 | { | ||
1025 | struct layout_dev *ldev = sdev->ofdev.dev.driver_data; | ||
1026 | int i; | ||
1027 | |||
1028 | for (i=0; i<MAX_CODECS_PER_BUS; i++) { | ||
1029 | if (ldev->codecs[i]) { | ||
1030 | aoa_fabric_unlink_codec(ldev->codecs[i]); | ||
1031 | } | ||
1032 | ldev->codecs[i] = NULL; | ||
1033 | } | ||
1034 | list_del(&ldev->list); | ||
1035 | layouts_list_items--; | ||
1036 | of_node_put(ldev->sound); | ||
1037 | |||
1038 | ldev->gpio.methods->set_notify(&ldev->gpio, | ||
1039 | AOA_NOTIFY_HEADPHONE, | ||
1040 | NULL, | ||
1041 | NULL); | ||
1042 | ldev->gpio.methods->set_notify(&ldev->gpio, | ||
1043 | AOA_NOTIFY_LINE_OUT, | ||
1044 | NULL, | ||
1045 | NULL); | ||
1046 | |||
1047 | ldev->gpio.methods->exit(&ldev->gpio); | ||
1048 | layout_device = NULL; | ||
1049 | kfree(ldev); | ||
1050 | sdev->pcmid = -1; | ||
1051 | sdev->pcmname = NULL; | ||
1052 | return 0; | ||
1053 | } | ||
1054 | |||
1055 | #ifdef CONFIG_PM | ||
1056 | static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state) | ||
1057 | { | ||
1058 | struct layout_dev *ldev = sdev->ofdev.dev.driver_data; | ||
1059 | |||
1060 | printk("aoa_fabric_layout_suspend()\n"); | ||
1061 | |||
1062 | if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) | ||
1063 | ldev->gpio.methods->all_amps_off(&ldev->gpio); | ||
1064 | |||
1065 | return 0; | ||
1066 | } | ||
1067 | |||
1068 | static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) | ||
1069 | { | ||
1070 | struct layout_dev *ldev = sdev->ofdev.dev.driver_data; | ||
1071 | |||
1072 | printk("aoa_fabric_layout_resume()\n"); | ||
1073 | |||
1074 | if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) | ||
1075 | ldev->gpio.methods->all_amps_restore(&ldev->gpio); | ||
1076 | |||
1077 | return 0; | ||
1078 | } | ||
1079 | #endif | ||
1080 | |||
1081 | static struct soundbus_driver aoa_soundbus_driver = { | ||
1082 | .name = "snd_aoa_soundbus_drv", | ||
1083 | .owner = THIS_MODULE, | ||
1084 | .probe = aoa_fabric_layout_probe, | ||
1085 | .remove = aoa_fabric_layout_remove, | ||
1086 | #ifdef CONFIG_PM | ||
1087 | .suspend = aoa_fabric_layout_suspend, | ||
1088 | .resume = aoa_fabric_layout_resume, | ||
1089 | #endif | ||
1090 | }; | ||
1091 | |||
1092 | static int __init aoa_fabric_layout_init(void) | ||
1093 | { | ||
1094 | int err; | ||
1095 | |||
1096 | err = soundbus_register_driver(&aoa_soundbus_driver); | ||
1097 | if (err) | ||
1098 | return err; | ||
1099 | return 0; | ||
1100 | } | ||
1101 | |||
1102 | static void __exit aoa_fabric_layout_exit(void) | ||
1103 | { | ||
1104 | soundbus_unregister_driver(&aoa_soundbus_driver); | ||
1105 | aoa_fabric_unregister(&layout_fabric); | ||
1106 | } | ||
1107 | |||
1108 | module_init(aoa_fabric_layout_init); | ||
1109 | module_exit(aoa_fabric_layout_exit); | ||
diff --git a/sound/aoa/soundbus/Kconfig b/sound/aoa/soundbus/Kconfig new file mode 100644 index 000000000000..d532d27a9f54 --- /dev/null +++ b/sound/aoa/soundbus/Kconfig | |||
@@ -0,0 +1,14 @@ | |||
1 | config SND_AOA_SOUNDBUS | ||
2 | tristate "Apple Soundbus support" | ||
3 | depends on SOUND && SND_PCM && EXPERIMENTAL | ||
4 | ---help--- | ||
5 | This option enables the generic driver for the soundbus | ||
6 | support on Apple machines. | ||
7 | |||
8 | It is required for the sound bus implementations. | ||
9 | |||
10 | config SND_AOA_SOUNDBUS_I2S | ||
11 | tristate "I2S bus support" | ||
12 | depends on SND_AOA_SOUNDBUS && PCI | ||
13 | ---help--- | ||
14 | This option enables support for Apple I2S busses. | ||
diff --git a/sound/aoa/soundbus/Makefile b/sound/aoa/soundbus/Makefile new file mode 100644 index 000000000000..0e61f5aa06b5 --- /dev/null +++ b/sound/aoa/soundbus/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_SND_AOA_SOUNDBUS) += snd-aoa-soundbus.o | ||
2 | snd-aoa-soundbus-objs := core.o sysfs.o | ||
3 | obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += i2sbus/ | ||
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c new file mode 100644 index 000000000000..abe84a76c835 --- /dev/null +++ b/sound/aoa/soundbus/core.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * soundbus | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include "soundbus.h" | ||
11 | |||
12 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
13 | MODULE_LICENSE("GPL"); | ||
14 | MODULE_DESCRIPTION("Apple Soundbus"); | ||
15 | |||
16 | struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev) | ||
17 | { | ||
18 | struct device *tmp; | ||
19 | |||
20 | if (!dev) | ||
21 | return NULL; | ||
22 | tmp = get_device(&dev->ofdev.dev); | ||
23 | if (tmp) | ||
24 | return to_soundbus_device(tmp); | ||
25 | else | ||
26 | return NULL; | ||
27 | } | ||
28 | EXPORT_SYMBOL_GPL(soundbus_dev_get); | ||
29 | |||
30 | void soundbus_dev_put(struct soundbus_dev *dev) | ||
31 | { | ||
32 | if (dev) | ||
33 | put_device(&dev->ofdev.dev); | ||
34 | } | ||
35 | EXPORT_SYMBOL_GPL(soundbus_dev_put); | ||
36 | |||
37 | static int soundbus_probe(struct device *dev) | ||
38 | { | ||
39 | int error = -ENODEV; | ||
40 | struct soundbus_driver *drv; | ||
41 | struct soundbus_dev *soundbus_dev; | ||
42 | |||
43 | drv = to_soundbus_driver(dev->driver); | ||
44 | soundbus_dev = to_soundbus_device(dev); | ||
45 | |||
46 | if (!drv->probe) | ||
47 | return error; | ||
48 | |||
49 | soundbus_dev_get(soundbus_dev); | ||
50 | |||
51 | error = drv->probe(soundbus_dev); | ||
52 | if (error) | ||
53 | soundbus_dev_put(soundbus_dev); | ||
54 | |||
55 | return error; | ||
56 | } | ||
57 | |||
58 | |||
59 | static int soundbus_uevent(struct device *dev, char **envp, int num_envp, | ||
60 | char *buffer, int buffer_size) | ||
61 | { | ||
62 | struct soundbus_dev * soundbus_dev; | ||
63 | struct of_device * of; | ||
64 | char *scratch, *compat, *compat2; | ||
65 | int i = 0; | ||
66 | int length, cplen, cplen2, seen = 0; | ||
67 | |||
68 | if (!dev) | ||
69 | return -ENODEV; | ||
70 | |||
71 | soundbus_dev = to_soundbus_device(dev); | ||
72 | if (!soundbus_dev) | ||
73 | return -ENODEV; | ||
74 | |||
75 | of = &soundbus_dev->ofdev; | ||
76 | |||
77 | /* stuff we want to pass to /sbin/hotplug */ | ||
78 | envp[i++] = scratch = buffer; | ||
79 | length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name); | ||
80 | ++length; | ||
81 | buffer_size -= length; | ||
82 | if ((buffer_size <= 0) || (i >= num_envp)) | ||
83 | return -ENOMEM; | ||
84 | scratch += length; | ||
85 | |||
86 | envp[i++] = scratch; | ||
87 | length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type); | ||
88 | ++length; | ||
89 | buffer_size -= length; | ||
90 | if ((buffer_size <= 0) || (i >= num_envp)) | ||
91 | return -ENOMEM; | ||
92 | scratch += length; | ||
93 | |||
94 | /* Since the compatible field can contain pretty much anything | ||
95 | * it's not really legal to split it out with commas. We split it | ||
96 | * up using a number of environment variables instead. */ | ||
97 | |||
98 | compat = (char *) get_property(of->node, "compatible", &cplen); | ||
99 | compat2 = compat; | ||
100 | cplen2= cplen; | ||
101 | while (compat && cplen > 0) { | ||
102 | envp[i++] = scratch; | ||
103 | length = scnprintf (scratch, buffer_size, | ||
104 | "OF_COMPATIBLE_%d=%s", seen, compat); | ||
105 | ++length; | ||
106 | buffer_size -= length; | ||
107 | if ((buffer_size <= 0) || (i >= num_envp)) | ||
108 | return -ENOMEM; | ||
109 | scratch += length; | ||
110 | length = strlen (compat) + 1; | ||
111 | compat += length; | ||
112 | cplen -= length; | ||
113 | seen++; | ||
114 | } | ||
115 | |||
116 | envp[i++] = scratch; | ||
117 | length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen); | ||
118 | ++length; | ||
119 | buffer_size -= length; | ||
120 | if ((buffer_size <= 0) || (i >= num_envp)) | ||
121 | return -ENOMEM; | ||
122 | scratch += length; | ||
123 | |||
124 | envp[i++] = scratch; | ||
125 | length = scnprintf (scratch, buffer_size, "MODALIAS=%s", | ||
126 | soundbus_dev->modalias); | ||
127 | |||
128 | buffer_size -= length; | ||
129 | if ((buffer_size <= 0) || (i >= num_envp)) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | envp[i] = NULL; | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int soundbus_device_remove(struct device *dev) | ||
138 | { | ||
139 | struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); | ||
140 | struct soundbus_driver * drv = to_soundbus_driver(dev->driver); | ||
141 | |||
142 | if (dev->driver && drv->remove) | ||
143 | drv->remove(soundbus_dev); | ||
144 | soundbus_dev_put(soundbus_dev); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static void soundbus_device_shutdown(struct device *dev) | ||
150 | { | ||
151 | struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); | ||
152 | struct soundbus_driver * drv = to_soundbus_driver(dev->driver); | ||
153 | |||
154 | if (dev->driver && drv->shutdown) | ||
155 | drv->shutdown(soundbus_dev); | ||
156 | } | ||
157 | |||
158 | #ifdef CONFIG_PM | ||
159 | |||
160 | static int soundbus_device_suspend(struct device *dev, pm_message_t state) | ||
161 | { | ||
162 | struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); | ||
163 | struct soundbus_driver * drv = to_soundbus_driver(dev->driver); | ||
164 | |||
165 | if (dev->driver && drv->suspend) | ||
166 | return drv->suspend(soundbus_dev, state); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | static int soundbus_device_resume(struct device * dev) | ||
171 | { | ||
172 | struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); | ||
173 | struct soundbus_driver * drv = to_soundbus_driver(dev->driver); | ||
174 | |||
175 | if (dev->driver && drv->resume) | ||
176 | return drv->resume(soundbus_dev); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | #endif /* CONFIG_PM */ | ||
181 | |||
182 | extern struct device_attribute soundbus_dev_attrs[]; | ||
183 | |||
184 | static struct bus_type soundbus_bus_type = { | ||
185 | .name = "aoa-soundbus", | ||
186 | .probe = soundbus_probe, | ||
187 | .uevent = soundbus_uevent, | ||
188 | .remove = soundbus_device_remove, | ||
189 | .shutdown = soundbus_device_shutdown, | ||
190 | #ifdef CONFIG_PM | ||
191 | .suspend = soundbus_device_suspend, | ||
192 | .resume = soundbus_device_resume, | ||
193 | #endif | ||
194 | .dev_attrs = soundbus_dev_attrs, | ||
195 | }; | ||
196 | |||
197 | static int __init soundbus_init(void) | ||
198 | { | ||
199 | return bus_register(&soundbus_bus_type); | ||
200 | } | ||
201 | |||
202 | static void __exit soundbus_exit(void) | ||
203 | { | ||
204 | bus_unregister(&soundbus_bus_type); | ||
205 | } | ||
206 | |||
207 | int soundbus_add_one(struct soundbus_dev *dev) | ||
208 | { | ||
209 | static int devcount; | ||
210 | |||
211 | /* sanity checks */ | ||
212 | if (!dev->attach_codec || | ||
213 | !dev->ofdev.node || | ||
214 | dev->pcmname || | ||
215 | dev->pcmid != -1) { | ||
216 | printk(KERN_ERR "soundbus: adding device failed sanity check!\n"); | ||
217 | return -EINVAL; | ||
218 | } | ||
219 | |||
220 | snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount); | ||
221 | dev->ofdev.dev.bus = &soundbus_bus_type; | ||
222 | return of_device_register(&dev->ofdev); | ||
223 | } | ||
224 | EXPORT_SYMBOL_GPL(soundbus_add_one); | ||
225 | |||
226 | void soundbus_remove_one(struct soundbus_dev *dev) | ||
227 | { | ||
228 | of_device_unregister(&dev->ofdev); | ||
229 | } | ||
230 | EXPORT_SYMBOL_GPL(soundbus_remove_one); | ||
231 | |||
232 | int soundbus_register_driver(struct soundbus_driver *drv) | ||
233 | { | ||
234 | /* initialize common driver fields */ | ||
235 | drv->driver.name = drv->name; | ||
236 | drv->driver.bus = &soundbus_bus_type; | ||
237 | |||
238 | /* register with core */ | ||
239 | return driver_register(&drv->driver); | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(soundbus_register_driver); | ||
242 | |||
243 | void soundbus_unregister_driver(struct soundbus_driver *drv) | ||
244 | { | ||
245 | driver_unregister(&drv->driver); | ||
246 | } | ||
247 | EXPORT_SYMBOL_GPL(soundbus_unregister_driver); | ||
248 | |||
249 | module_init(soundbus_init); | ||
250 | module_exit(soundbus_exit); | ||
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile new file mode 100644 index 000000000000..e57a5cf65655 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o | ||
2 | snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o | ||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c new file mode 100644 index 000000000000..f50407952d3c --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c | |||
@@ -0,0 +1,192 @@ | |||
1 | /* | ||
2 | * i2sbus driver -- bus control routines | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #include <asm/io.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <asm/prom.h> | ||
12 | #include <asm/macio.h> | ||
13 | #include <asm/pmac_feature.h> | ||
14 | #include <asm/pmac_pfunc.h> | ||
15 | #include "i2sbus.h" | ||
16 | |||
17 | int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c) | ||
18 | { | ||
19 | *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL); | ||
20 | if (!*c) | ||
21 | return -ENOMEM; | ||
22 | |||
23 | INIT_LIST_HEAD(&(*c)->list); | ||
24 | |||
25 | if (of_address_to_resource(dev->ofdev.node, 0, &(*c)->rsrc)) | ||
26 | goto err; | ||
27 | /* we really should be using feature calls instead of mapping | ||
28 | * these registers. It's safe for now since no one else is | ||
29 | * touching them... */ | ||
30 | (*c)->controlregs = ioremap((*c)->rsrc.start, | ||
31 | sizeof(struct i2s_control_regs)); | ||
32 | if (!(*c)->controlregs) | ||
33 | goto err; | ||
34 | |||
35 | return 0; | ||
36 | err: | ||
37 | kfree(*c); | ||
38 | *c = NULL; | ||
39 | return -ENODEV; | ||
40 | } | ||
41 | |||
42 | void i2sbus_control_destroy(struct i2sbus_control *c) | ||
43 | { | ||
44 | iounmap(c->controlregs); | ||
45 | kfree(c); | ||
46 | } | ||
47 | |||
48 | /* this is serialised externally */ | ||
49 | int i2sbus_control_add_dev(struct i2sbus_control *c, | ||
50 | struct i2sbus_dev *i2sdev) | ||
51 | { | ||
52 | struct device_node *np; | ||
53 | |||
54 | np = i2sdev->sound.ofdev.node; | ||
55 | i2sdev->enable = pmf_find_function(np, "enable"); | ||
56 | i2sdev->cell_enable = pmf_find_function(np, "cell-enable"); | ||
57 | i2sdev->clock_enable = pmf_find_function(np, "clock-enable"); | ||
58 | i2sdev->cell_disable = pmf_find_function(np, "cell-disable"); | ||
59 | i2sdev->clock_disable = pmf_find_function(np, "clock-disable"); | ||
60 | |||
61 | /* if the bus number is not 0 or 1 we absolutely need to use | ||
62 | * the platform functions -- there's nothing in Darwin that | ||
63 | * would allow seeing a system behind what the FCRs are then, | ||
64 | * and I don't want to go parsing a bunch of platform functions | ||
65 | * by hand to try finding a system... */ | ||
66 | if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 && | ||
67 | (!i2sdev->enable || | ||
68 | !i2sdev->cell_enable || !i2sdev->clock_enable || | ||
69 | !i2sdev->cell_disable || !i2sdev->clock_disable)) { | ||
70 | pmf_put_function(i2sdev->enable); | ||
71 | pmf_put_function(i2sdev->cell_enable); | ||
72 | pmf_put_function(i2sdev->clock_enable); | ||
73 | pmf_put_function(i2sdev->cell_disable); | ||
74 | pmf_put_function(i2sdev->clock_disable); | ||
75 | return -ENODEV; | ||
76 | } | ||
77 | |||
78 | list_add(&i2sdev->item, &c->list); | ||
79 | |||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | void i2sbus_control_remove_dev(struct i2sbus_control *c, | ||
84 | struct i2sbus_dev *i2sdev) | ||
85 | { | ||
86 | /* this is serialised externally */ | ||
87 | list_del(&i2sdev->item); | ||
88 | if (list_empty(&c->list)) | ||
89 | i2sbus_control_destroy(c); | ||
90 | } | ||
91 | |||
92 | int i2sbus_control_enable(struct i2sbus_control *c, | ||
93 | struct i2sbus_dev *i2sdev) | ||
94 | { | ||
95 | struct pmf_args args = { .count = 0 }; | ||
96 | int cc; | ||
97 | |||
98 | if (i2sdev->enable) | ||
99 | return pmf_call_one(i2sdev->enable, &args); | ||
100 | |||
101 | switch (i2sdev->bus_number) { | ||
102 | case 0: | ||
103 | cc = in_le32(&c->controlregs->cell_control); | ||
104 | out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_0_ENABLE); | ||
105 | break; | ||
106 | case 1: | ||
107 | cc = in_le32(&c->controlregs->cell_control); | ||
108 | out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_1_ENABLE); | ||
109 | break; | ||
110 | default: | ||
111 | return -ENODEV; | ||
112 | } | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | int i2sbus_control_cell(struct i2sbus_control *c, | ||
117 | struct i2sbus_dev *i2sdev, | ||
118 | int enable) | ||
119 | { | ||
120 | struct pmf_args args = { .count = 0 }; | ||
121 | int cc; | ||
122 | |||
123 | switch (enable) { | ||
124 | case 0: | ||
125 | if (i2sdev->cell_disable) | ||
126 | return pmf_call_one(i2sdev->cell_disable, &args); | ||
127 | break; | ||
128 | case 1: | ||
129 | if (i2sdev->cell_enable) | ||
130 | return pmf_call_one(i2sdev->cell_enable, &args); | ||
131 | break; | ||
132 | default: | ||
133 | printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n"); | ||
134 | return -ENODEV; | ||
135 | } | ||
136 | switch (i2sdev->bus_number) { | ||
137 | case 0: | ||
138 | cc = in_le32(&c->controlregs->cell_control); | ||
139 | cc &= ~CTRL_CLOCK_CELL_0_ENABLE; | ||
140 | cc |= enable * CTRL_CLOCK_CELL_0_ENABLE; | ||
141 | out_le32(&c->controlregs->cell_control, cc); | ||
142 | break; | ||
143 | case 1: | ||
144 | cc = in_le32(&c->controlregs->cell_control); | ||
145 | cc &= ~CTRL_CLOCK_CELL_1_ENABLE; | ||
146 | cc |= enable * CTRL_CLOCK_CELL_1_ENABLE; | ||
147 | out_le32(&c->controlregs->cell_control, cc); | ||
148 | break; | ||
149 | default: | ||
150 | return -ENODEV; | ||
151 | } | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | int i2sbus_control_clock(struct i2sbus_control *c, | ||
156 | struct i2sbus_dev *i2sdev, | ||
157 | int enable) | ||
158 | { | ||
159 | struct pmf_args args = { .count = 0 }; | ||
160 | int cc; | ||
161 | |||
162 | switch (enable) { | ||
163 | case 0: | ||
164 | if (i2sdev->clock_disable) | ||
165 | return pmf_call_one(i2sdev->clock_disable, &args); | ||
166 | break; | ||
167 | case 1: | ||
168 | if (i2sdev->clock_enable) | ||
169 | return pmf_call_one(i2sdev->clock_enable, &args); | ||
170 | break; | ||
171 | default: | ||
172 | printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n"); | ||
173 | return -ENODEV; | ||
174 | } | ||
175 | switch (i2sdev->bus_number) { | ||
176 | case 0: | ||
177 | cc = in_le32(&c->controlregs->cell_control); | ||
178 | cc &= ~CTRL_CLOCK_CLOCK_0_ENABLE; | ||
179 | cc |= enable * CTRL_CLOCK_CLOCK_0_ENABLE; | ||
180 | out_le32(&c->controlregs->cell_control, cc); | ||
181 | break; | ||
182 | case 1: | ||
183 | cc = in_le32(&c->controlregs->cell_control); | ||
184 | cc &= ~CTRL_CLOCK_CLOCK_1_ENABLE; | ||
185 | cc |= enable * CTRL_CLOCK_CLOCK_1_ENABLE; | ||
186 | out_le32(&c->controlregs->cell_control, cc); | ||
187 | break; | ||
188 | default: | ||
189 | return -ENODEV; | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.h b/sound/aoa/soundbus/i2sbus/i2sbus-control.h new file mode 100644 index 000000000000..bb05550f730b --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * i2sbus driver -- bus register definitions | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | #ifndef __I2SBUS_CONTROLREGS_H | ||
9 | #define __I2SBUS_CONTROLREGS_H | ||
10 | |||
11 | /* i2s control registers, at least what we know about them */ | ||
12 | |||
13 | #define __PAD(m,n) u8 __pad##m[n] | ||
14 | #define _PAD(line, n) __PAD(line, n) | ||
15 | #define PAD(n) _PAD(__LINE__, (n)) | ||
16 | struct i2s_control_regs { | ||
17 | PAD(0x38); | ||
18 | __le32 fcr0; /* 0x38 (unknown) */ | ||
19 | __le32 cell_control; /* 0x3c (fcr1) */ | ||
20 | __le32 fcr2; /* 0x40 (unknown) */ | ||
21 | __le32 fcr3; /* 0x44 (fcr3) */ | ||
22 | __le32 clock_control; /* 0x48 (unknown) */ | ||
23 | PAD(4); | ||
24 | /* total size: 0x50 bytes */ | ||
25 | } __attribute__((__packed__)); | ||
26 | |||
27 | #define CTRL_CLOCK_CELL_0_ENABLE (1<<10) | ||
28 | #define CTRL_CLOCK_CLOCK_0_ENABLE (1<<12) | ||
29 | #define CTRL_CLOCK_SWRESET_0 (1<<11) | ||
30 | #define CTRL_CLOCK_INTF_0_ENABLE (1<<13) | ||
31 | |||
32 | #define CTRL_CLOCK_CELL_1_ENABLE (1<<17) | ||
33 | #define CTRL_CLOCK_CLOCK_1_ENABLE (1<<18) | ||
34 | #define CTRL_CLOCK_SWRESET_1 (1<<19) | ||
35 | #define CTRL_CLOCK_INTF_1_ENABLE (1<<20) | ||
36 | |||
37 | #endif /* __I2SBUS_CONTROLREGS_H */ | ||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c new file mode 100644 index 000000000000..f268dacdaa00 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | * i2sbus driver | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <asm/macio.h> | ||
11 | #include <asm/dbdma.h> | ||
12 | #include <linux/pci.h> | ||
13 | #include <linux/interrupt.h> | ||
14 | #include <sound/driver.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <linux/dma-mapping.h> | ||
17 | #include "../soundbus.h" | ||
18 | #include "i2sbus.h" | ||
19 | |||
20 | MODULE_LICENSE("GPL"); | ||
21 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | ||
22 | MODULE_DESCRIPTION("Apple Soundbus: I2S support"); | ||
23 | /* for auto-loading, declare that we handle this weird | ||
24 | * string that macio puts into the relevant device */ | ||
25 | MODULE_ALIAS("of:Ni2sTi2sC"); | ||
26 | |||
27 | static struct of_device_id i2sbus_match[] = { | ||
28 | { .name = "i2s" }, | ||
29 | { } | ||
30 | }; | ||
31 | |||
32 | static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, | ||
33 | struct dbdma_command_mem *r, | ||
34 | int numcmds) | ||
35 | { | ||
36 | /* one more for rounding */ | ||
37 | r->size = (numcmds+1) * sizeof(struct dbdma_cmd); | ||
38 | /* We use the PCI APIs for now until the generic one gets fixed | ||
39 | * enough or until we get some macio-specific versions | ||
40 | */ | ||
41 | r->space = dma_alloc_coherent( | ||
42 | &macio_get_pci_dev(i2sdev->macio)->dev, | ||
43 | r->size, | ||
44 | &r->bus_addr, | ||
45 | GFP_KERNEL); | ||
46 | |||
47 | if (!r->space) return -ENOMEM; | ||
48 | |||
49 | memset(r->space, 0, r->size); | ||
50 | r->cmds = (void*)DBDMA_ALIGN(r->space); | ||
51 | r->bus_cmd_start = r->bus_addr + | ||
52 | (dma_addr_t)((char*)r->cmds - (char*)r->space); | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, | ||
58 | struct dbdma_command_mem *r) | ||
59 | { | ||
60 | if (!r->space) return; | ||
61 | |||
62 | dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, | ||
63 | r->size, r->space, r->bus_addr); | ||
64 | } | ||
65 | |||
66 | static void i2sbus_release_dev(struct device *dev) | ||
67 | { | ||
68 | struct i2sbus_dev *i2sdev; | ||
69 | int i; | ||
70 | |||
71 | i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev); | ||
72 | |||
73 | if (i2sdev->intfregs) iounmap(i2sdev->intfregs); | ||
74 | if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma); | ||
75 | if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma); | ||
76 | for (i=0;i<3;i++) | ||
77 | if (i2sdev->allocated_resource[i]) | ||
78 | release_and_free_resource(i2sdev->allocated_resource[i]); | ||
79 | free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring); | ||
80 | free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring); | ||
81 | for (i=0;i<3;i++) | ||
82 | free_irq(i2sdev->interrupts[i], i2sdev); | ||
83 | i2sbus_control_remove_dev(i2sdev->control, i2sdev); | ||
84 | mutex_destroy(&i2sdev->lock); | ||
85 | kfree(i2sdev); | ||
86 | } | ||
87 | |||
88 | static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs) | ||
89 | { | ||
90 | struct i2sbus_dev *dev = devid; | ||
91 | u32 intreg; | ||
92 | |||
93 | spin_lock(&dev->low_lock); | ||
94 | intreg = in_le32(&dev->intfregs->intr_ctl); | ||
95 | |||
96 | /* acknowledge interrupt reasons */ | ||
97 | out_le32(&dev->intfregs->intr_ctl, intreg); | ||
98 | |||
99 | spin_unlock(&dev->low_lock); | ||
100 | |||
101 | return IRQ_HANDLED; | ||
102 | } | ||
103 | |||
104 | static int force; | ||
105 | module_param(force, int, 0444); | ||
106 | MODULE_PARM_DESC(force, "Force loading i2sbus even when" | ||
107 | " no layout-id property is present"); | ||
108 | |||
109 | /* FIXME: look at device node refcounting */ | ||
110 | static int i2sbus_add_dev(struct macio_dev *macio, | ||
111 | struct i2sbus_control *control, | ||
112 | struct device_node *np) | ||
113 | { | ||
114 | struct i2sbus_dev *dev; | ||
115 | struct device_node *child = NULL, *sound = NULL; | ||
116 | int i; | ||
117 | static const char *rnames[] = { "i2sbus: %s (control)", | ||
118 | "i2sbus: %s (tx)", | ||
119 | "i2sbus: %s (rx)" }; | ||
120 | static irqreturn_t (*ints[])(int irq, void *devid, | ||
121 | struct pt_regs *regs) = { | ||
122 | i2sbus_bus_intr, | ||
123 | i2sbus_tx_intr, | ||
124 | i2sbus_rx_intr | ||
125 | }; | ||
126 | |||
127 | if (strlen(np->name) != 5) | ||
128 | return 0; | ||
129 | if (strncmp(np->name, "i2s-", 4)) | ||
130 | return 0; | ||
131 | |||
132 | if (np->n_intrs != 3) | ||
133 | return 0; | ||
134 | |||
135 | dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); | ||
136 | if (!dev) | ||
137 | return 0; | ||
138 | |||
139 | i = 0; | ||
140 | while ((child = of_get_next_child(np, child))) { | ||
141 | if (strcmp(child->name, "sound") == 0) { | ||
142 | i++; | ||
143 | sound = child; | ||
144 | } | ||
145 | } | ||
146 | if (i == 1) { | ||
147 | u32 *layout_id; | ||
148 | layout_id = (u32*) get_property(sound, "layout-id", NULL); | ||
149 | if (layout_id) { | ||
150 | snprintf(dev->sound.modalias, 32, | ||
151 | "sound-layout-%d", *layout_id); | ||
152 | force = 1; | ||
153 | } | ||
154 | } | ||
155 | /* for the time being, until we can handle non-layout-id | ||
156 | * things in some fabric, refuse to attach if there is no | ||
157 | * layout-id property or we haven't been forced to attach. | ||
158 | * When there are two i2s busses and only one has a layout-id, | ||
159 | * then this depends on the order, but that isn't important | ||
160 | * either as the second one in that case is just a modem. */ | ||
161 | if (!force) { | ||
162 | kfree(dev); | ||
163 | return -ENODEV; | ||
164 | } | ||
165 | |||
166 | mutex_init(&dev->lock); | ||
167 | spin_lock_init(&dev->low_lock); | ||
168 | dev->sound.ofdev.node = np; | ||
169 | dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask; | ||
170 | dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask; | ||
171 | dev->sound.ofdev.dev.parent = &macio->ofdev.dev; | ||
172 | dev->sound.ofdev.dev.release = i2sbus_release_dev; | ||
173 | dev->sound.attach_codec = i2sbus_attach_codec; | ||
174 | dev->sound.detach_codec = i2sbus_detach_codec; | ||
175 | dev->sound.pcmid = -1; | ||
176 | dev->macio = macio; | ||
177 | dev->control = control; | ||
178 | dev->bus_number = np->name[4] - 'a'; | ||
179 | INIT_LIST_HEAD(&dev->sound.codec_list); | ||
180 | |||
181 | for (i=0;i<3;i++) { | ||
182 | dev->interrupts[i] = -1; | ||
183 | snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name); | ||
184 | } | ||
185 | for (i=0;i<3;i++) { | ||
186 | if (request_irq(np->intrs[i].line, ints[i], 0, dev->rnames[i], dev)) | ||
187 | goto err; | ||
188 | dev->interrupts[i] = np->intrs[i].line; | ||
189 | } | ||
190 | |||
191 | for (i=0;i<3;i++) { | ||
192 | if (of_address_to_resource(np, i, &dev->resources[i])) | ||
193 | goto err; | ||
194 | /* if only we could use our resource dev->resources[i]... | ||
195 | * but request_resource doesn't know about parents and | ||
196 | * contained resources... */ | ||
197 | dev->allocated_resource[i] = | ||
198 | request_mem_region(dev->resources[i].start, | ||
199 | dev->resources[i].end - | ||
200 | dev->resources[i].start + 1, | ||
201 | dev->rnames[i]); | ||
202 | if (!dev->allocated_resource[i]) { | ||
203 | printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i); | ||
204 | goto err; | ||
205 | } | ||
206 | } | ||
207 | /* should do sanity checking here about length of them */ | ||
208 | dev->intfregs = ioremap(dev->resources[0].start, | ||
209 | dev->resources[0].end-dev->resources[0].start+1); | ||
210 | dev->out.dbdma = ioremap(dev->resources[1].start, | ||
211 | dev->resources[1].end-dev->resources[1].start+1); | ||
212 | dev->in.dbdma = ioremap(dev->resources[2].start, | ||
213 | dev->resources[2].end-dev->resources[2].start+1); | ||
214 | if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma) | ||
215 | goto err; | ||
216 | |||
217 | if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring, | ||
218 | MAX_DBDMA_COMMANDS)) | ||
219 | goto err; | ||
220 | if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring, | ||
221 | MAX_DBDMA_COMMANDS)) | ||
222 | goto err; | ||
223 | |||
224 | if (i2sbus_control_add_dev(dev->control, dev)) { | ||
225 | printk(KERN_ERR "i2sbus: control layer didn't like bus\n"); | ||
226 | goto err; | ||
227 | } | ||
228 | |||
229 | if (soundbus_add_one(&dev->sound)) { | ||
230 | printk(KERN_DEBUG "i2sbus: device registration error!\n"); | ||
231 | goto err; | ||
232 | } | ||
233 | |||
234 | /* enable this cell */ | ||
235 | i2sbus_control_cell(dev->control, dev, 1); | ||
236 | i2sbus_control_enable(dev->control, dev); | ||
237 | i2sbus_control_clock(dev->control, dev, 1); | ||
238 | |||
239 | return 1; | ||
240 | err: | ||
241 | for (i=0;i<3;i++) | ||
242 | if (dev->interrupts[i] != -1) | ||
243 | free_irq(dev->interrupts[i], dev); | ||
244 | free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring); | ||
245 | free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring); | ||
246 | if (dev->intfregs) iounmap(dev->intfregs); | ||
247 | if (dev->out.dbdma) iounmap(dev->out.dbdma); | ||
248 | if (dev->in.dbdma) iounmap(dev->in.dbdma); | ||
249 | for (i=0;i<3;i++) | ||
250 | if (dev->allocated_resource[i]) | ||
251 | release_and_free_resource(dev->allocated_resource[i]); | ||
252 | mutex_destroy(&dev->lock); | ||
253 | kfree(dev); | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match) | ||
258 | { | ||
259 | struct device_node *np = NULL; | ||
260 | int got = 0, err; | ||
261 | struct i2sbus_control *control = NULL; | ||
262 | |||
263 | err = i2sbus_control_init(dev, &control); | ||
264 | if (err) | ||
265 | return err; | ||
266 | if (!control) { | ||
267 | printk(KERN_ERR "i2sbus_control_init API breakage\n"); | ||
268 | return -ENODEV; | ||
269 | } | ||
270 | |||
271 | while ((np = of_get_next_child(dev->ofdev.node, np))) { | ||
272 | if (device_is_compatible(np, "i2sbus") || | ||
273 | device_is_compatible(np, "i2s-modem")) { | ||
274 | got += i2sbus_add_dev(dev, control, np); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | if (!got) { | ||
279 | /* found none, clean up */ | ||
280 | i2sbus_control_destroy(control); | ||
281 | return -ENODEV; | ||
282 | } | ||
283 | |||
284 | dev->ofdev.dev.driver_data = control; | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int i2sbus_remove(struct macio_dev* dev) | ||
290 | { | ||
291 | struct i2sbus_control *control = dev->ofdev.dev.driver_data; | ||
292 | struct i2sbus_dev *i2sdev, *tmp; | ||
293 | |||
294 | list_for_each_entry_safe(i2sdev, tmp, &control->list, item) | ||
295 | soundbus_remove_one(&i2sdev->sound); | ||
296 | |||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | #ifdef CONFIG_PM | ||
301 | static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state) | ||
302 | { | ||
303 | struct i2sbus_control *control = dev->ofdev.dev.driver_data; | ||
304 | struct codec_info_item *cii; | ||
305 | struct i2sbus_dev* i2sdev; | ||
306 | int err, ret = 0; | ||
307 | |||
308 | list_for_each_entry(i2sdev, &control->list, item) { | ||
309 | /* Notify Alsa */ | ||
310 | if (i2sdev->sound.pcm) { | ||
311 | /* Suspend PCM streams */ | ||
312 | snd_pcm_suspend_all(i2sdev->sound.pcm); | ||
313 | /* Probably useless as we handle | ||
314 | * power transitions ourselves */ | ||
315 | snd_power_change_state(i2sdev->sound.pcm->card, | ||
316 | SNDRV_CTL_POWER_D3hot); | ||
317 | } | ||
318 | /* Notify codecs */ | ||
319 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
320 | err = 0; | ||
321 | if (cii->codec->suspend) | ||
322 | err = cii->codec->suspend(cii, state); | ||
323 | if (err) | ||
324 | ret = err; | ||
325 | } | ||
326 | } | ||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | static int i2sbus_resume(struct macio_dev* dev) | ||
331 | { | ||
332 | struct i2sbus_control *control = dev->ofdev.dev.driver_data; | ||
333 | struct codec_info_item *cii; | ||
334 | struct i2sbus_dev* i2sdev; | ||
335 | int err, ret = 0; | ||
336 | |||
337 | list_for_each_entry(i2sdev, &control->list, item) { | ||
338 | /* Notify codecs so they can re-initialize */ | ||
339 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
340 | err = 0; | ||
341 | if (cii->codec->resume) | ||
342 | err = cii->codec->resume(cii); | ||
343 | if (err) | ||
344 | ret = err; | ||
345 | } | ||
346 | /* Notify Alsa */ | ||
347 | if (i2sdev->sound.pcm) { | ||
348 | /* Same comment as above, probably useless */ | ||
349 | snd_power_change_state(i2sdev->sound.pcm->card, | ||
350 | SNDRV_CTL_POWER_D0); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | return ret; | ||
355 | } | ||
356 | #endif /* CONFIG_PM */ | ||
357 | |||
358 | static int i2sbus_shutdown(struct macio_dev* dev) | ||
359 | { | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | static struct macio_driver i2sbus_drv = { | ||
364 | .name = "soundbus-i2s", | ||
365 | .owner = THIS_MODULE, | ||
366 | .match_table = i2sbus_match, | ||
367 | .probe = i2sbus_probe, | ||
368 | .remove = i2sbus_remove, | ||
369 | #ifdef CONFIG_PM | ||
370 | .suspend = i2sbus_suspend, | ||
371 | .resume = i2sbus_resume, | ||
372 | #endif | ||
373 | .shutdown = i2sbus_shutdown, | ||
374 | }; | ||
375 | |||
376 | static int __init soundbus_i2sbus_init(void) | ||
377 | { | ||
378 | return macio_register_driver(&i2sbus_drv); | ||
379 | } | ||
380 | |||
381 | static void __exit soundbus_i2sbus_exit(void) | ||
382 | { | ||
383 | macio_unregister_driver(&i2sbus_drv); | ||
384 | } | ||
385 | |||
386 | module_init(soundbus_i2sbus_init); | ||
387 | module_exit(soundbus_i2sbus_exit); | ||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h new file mode 100644 index 000000000000..c6b5f5452d20 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * i2sbus driver -- interface register definitions | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | #ifndef __I2SBUS_INTERFACE_H | ||
9 | #define __I2SBUS_INTERFACE_H | ||
10 | |||
11 | /* i2s bus control registers, at least what we know about them */ | ||
12 | |||
13 | #define __PAD(m,n) u8 __pad##m[n] | ||
14 | #define _PAD(line, n) __PAD(line, n) | ||
15 | #define PAD(n) _PAD(__LINE__, (n)) | ||
16 | struct i2s_interface_regs { | ||
17 | __le32 intr_ctl; /* 0x00 */ | ||
18 | PAD(12); | ||
19 | __le32 serial_format; /* 0x10 */ | ||
20 | PAD(12); | ||
21 | __le32 codec_msg_out; /* 0x20 */ | ||
22 | PAD(12); | ||
23 | __le32 codec_msg_in; /* 0x30 */ | ||
24 | PAD(12); | ||
25 | __le32 frame_count; /* 0x40 */ | ||
26 | PAD(12); | ||
27 | __le32 frame_match; /* 0x50 */ | ||
28 | PAD(12); | ||
29 | __le32 data_word_sizes; /* 0x60 */ | ||
30 | PAD(12); | ||
31 | __le32 peak_level_sel; /* 0x70 */ | ||
32 | PAD(12); | ||
33 | __le32 peak_level_in0; /* 0x80 */ | ||
34 | PAD(12); | ||
35 | __le32 peak_level_in1; /* 0x90 */ | ||
36 | PAD(12); | ||
37 | /* total size: 0x100 bytes */ | ||
38 | } __attribute__((__packed__)); | ||
39 | |||
40 | /* interrupt register is just a bitfield with | ||
41 | * interrupt enable and pending bits */ | ||
42 | #define I2S_REG_INTR_CTL 0x00 | ||
43 | # define I2S_INT_FRAME_COUNT (1<<31) | ||
44 | # define I2S_PENDING_FRAME_COUNT (1<<30) | ||
45 | # define I2S_INT_MESSAGE_FLAG (1<<29) | ||
46 | # define I2S_PENDING_MESSAGE_FLAG (1<<28) | ||
47 | # define I2S_INT_NEW_PEAK (1<<27) | ||
48 | # define I2S_PENDING_NEW_PEAK (1<<26) | ||
49 | # define I2S_INT_CLOCKS_STOPPED (1<<25) | ||
50 | # define I2S_PENDING_CLOCKS_STOPPED (1<<24) | ||
51 | # define I2S_INT_EXTERNAL_SYNC_ERROR (1<<23) | ||
52 | # define I2S_PENDING_EXTERNAL_SYNC_ERROR (1<<22) | ||
53 | # define I2S_INT_EXTERNAL_SYNC_OK (1<<21) | ||
54 | # define I2S_PENDING_EXTERNAL_SYNC_OK (1<<20) | ||
55 | # define I2S_INT_NEW_SAMPLE_RATE (1<<19) | ||
56 | # define I2S_PENDING_NEW_SAMPLE_RATE (1<<18) | ||
57 | # define I2S_INT_STATUS_FLAG (1<<17) | ||
58 | # define I2S_PENDING_STATUS_FLAG (1<<16) | ||
59 | |||
60 | /* serial format register is more interesting :) | ||
61 | * It contains: | ||
62 | * - clock source | ||
63 | * - MClk divisor | ||
64 | * - SClk divisor | ||
65 | * - SClk master flag | ||
66 | * - serial format (sony, i2s 64x, i2s 32x, dav, silabs) | ||
67 | * - external sample frequency interrupt (don't understand) | ||
68 | * - external sample frequency | ||
69 | */ | ||
70 | #define I2S_REG_SERIAL_FORMAT 0x10 | ||
71 | /* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */ | ||
72 | # define I2S_SF_CLOCK_SOURCE_SHIFT 30 | ||
73 | # define I2S_SF_CLOCK_SOURCE_MASK (3<<I2S_SF_CLOCK_SOURCE_SHIFT) | ||
74 | # define I2S_SF_CLOCK_SOURCE_18MHz (0<<I2S_SF_CLOCK_SOURCE_SHIFT) | ||
75 | # define I2S_SF_CLOCK_SOURCE_45MHz (1<<I2S_SF_CLOCK_SOURCE_SHIFT) | ||
76 | # define I2S_SF_CLOCK_SOURCE_49MHz (2<<I2S_SF_CLOCK_SOURCE_SHIFT) | ||
77 | /* also, let's define the exact clock speeds here, in Hz */ | ||
78 | #define I2S_CLOCK_SPEED_18MHz 18432000 | ||
79 | #define I2S_CLOCK_SPEED_45MHz 45158400 | ||
80 | #define I2S_CLOCK_SPEED_49MHz 49152000 | ||
81 | /* MClk is the clock that drives the codec, usually called its 'system clock'. | ||
82 | * It is derived by taking only every 'divisor' tick of the clock. | ||
83 | */ | ||
84 | # define I2S_SF_MCLKDIV_SHIFT 24 | ||
85 | # define I2S_SF_MCLKDIV_MASK (0x1F<<I2S_SF_MCLKDIV_SHIFT) | ||
86 | # define I2S_SF_MCLKDIV_1 (0x14<<I2S_SF_MCLKDIV_SHIFT) | ||
87 | # define I2S_SF_MCLKDIV_3 (0x13<<I2S_SF_MCLKDIV_SHIFT) | ||
88 | # define I2S_SF_MCLKDIV_5 (0x12<<I2S_SF_MCLKDIV_SHIFT) | ||
89 | # define I2S_SF_MCLKDIV_14 (0x0E<<I2S_SF_MCLKDIV_SHIFT) | ||
90 | # define I2S_SF_MCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK) | ||
91 | static inline int i2s_sf_mclkdiv(int div, int *out) | ||
92 | { | ||
93 | int d; | ||
94 | |||
95 | switch(div) { | ||
96 | case 1: *out |= I2S_SF_MCLKDIV_1; return 0; | ||
97 | case 3: *out |= I2S_SF_MCLKDIV_3; return 0; | ||
98 | case 5: *out |= I2S_SF_MCLKDIV_5; return 0; | ||
99 | case 14: *out |= I2S_SF_MCLKDIV_14; return 0; | ||
100 | default: | ||
101 | if (div%2) return -1; | ||
102 | d = div/2-1; | ||
103 | if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E) | ||
104 | return -1; | ||
105 | *out |= I2S_SF_MCLKDIV_OTHER(div); | ||
106 | return 0; | ||
107 | } | ||
108 | } | ||
109 | /* SClk is the clock that drives the i2s wire bus. Note that it is | ||
110 | * derived from the MClk above by taking only every 'divisor' tick | ||
111 | * of MClk. | ||
112 | */ | ||
113 | # define I2S_SF_SCLKDIV_SHIFT 20 | ||
114 | # define I2S_SF_SCLKDIV_MASK (0xF<<I2S_SF_SCLKDIV_SHIFT) | ||
115 | # define I2S_SF_SCLKDIV_1 (8<<I2S_SF_SCLKDIV_SHIFT) | ||
116 | # define I2S_SF_SCLKDIV_3 (9<<I2S_SF_SCLKDIV_SHIFT) | ||
117 | # define I2S_SF_SCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK) | ||
118 | static inline int i2s_sf_sclkdiv(int div, int *out) | ||
119 | { | ||
120 | int d; | ||
121 | |||
122 | switch(div) { | ||
123 | case 1: *out |= I2S_SF_SCLKDIV_1; return 0; | ||
124 | case 3: *out |= I2S_SF_SCLKDIV_3; return 0; | ||
125 | default: | ||
126 | if (div%2) return -1; | ||
127 | d = div/2-1; | ||
128 | if (d == 8 || d == 9) return -1; | ||
129 | *out |= I2S_SF_SCLKDIV_OTHER(div); | ||
130 | return 0; | ||
131 | } | ||
132 | } | ||
133 | # define I2S_SF_SCLK_MASTER (1<<19) | ||
134 | /* serial format is the way the data is put to the i2s wire bus */ | ||
135 | # define I2S_SF_SERIAL_FORMAT_SHIFT 16 | ||
136 | # define I2S_SF_SERIAL_FORMAT_MASK (7<<I2S_SF_SERIAL_FORMAT_SHIFT) | ||
137 | # define I2S_SF_SERIAL_FORMAT_SONY (0<<I2S_SF_SERIAL_FORMAT_SHIFT) | ||
138 | # define I2S_SF_SERIAL_FORMAT_I2S_64X (1<<I2S_SF_SERIAL_FORMAT_SHIFT) | ||
139 | # define I2S_SF_SERIAL_FORMAT_I2S_32X (2<<I2S_SF_SERIAL_FORMAT_SHIFT) | ||
140 | # define I2S_SF_SERIAL_FORMAT_I2S_DAV (4<<I2S_SF_SERIAL_FORMAT_SHIFT) | ||
141 | # define I2S_SF_SERIAL_FORMAT_I2S_SILABS (5<<I2S_SF_SERIAL_FORMAT_SHIFT) | ||
142 | /* unknown */ | ||
143 | # define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT 12 | ||
144 | # define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK (0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT) | ||
145 | /* probably gives external frequency? */ | ||
146 | # define I2S_SF_EXT_SAMPLE_FREQ_MASK 0xFFF | ||
147 | |||
148 | /* used to send codec messages, but how isn't clear */ | ||
149 | #define I2S_REG_CODEC_MSG_OUT 0x20 | ||
150 | |||
151 | /* used to receive codec messages, but how isn't clear */ | ||
152 | #define I2S_REG_CODEC_MSG_IN 0x30 | ||
153 | |||
154 | /* frame count reg isn't clear to me yet, but probably useful */ | ||
155 | #define I2S_REG_FRAME_COUNT 0x40 | ||
156 | |||
157 | /* program to some value, and get interrupt if frame count reaches it */ | ||
158 | #define I2S_REG_FRAME_MATCH 0x50 | ||
159 | |||
160 | /* this register describes how the bus transfers data */ | ||
161 | #define I2S_REG_DATA_WORD_SIZES 0x60 | ||
162 | /* number of interleaved input channels */ | ||
163 | # define I2S_DWS_NUM_CHANNELS_IN_SHIFT 24 | ||
164 | # define I2S_DWS_NUM_CHANNELS_IN_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT) | ||
165 | /* word size of input data */ | ||
166 | # define I2S_DWS_DATA_IN_SIZE_SHIFT 16 | ||
167 | # define I2S_DWS_DATA_IN_16BIT (0<<I2S_DWS_DATA_IN_SIZE_SHIFT) | ||
168 | # define I2S_DWS_DATA_IN_24BIT (3<<I2S_DWS_DATA_IN_SIZE_SHIFT) | ||
169 | /* number of interleaved output channels */ | ||
170 | # define I2S_DWS_NUM_CHANNELS_OUT_SHIFT 8 | ||
171 | # define I2S_DWS_NUM_CHANNELS_OUT_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | ||
172 | /* word size of output data */ | ||
173 | # define I2S_DWS_DATA_OUT_SIZE_SHIFT 0 | ||
174 | # define I2S_DWS_DATA_OUT_16BIT (0<<I2S_DWS_DATA_OUT_SIZE_SHIFT) | ||
175 | # define I2S_DWS_DATA_OUT_24BIT (3<<I2S_DWS_DATA_OUT_SIZE_SHIFT) | ||
176 | |||
177 | |||
178 | /* unknown */ | ||
179 | #define I2S_REG_PEAK_LEVEL_SEL 0x70 | ||
180 | |||
181 | /* unknown */ | ||
182 | #define I2S_REG_PEAK_LEVEL_IN0 0x80 | ||
183 | |||
184 | /* unknown */ | ||
185 | #define I2S_REG_PEAK_LEVEL_IN1 0x90 | ||
186 | |||
187 | #endif /* __I2SBUS_INTERFACE_H */ | ||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c new file mode 100644 index 000000000000..3049015a04f1 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c | |||
@@ -0,0 +1,1021 @@ | |||
1 | /* | ||
2 | * i2sbus driver -- pcm routines | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | |||
9 | #include <asm/io.h> | ||
10 | #include <linux/delay.h> | ||
11 | /* So apparently there's a reason for requiring driver.h | ||
12 | * to be included first, even if I don't know it... */ | ||
13 | #include <sound/driver.h> | ||
14 | #include <sound/core.h> | ||
15 | #include <asm/macio.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include "../soundbus.h" | ||
18 | #include "i2sbus.h" | ||
19 | |||
20 | static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in, | ||
21 | struct pcm_info **pi, struct pcm_info **other) | ||
22 | { | ||
23 | if (in) { | ||
24 | if (pi) | ||
25 | *pi = &i2sdev->in; | ||
26 | if (other) | ||
27 | *other = &i2sdev->out; | ||
28 | } else { | ||
29 | if (pi) | ||
30 | *pi = &i2sdev->out; | ||
31 | if (other) | ||
32 | *other = &i2sdev->in; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | static int clock_and_divisors(int mclk, int sclk, int rate, int *out) | ||
37 | { | ||
38 | /* sclk must be derived from mclk! */ | ||
39 | if (mclk % sclk) | ||
40 | return -1; | ||
41 | /* derive sclk register value */ | ||
42 | if (i2s_sf_sclkdiv(mclk / sclk, out)) | ||
43 | return -1; | ||
44 | |||
45 | if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) { | ||
46 | if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) { | ||
47 | *out |= I2S_SF_CLOCK_SOURCE_18MHz; | ||
48 | return 0; | ||
49 | } | ||
50 | } | ||
51 | if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) { | ||
52 | if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) { | ||
53 | *out |= I2S_SF_CLOCK_SOURCE_45MHz; | ||
54 | return 0; | ||
55 | } | ||
56 | } | ||
57 | if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) { | ||
58 | if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) { | ||
59 | *out |= I2S_SF_CLOCK_SOURCE_49MHz; | ||
60 | return 0; | ||
61 | } | ||
62 | } | ||
63 | return -1; | ||
64 | } | ||
65 | |||
66 | #define CHECK_RATE(rate) \ | ||
67 | do { if (rates & SNDRV_PCM_RATE_ ##rate) { \ | ||
68 | int dummy; \ | ||
69 | if (clock_and_divisors(sysclock_factor, \ | ||
70 | bus_factor, rate, &dummy)) \ | ||
71 | rates &= ~SNDRV_PCM_RATE_ ##rate; \ | ||
72 | } } while (0) | ||
73 | |||
74 | static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) | ||
75 | { | ||
76 | struct pcm_info *pi, *other; | ||
77 | struct soundbus_dev *sdev; | ||
78 | int masks_inited = 0, err; | ||
79 | struct codec_info_item *cii, *rev; | ||
80 | struct snd_pcm_hardware *hw; | ||
81 | u64 formats = 0; | ||
82 | unsigned int rates = 0; | ||
83 | struct transfer_info v; | ||
84 | int result = 0; | ||
85 | int bus_factor = 0, sysclock_factor = 0; | ||
86 | int found_this; | ||
87 | |||
88 | mutex_lock(&i2sdev->lock); | ||
89 | |||
90 | get_pcm_info(i2sdev, in, &pi, &other); | ||
91 | |||
92 | hw = &pi->substream->runtime->hw; | ||
93 | sdev = &i2sdev->sound; | ||
94 | |||
95 | if (pi->active) { | ||
96 | /* alsa messed up */ | ||
97 | result = -EBUSY; | ||
98 | goto out_unlock; | ||
99 | } | ||
100 | |||
101 | /* we now need to assign the hw */ | ||
102 | list_for_each_entry(cii, &sdev->codec_list, list) { | ||
103 | struct transfer_info *ti = cii->codec->transfers; | ||
104 | bus_factor = cii->codec->bus_factor; | ||
105 | sysclock_factor = cii->codec->sysclock_factor; | ||
106 | while (ti->formats && ti->rates) { | ||
107 | v = *ti; | ||
108 | if (ti->transfer_in == in | ||
109 | && cii->codec->usable(cii, ti, &v)) { | ||
110 | if (masks_inited) { | ||
111 | formats &= v.formats; | ||
112 | rates &= v.rates; | ||
113 | } else { | ||
114 | formats = v.formats; | ||
115 | rates = v.rates; | ||
116 | masks_inited = 1; | ||
117 | } | ||
118 | } | ||
119 | ti++; | ||
120 | } | ||
121 | } | ||
122 | if (!masks_inited || !bus_factor || !sysclock_factor) { | ||
123 | result = -ENODEV; | ||
124 | goto out_unlock; | ||
125 | } | ||
126 | /* bus dependent stuff */ | ||
127 | hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | ||
128 | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME; | ||
129 | |||
130 | CHECK_RATE(5512); | ||
131 | CHECK_RATE(8000); | ||
132 | CHECK_RATE(11025); | ||
133 | CHECK_RATE(16000); | ||
134 | CHECK_RATE(22050); | ||
135 | CHECK_RATE(32000); | ||
136 | CHECK_RATE(44100); | ||
137 | CHECK_RATE(48000); | ||
138 | CHECK_RATE(64000); | ||
139 | CHECK_RATE(88200); | ||
140 | CHECK_RATE(96000); | ||
141 | CHECK_RATE(176400); | ||
142 | CHECK_RATE(192000); | ||
143 | hw->rates = rates; | ||
144 | |||
145 | /* well. the codec might want 24 bits only, and we'll | ||
146 | * ever only transfer 24 bits, but they are top-aligned! | ||
147 | * So for alsa, we claim that we're doing full 32 bit | ||
148 | * while in reality we'll ignore the lower 8 bits of | ||
149 | * that when doing playback (they're transferred as 0 | ||
150 | * as far as I know, no codecs we have are 32-bit capable | ||
151 | * so I can't really test) and when doing recording we'll | ||
152 | * always have those lower 8 bits recorded as 0 */ | ||
153 | if (formats & SNDRV_PCM_FMTBIT_S24_BE) | ||
154 | formats |= SNDRV_PCM_FMTBIT_S32_BE; | ||
155 | if (formats & SNDRV_PCM_FMTBIT_U24_BE) | ||
156 | formats |= SNDRV_PCM_FMTBIT_U32_BE; | ||
157 | /* now mask off what we can support. I suppose we could | ||
158 | * also support S24_3LE and some similar formats, but I | ||
159 | * doubt there's a codec that would be able to use that, | ||
160 | * so we don't support it here. */ | ||
161 | hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE | | ||
162 | SNDRV_PCM_FMTBIT_U16_BE | | ||
163 | SNDRV_PCM_FMTBIT_S32_BE | | ||
164 | SNDRV_PCM_FMTBIT_U32_BE); | ||
165 | |||
166 | /* we need to set the highest and lowest rate possible. | ||
167 | * These are the highest and lowest rates alsa can | ||
168 | * support properly in its bitfield. | ||
169 | * Below, we'll use that to restrict to the rate | ||
170 | * currently in use (if any). */ | ||
171 | hw->rate_min = 5512; | ||
172 | hw->rate_max = 192000; | ||
173 | /* if the other stream is active, then we can only | ||
174 | * support what it is currently using. | ||
175 | * FIXME: I lied. This comment is wrong. We can support | ||
176 | * anything that works with the same serial format, ie. | ||
177 | * when recording 24 bit sound we can well play 16 bit | ||
178 | * sound at the same time iff using the same transfer mode. | ||
179 | */ | ||
180 | if (other->active) { | ||
181 | /* FIXME: is this guaranteed by the alsa api? */ | ||
182 | hw->formats &= (1ULL << i2sdev->format); | ||
183 | /* see above, restrict rates to the one we already have */ | ||
184 | hw->rate_min = i2sdev->rate; | ||
185 | hw->rate_max = i2sdev->rate; | ||
186 | } | ||
187 | |||
188 | hw->channels_min = 2; | ||
189 | hw->channels_max = 2; | ||
190 | /* these are somewhat arbitrary */ | ||
191 | hw->buffer_bytes_max = 131072; | ||
192 | hw->period_bytes_min = 256; | ||
193 | hw->period_bytes_max = 16384; | ||
194 | hw->periods_min = 3; | ||
195 | hw->periods_max = MAX_DBDMA_COMMANDS; | ||
196 | list_for_each_entry(cii, &sdev->codec_list, list) { | ||
197 | if (cii->codec->open) { | ||
198 | err = cii->codec->open(cii, pi->substream); | ||
199 | if (err) { | ||
200 | result = err; | ||
201 | /* unwind */ | ||
202 | found_this = 0; | ||
203 | list_for_each_entry_reverse(rev, | ||
204 | &sdev->codec_list, list) { | ||
205 | if (found_this && rev->codec->close) { | ||
206 | rev->codec->close(rev, | ||
207 | pi->substream); | ||
208 | } | ||
209 | if (rev == cii) | ||
210 | found_this = 1; | ||
211 | } | ||
212 | goto out_unlock; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | out_unlock: | ||
218 | mutex_unlock(&i2sdev->lock); | ||
219 | return result; | ||
220 | } | ||
221 | |||
222 | #undef CHECK_RATE | ||
223 | |||
224 | static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) | ||
225 | { | ||
226 | struct codec_info_item *cii; | ||
227 | struct pcm_info *pi; | ||
228 | int err = 0, tmp; | ||
229 | |||
230 | mutex_lock(&i2sdev->lock); | ||
231 | |||
232 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
233 | |||
234 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
235 | if (cii->codec->close) { | ||
236 | tmp = cii->codec->close(cii, pi->substream); | ||
237 | if (tmp) | ||
238 | err = tmp; | ||
239 | } | ||
240 | } | ||
241 | |||
242 | pi->substream = NULL; | ||
243 | pi->active = 0; | ||
244 | mutex_unlock(&i2sdev->lock); | ||
245 | return err; | ||
246 | } | ||
247 | |||
248 | static int i2sbus_hw_params(struct snd_pcm_substream *substream, | ||
249 | struct snd_pcm_hw_params *params) | ||
250 | { | ||
251 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
252 | } | ||
253 | |||
254 | static int i2sbus_hw_free(struct snd_pcm_substream *substream) | ||
255 | { | ||
256 | snd_pcm_lib_free_pages(substream); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) | ||
261 | { | ||
262 | /* whee. Hard work now. The user has selected a bitrate | ||
263 | * and bit format, so now we have to program our | ||
264 | * I2S controller appropriately. */ | ||
265 | struct snd_pcm_runtime *runtime; | ||
266 | struct dbdma_cmd *command; | ||
267 | int i, periodsize; | ||
268 | dma_addr_t offset; | ||
269 | struct bus_info bi; | ||
270 | struct codec_info_item *cii; | ||
271 | int sfr = 0; /* serial format register */ | ||
272 | int dws = 0; /* data word sizes reg */ | ||
273 | int input_16bit; | ||
274 | struct pcm_info *pi, *other; | ||
275 | int cnt; | ||
276 | int result = 0; | ||
277 | |||
278 | mutex_lock(&i2sdev->lock); | ||
279 | |||
280 | get_pcm_info(i2sdev, in, &pi, &other); | ||
281 | |||
282 | if (pi->dbdma_ring.running) { | ||
283 | result = -EBUSY; | ||
284 | goto out_unlock; | ||
285 | } | ||
286 | |||
287 | runtime = pi->substream->runtime; | ||
288 | pi->active = 1; | ||
289 | if (other->active && | ||
290 | ((i2sdev->format != runtime->format) | ||
291 | || (i2sdev->rate != runtime->rate))) { | ||
292 | result = -EINVAL; | ||
293 | goto out_unlock; | ||
294 | } | ||
295 | |||
296 | i2sdev->format = runtime->format; | ||
297 | i2sdev->rate = runtime->rate; | ||
298 | |||
299 | periodsize = snd_pcm_lib_period_bytes(pi->substream); | ||
300 | pi->current_period = 0; | ||
301 | |||
302 | /* generate dbdma command ring first */ | ||
303 | command = pi->dbdma_ring.cmds; | ||
304 | offset = runtime->dma_addr; | ||
305 | for (i = 0; i < pi->substream->runtime->periods; | ||
306 | i++, command++, offset += periodsize) { | ||
307 | memset(command, 0, sizeof(struct dbdma_cmd)); | ||
308 | command->command = | ||
309 | cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS); | ||
310 | command->phy_addr = cpu_to_le32(offset); | ||
311 | command->req_count = cpu_to_le16(periodsize); | ||
312 | command->xfer_status = cpu_to_le16(0); | ||
313 | } | ||
314 | /* last one branches back to first */ | ||
315 | command--; | ||
316 | command->command |= cpu_to_le16(BR_ALWAYS); | ||
317 | command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start); | ||
318 | |||
319 | /* ok, let's set the serial format and stuff */ | ||
320 | switch (runtime->format) { | ||
321 | /* 16 bit formats */ | ||
322 | case SNDRV_PCM_FORMAT_S16_BE: | ||
323 | case SNDRV_PCM_FORMAT_U16_BE: | ||
324 | /* FIXME: if we add different bus factors we need to | ||
325 | * do more here!! */ | ||
326 | bi.bus_factor = 0; | ||
327 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
328 | bi.bus_factor = cii->codec->bus_factor; | ||
329 | break; | ||
330 | } | ||
331 | if (!bi.bus_factor) { | ||
332 | result = -ENODEV; | ||
333 | goto out_unlock; | ||
334 | } | ||
335 | input_16bit = 1; | ||
336 | break; | ||
337 | case SNDRV_PCM_FORMAT_S32_BE: | ||
338 | case SNDRV_PCM_FORMAT_U32_BE: | ||
339 | /* force 64x bus speed, otherwise the data cannot be | ||
340 | * transferred quickly enough! */ | ||
341 | bi.bus_factor = 64; | ||
342 | input_16bit = 0; | ||
343 | break; | ||
344 | default: | ||
345 | result = -EINVAL; | ||
346 | goto out_unlock; | ||
347 | } | ||
348 | /* we assume all sysclocks are the same! */ | ||
349 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
350 | bi.sysclock_factor = cii->codec->sysclock_factor; | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | if (clock_and_divisors(bi.sysclock_factor, | ||
355 | bi.bus_factor, | ||
356 | runtime->rate, | ||
357 | &sfr) < 0) { | ||
358 | result = -EINVAL; | ||
359 | goto out_unlock; | ||
360 | } | ||
361 | switch (bi.bus_factor) { | ||
362 | case 32: | ||
363 | sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; | ||
364 | break; | ||
365 | case 64: | ||
366 | sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X; | ||
367 | break; | ||
368 | } | ||
369 | /* FIXME: THIS ASSUMES MASTER ALL THE TIME */ | ||
370 | sfr |= I2S_SF_SCLK_MASTER; | ||
371 | |||
372 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { | ||
373 | int err = 0; | ||
374 | if (cii->codec->prepare) | ||
375 | err = cii->codec->prepare(cii, &bi, pi->substream); | ||
376 | if (err) { | ||
377 | result = err; | ||
378 | goto out_unlock; | ||
379 | } | ||
380 | } | ||
381 | /* codecs are fine with it, so set our clocks */ | ||
382 | if (input_16bit) | ||
383 | dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | | ||
384 | (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | | ||
385 | I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT; | ||
386 | else | ||
387 | dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | | ||
388 | (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | | ||
389 | I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT; | ||
390 | |||
391 | /* early exit if already programmed correctly */ | ||
392 | /* not locking these is fine since we touch them only in this function */ | ||
393 | if (in_le32(&i2sdev->intfregs->serial_format) == sfr | ||
394 | && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) | ||
395 | goto out_unlock; | ||
396 | |||
397 | /* let's notify the codecs about clocks going away. | ||
398 | * For now we only do mastering on the i2s cell... */ | ||
399 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
400 | if (cii->codec->switch_clock) | ||
401 | cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE); | ||
402 | |||
403 | i2sbus_control_enable(i2sdev->control, i2sdev); | ||
404 | i2sbus_control_cell(i2sdev->control, i2sdev, 1); | ||
405 | |||
406 | out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); | ||
407 | |||
408 | i2sbus_control_clock(i2sdev->control, i2sdev, 0); | ||
409 | |||
410 | msleep(1); | ||
411 | |||
412 | /* wait for clock stopped. This can apparently take a while... */ | ||
413 | cnt = 100; | ||
414 | while (cnt-- && | ||
415 | !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) { | ||
416 | msleep(5); | ||
417 | } | ||
418 | out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); | ||
419 | |||
420 | /* not locking these is fine since we touch them only in this function */ | ||
421 | out_le32(&i2sdev->intfregs->serial_format, sfr); | ||
422 | out_le32(&i2sdev->intfregs->data_word_sizes, dws); | ||
423 | |||
424 | i2sbus_control_enable(i2sdev->control, i2sdev); | ||
425 | i2sbus_control_cell(i2sdev->control, i2sdev, 1); | ||
426 | i2sbus_control_clock(i2sdev->control, i2sdev, 1); | ||
427 | msleep(1); | ||
428 | |||
429 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
430 | if (cii->codec->switch_clock) | ||
431 | cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); | ||
432 | |||
433 | out_unlock: | ||
434 | mutex_unlock(&i2sdev->lock); | ||
435 | return result; | ||
436 | } | ||
437 | |||
438 | static struct dbdma_cmd STOP_CMD = { | ||
439 | .command = __constant_cpu_to_le16(DBDMA_STOP), | ||
440 | }; | ||
441 | |||
442 | static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) | ||
443 | { | ||
444 | struct codec_info_item *cii; | ||
445 | struct pcm_info *pi; | ||
446 | int timeout; | ||
447 | struct dbdma_cmd tmp; | ||
448 | int result = 0; | ||
449 | unsigned long flags; | ||
450 | |||
451 | spin_lock_irqsave(&i2sdev->low_lock, flags); | ||
452 | |||
453 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
454 | |||
455 | switch (cmd) { | ||
456 | case SNDRV_PCM_TRIGGER_START: | ||
457 | case SNDRV_PCM_TRIGGER_RESUME: | ||
458 | if (pi->dbdma_ring.running) { | ||
459 | result = -EALREADY; | ||
460 | goto out_unlock; | ||
461 | } | ||
462 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
463 | if (cii->codec->start) | ||
464 | cii->codec->start(cii, pi->substream); | ||
465 | pi->dbdma_ring.running = 1; | ||
466 | |||
467 | /* reset dma engine */ | ||
468 | out_le32(&pi->dbdma->control, | ||
469 | 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); | ||
470 | timeout = 100; | ||
471 | while (in_le32(&pi->dbdma->status) & RUN && timeout--) | ||
472 | udelay(1); | ||
473 | if (timeout <= 0) { | ||
474 | printk(KERN_ERR | ||
475 | "i2sbus: error waiting for dma reset\n"); | ||
476 | result = -ENXIO; | ||
477 | goto out_unlock; | ||
478 | } | ||
479 | |||
480 | /* write dma command buffer address to the dbdma chip */ | ||
481 | out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); | ||
482 | /* post PCI write */ | ||
483 | mb(); | ||
484 | (void)in_le32(&pi->dbdma->status); | ||
485 | |||
486 | /* change first command to STOP */ | ||
487 | tmp = *pi->dbdma_ring.cmds; | ||
488 | *pi->dbdma_ring.cmds = STOP_CMD; | ||
489 | |||
490 | /* set running state, remember that the first command is STOP */ | ||
491 | out_le32(&pi->dbdma->control, RUN | (RUN << 16)); | ||
492 | timeout = 100; | ||
493 | /* wait for STOP to be executed */ | ||
494 | while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--) | ||
495 | udelay(1); | ||
496 | if (timeout <= 0) { | ||
497 | printk(KERN_ERR "i2sbus: error waiting for dma stop\n"); | ||
498 | result = -ENXIO; | ||
499 | goto out_unlock; | ||
500 | } | ||
501 | /* again, write dma command buffer address to the dbdma chip, | ||
502 | * this time of the first real command */ | ||
503 | *pi->dbdma_ring.cmds = tmp; | ||
504 | out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); | ||
505 | /* post write */ | ||
506 | mb(); | ||
507 | (void)in_le32(&pi->dbdma->status); | ||
508 | |||
509 | /* reset dma engine again */ | ||
510 | out_le32(&pi->dbdma->control, | ||
511 | 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); | ||
512 | timeout = 100; | ||
513 | while (in_le32(&pi->dbdma->status) & RUN && timeout--) | ||
514 | udelay(1); | ||
515 | if (timeout <= 0) { | ||
516 | printk(KERN_ERR | ||
517 | "i2sbus: error waiting for dma reset\n"); | ||
518 | result = -ENXIO; | ||
519 | goto out_unlock; | ||
520 | } | ||
521 | |||
522 | /* wake up the chip with the next descriptor */ | ||
523 | out_le32(&pi->dbdma->control, | ||
524 | (RUN | WAKE) | ((RUN | WAKE) << 16)); | ||
525 | /* get the frame count */ | ||
526 | pi->frame_count = in_le32(&i2sdev->intfregs->frame_count); | ||
527 | |||
528 | /* off you go! */ | ||
529 | break; | ||
530 | case SNDRV_PCM_TRIGGER_STOP: | ||
531 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
532 | if (!pi->dbdma_ring.running) { | ||
533 | result = -EALREADY; | ||
534 | goto out_unlock; | ||
535 | } | ||
536 | |||
537 | /* turn off all relevant bits */ | ||
538 | out_le32(&pi->dbdma->control, | ||
539 | (RUN | WAKE | FLUSH | PAUSE) << 16); | ||
540 | { | ||
541 | /* FIXME: move to own function */ | ||
542 | int timeout = 5000; | ||
543 | while ((in_le32(&pi->dbdma->status) & RUN) | ||
544 | && --timeout > 0) | ||
545 | udelay(1); | ||
546 | if (!timeout) | ||
547 | printk(KERN_ERR | ||
548 | "i2sbus: timed out turning " | ||
549 | "off dbdma engine!\n"); | ||
550 | } | ||
551 | |||
552 | pi->dbdma_ring.running = 0; | ||
553 | list_for_each_entry(cii, &i2sdev->sound.codec_list, list) | ||
554 | if (cii->codec->stop) | ||
555 | cii->codec->stop(cii, pi->substream); | ||
556 | break; | ||
557 | default: | ||
558 | result = -EINVAL; | ||
559 | goto out_unlock; | ||
560 | } | ||
561 | |||
562 | out_unlock: | ||
563 | spin_unlock_irqrestore(&i2sdev->low_lock, flags); | ||
564 | return result; | ||
565 | } | ||
566 | |||
567 | static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in) | ||
568 | { | ||
569 | struct pcm_info *pi; | ||
570 | u32 fc; | ||
571 | |||
572 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
573 | |||
574 | fc = in_le32(&i2sdev->intfregs->frame_count); | ||
575 | fc = fc - pi->frame_count; | ||
576 | |||
577 | return (bytes_to_frames(pi->substream->runtime, | ||
578 | pi->current_period * | ||
579 | snd_pcm_lib_period_bytes(pi->substream)) | ||
580 | + fc) % pi->substream->runtime->buffer_size; | ||
581 | } | ||
582 | |||
583 | static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) | ||
584 | { | ||
585 | struct pcm_info *pi; | ||
586 | u32 fc; | ||
587 | u32 delta; | ||
588 | |||
589 | spin_lock(&i2sdev->low_lock); | ||
590 | get_pcm_info(i2sdev, in, &pi, NULL); | ||
591 | |||
592 | if (!pi->dbdma_ring.running) { | ||
593 | /* there was still an interrupt pending | ||
594 | * while we stopped. or maybe another | ||
595 | * processor (not the one that was stopping | ||
596 | * the DMA engine) was spinning above | ||
597 | * waiting for the lock. */ | ||
598 | goto out_unlock; | ||
599 | } | ||
600 | |||
601 | fc = in_le32(&i2sdev->intfregs->frame_count); | ||
602 | /* a counter overflow does not change the calculation. */ | ||
603 | delta = fc - pi->frame_count; | ||
604 | |||
605 | /* update current_period */ | ||
606 | while (delta >= pi->substream->runtime->period_size) { | ||
607 | pi->current_period++; | ||
608 | delta = delta - pi->substream->runtime->period_size; | ||
609 | } | ||
610 | |||
611 | if (unlikely(delta)) { | ||
612 | /* Some interrupt came late, so check the dbdma. | ||
613 | * This special case exists to syncronize the frame_count with | ||
614 | * the dbdma transfer, but is hit every once in a while. */ | ||
615 | int period; | ||
616 | |||
617 | period = (in_le32(&pi->dbdma->cmdptr) | ||
618 | - pi->dbdma_ring.bus_cmd_start) | ||
619 | / sizeof(struct dbdma_cmd); | ||
620 | pi->current_period = pi->current_period | ||
621 | % pi->substream->runtime->periods; | ||
622 | |||
623 | while (pi->current_period != period) { | ||
624 | pi->current_period++; | ||
625 | pi->current_period %= pi->substream->runtime->periods; | ||
626 | /* Set delta to zero, as the frame_count value is too | ||
627 | * high (otherwise the code path will not be executed). | ||
628 | * This corrects the fact that the frame_count is too | ||
629 | * low at the beginning due to buffering. */ | ||
630 | delta = 0; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | pi->frame_count = fc - delta; | ||
635 | pi->current_period %= pi->substream->runtime->periods; | ||
636 | |||
637 | spin_unlock(&i2sdev->low_lock); | ||
638 | /* may call _trigger again, hence needs to be unlocked */ | ||
639 | snd_pcm_period_elapsed(pi->substream); | ||
640 | return; | ||
641 | out_unlock: | ||
642 | spin_unlock(&i2sdev->low_lock); | ||
643 | } | ||
644 | |||
645 | irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs) | ||
646 | { | ||
647 | handle_interrupt((struct i2sbus_dev *)devid, 0); | ||
648 | return IRQ_HANDLED; | ||
649 | } | ||
650 | |||
651 | irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs) | ||
652 | { | ||
653 | handle_interrupt((struct i2sbus_dev *)devid, 1); | ||
654 | return IRQ_HANDLED; | ||
655 | } | ||
656 | |||
657 | static int i2sbus_playback_open(struct snd_pcm_substream *substream) | ||
658 | { | ||
659 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
660 | |||
661 | if (!i2sdev) | ||
662 | return -EINVAL; | ||
663 | i2sdev->out.substream = substream; | ||
664 | return i2sbus_pcm_open(i2sdev, 0); | ||
665 | } | ||
666 | |||
667 | static int i2sbus_playback_close(struct snd_pcm_substream *substream) | ||
668 | { | ||
669 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
670 | int err; | ||
671 | |||
672 | if (!i2sdev) | ||
673 | return -EINVAL; | ||
674 | if (i2sdev->out.substream != substream) | ||
675 | return -EINVAL; | ||
676 | err = i2sbus_pcm_close(i2sdev, 0); | ||
677 | if (!err) | ||
678 | i2sdev->out.substream = NULL; | ||
679 | return err; | ||
680 | } | ||
681 | |||
682 | static int i2sbus_playback_prepare(struct snd_pcm_substream *substream) | ||
683 | { | ||
684 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
685 | |||
686 | if (!i2sdev) | ||
687 | return -EINVAL; | ||
688 | if (i2sdev->out.substream != substream) | ||
689 | return -EINVAL; | ||
690 | return i2sbus_pcm_prepare(i2sdev, 0); | ||
691 | } | ||
692 | |||
693 | static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd) | ||
694 | { | ||
695 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
696 | |||
697 | if (!i2sdev) | ||
698 | return -EINVAL; | ||
699 | if (i2sdev->out.substream != substream) | ||
700 | return -EINVAL; | ||
701 | return i2sbus_pcm_trigger(i2sdev, 0, cmd); | ||
702 | } | ||
703 | |||
704 | static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream | ||
705 | *substream) | ||
706 | { | ||
707 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
708 | |||
709 | if (!i2sdev) | ||
710 | return -EINVAL; | ||
711 | if (i2sdev->out.substream != substream) | ||
712 | return 0; | ||
713 | return i2sbus_pcm_pointer(i2sdev, 0); | ||
714 | } | ||
715 | |||
716 | static struct snd_pcm_ops i2sbus_playback_ops = { | ||
717 | .open = i2sbus_playback_open, | ||
718 | .close = i2sbus_playback_close, | ||
719 | .ioctl = snd_pcm_lib_ioctl, | ||
720 | .hw_params = i2sbus_hw_params, | ||
721 | .hw_free = i2sbus_hw_free, | ||
722 | .prepare = i2sbus_playback_prepare, | ||
723 | .trigger = i2sbus_playback_trigger, | ||
724 | .pointer = i2sbus_playback_pointer, | ||
725 | }; | ||
726 | |||
727 | static int i2sbus_record_open(struct snd_pcm_substream *substream) | ||
728 | { | ||
729 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
730 | |||
731 | if (!i2sdev) | ||
732 | return -EINVAL; | ||
733 | i2sdev->in.substream = substream; | ||
734 | return i2sbus_pcm_open(i2sdev, 1); | ||
735 | } | ||
736 | |||
737 | static int i2sbus_record_close(struct snd_pcm_substream *substream) | ||
738 | { | ||
739 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
740 | int err; | ||
741 | |||
742 | if (!i2sdev) | ||
743 | return -EINVAL; | ||
744 | if (i2sdev->in.substream != substream) | ||
745 | return -EINVAL; | ||
746 | err = i2sbus_pcm_close(i2sdev, 1); | ||
747 | if (!err) | ||
748 | i2sdev->in.substream = NULL; | ||
749 | return err; | ||
750 | } | ||
751 | |||
752 | static int i2sbus_record_prepare(struct snd_pcm_substream *substream) | ||
753 | { | ||
754 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
755 | |||
756 | if (!i2sdev) | ||
757 | return -EINVAL; | ||
758 | if (i2sdev->in.substream != substream) | ||
759 | return -EINVAL; | ||
760 | return i2sbus_pcm_prepare(i2sdev, 1); | ||
761 | } | ||
762 | |||
763 | static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd) | ||
764 | { | ||
765 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
766 | |||
767 | if (!i2sdev) | ||
768 | return -EINVAL; | ||
769 | if (i2sdev->in.substream != substream) | ||
770 | return -EINVAL; | ||
771 | return i2sbus_pcm_trigger(i2sdev, 1, cmd); | ||
772 | } | ||
773 | |||
774 | static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream | ||
775 | *substream) | ||
776 | { | ||
777 | struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); | ||
778 | |||
779 | if (!i2sdev) | ||
780 | return -EINVAL; | ||
781 | if (i2sdev->in.substream != substream) | ||
782 | return 0; | ||
783 | return i2sbus_pcm_pointer(i2sdev, 1); | ||
784 | } | ||
785 | |||
786 | static struct snd_pcm_ops i2sbus_record_ops = { | ||
787 | .open = i2sbus_record_open, | ||
788 | .close = i2sbus_record_close, | ||
789 | .ioctl = snd_pcm_lib_ioctl, | ||
790 | .hw_params = i2sbus_hw_params, | ||
791 | .hw_free = i2sbus_hw_free, | ||
792 | .prepare = i2sbus_record_prepare, | ||
793 | .trigger = i2sbus_record_trigger, | ||
794 | .pointer = i2sbus_record_pointer, | ||
795 | }; | ||
796 | |||
797 | static void i2sbus_private_free(struct snd_pcm *pcm) | ||
798 | { | ||
799 | struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm); | ||
800 | struct codec_info_item *p, *tmp; | ||
801 | |||
802 | i2sdev->sound.pcm = NULL; | ||
803 | i2sdev->out.created = 0; | ||
804 | i2sdev->in.created = 0; | ||
805 | list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) { | ||
806 | printk(KERN_ERR "i2sbus: a codec didn't unregister!\n"); | ||
807 | list_del(&p->list); | ||
808 | module_put(p->codec->owner); | ||
809 | kfree(p); | ||
810 | } | ||
811 | soundbus_dev_put(&i2sdev->sound); | ||
812 | module_put(THIS_MODULE); | ||
813 | } | ||
814 | |||
815 | /* FIXME: this function needs an error handling strategy with labels */ | ||
816 | int | ||
817 | i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, | ||
818 | struct codec_info *ci, void *data) | ||
819 | { | ||
820 | int err, in = 0, out = 0; | ||
821 | struct transfer_info *tmp; | ||
822 | struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev); | ||
823 | struct codec_info_item *cii; | ||
824 | |||
825 | if (!dev->pcmname || dev->pcmid == -1) { | ||
826 | printk(KERN_ERR "i2sbus: pcm name and id must be set!\n"); | ||
827 | return -EINVAL; | ||
828 | } | ||
829 | |||
830 | list_for_each_entry(cii, &dev->codec_list, list) { | ||
831 | if (cii->codec_data == data) | ||
832 | return -EALREADY; | ||
833 | } | ||
834 | |||
835 | if (!ci->transfers || !ci->transfers->formats | ||
836 | || !ci->transfers->rates || !ci->usable) | ||
837 | return -EINVAL; | ||
838 | |||
839 | /* we currently code the i2s transfer on the clock, and support only | ||
840 | * 32 and 64 */ | ||
841 | if (ci->bus_factor != 32 && ci->bus_factor != 64) | ||
842 | return -EINVAL; | ||
843 | |||
844 | /* If you want to fix this, you need to keep track of what transport infos | ||
845 | * are to be used, which codecs they belong to, and then fix all the | ||
846 | * sysclock/busclock stuff above to depend on which is usable */ | ||
847 | list_for_each_entry(cii, &dev->codec_list, list) { | ||
848 | if (cii->codec->sysclock_factor != ci->sysclock_factor) { | ||
849 | printk(KERN_DEBUG | ||
850 | "cannot yet handle multiple different sysclocks!\n"); | ||
851 | return -EINVAL; | ||
852 | } | ||
853 | if (cii->codec->bus_factor != ci->bus_factor) { | ||
854 | printk(KERN_DEBUG | ||
855 | "cannot yet handle multiple different bus clocks!\n"); | ||
856 | return -EINVAL; | ||
857 | } | ||
858 | } | ||
859 | |||
860 | tmp = ci->transfers; | ||
861 | while (tmp->formats && tmp->rates) { | ||
862 | if (tmp->transfer_in) | ||
863 | in = 1; | ||
864 | else | ||
865 | out = 1; | ||
866 | tmp++; | ||
867 | } | ||
868 | |||
869 | cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL); | ||
870 | if (!cii) { | ||
871 | printk(KERN_DEBUG "i2sbus: failed to allocate cii\n"); | ||
872 | return -ENOMEM; | ||
873 | } | ||
874 | |||
875 | /* use the private data to point to the codec info */ | ||
876 | cii->sdev = soundbus_dev_get(dev); | ||
877 | cii->codec = ci; | ||
878 | cii->codec_data = data; | ||
879 | |||
880 | if (!cii->sdev) { | ||
881 | printk(KERN_DEBUG | ||
882 | "i2sbus: failed to get soundbus dev reference\n"); | ||
883 | kfree(cii); | ||
884 | return -ENODEV; | ||
885 | } | ||
886 | |||
887 | if (!try_module_get(THIS_MODULE)) { | ||
888 | printk(KERN_DEBUG "i2sbus: failed to get module reference!\n"); | ||
889 | soundbus_dev_put(dev); | ||
890 | kfree(cii); | ||
891 | return -EBUSY; | ||
892 | } | ||
893 | |||
894 | if (!try_module_get(ci->owner)) { | ||
895 | printk(KERN_DEBUG | ||
896 | "i2sbus: failed to get module reference to codec owner!\n"); | ||
897 | module_put(THIS_MODULE); | ||
898 | soundbus_dev_put(dev); | ||
899 | kfree(cii); | ||
900 | return -EBUSY; | ||
901 | } | ||
902 | |||
903 | if (!dev->pcm) { | ||
904 | err = snd_pcm_new(card, | ||
905 | dev->pcmname, | ||
906 | dev->pcmid, | ||
907 | 0, | ||
908 | 0, | ||
909 | &dev->pcm); | ||
910 | if (err) { | ||
911 | printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); | ||
912 | kfree(cii); | ||
913 | module_put(ci->owner); | ||
914 | soundbus_dev_put(dev); | ||
915 | module_put(THIS_MODULE); | ||
916 | return err; | ||
917 | } | ||
918 | } | ||
919 | |||
920 | /* ALSA yet again sucks. | ||
921 | * If it is ever fixed, remove this line. See below. */ | ||
922 | out = in = 1; | ||
923 | |||
924 | if (!i2sdev->out.created && out) { | ||
925 | if (dev->pcm->card != card) { | ||
926 | /* eh? */ | ||
927 | printk(KERN_ERR | ||
928 | "Can't attach same bus to different cards!\n"); | ||
929 | module_put(ci->owner); | ||
930 | kfree(cii); | ||
931 | soundbus_dev_put(dev); | ||
932 | module_put(THIS_MODULE); | ||
933 | return -EINVAL; | ||
934 | } | ||
935 | if ((err = | ||
936 | snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) { | ||
937 | module_put(ci->owner); | ||
938 | kfree(cii); | ||
939 | soundbus_dev_put(dev); | ||
940 | module_put(THIS_MODULE); | ||
941 | return err; | ||
942 | } | ||
943 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
944 | &i2sbus_playback_ops); | ||
945 | i2sdev->out.created = 1; | ||
946 | } | ||
947 | |||
948 | if (!i2sdev->in.created && in) { | ||
949 | if (dev->pcm->card != card) { | ||
950 | printk(KERN_ERR | ||
951 | "Can't attach same bus to different cards!\n"); | ||
952 | module_put(ci->owner); | ||
953 | kfree(cii); | ||
954 | soundbus_dev_put(dev); | ||
955 | module_put(THIS_MODULE); | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | if ((err = | ||
959 | snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) { | ||
960 | module_put(ci->owner); | ||
961 | kfree(cii); | ||
962 | soundbus_dev_put(dev); | ||
963 | module_put(THIS_MODULE); | ||
964 | return err; | ||
965 | } | ||
966 | snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, | ||
967 | &i2sbus_record_ops); | ||
968 | i2sdev->in.created = 1; | ||
969 | } | ||
970 | |||
971 | /* so we have to register the pcm after adding any substream | ||
972 | * to it because alsa doesn't create the devices for the | ||
973 | * substreams when we add them later. | ||
974 | * Therefore, force in and out on both busses (above) and | ||
975 | * register the pcm now instead of just after creating it. | ||
976 | */ | ||
977 | err = snd_device_register(card, dev->pcm); | ||
978 | if (err) { | ||
979 | printk(KERN_ERR "i2sbus: error registering new pcm\n"); | ||
980 | module_put(ci->owner); | ||
981 | kfree(cii); | ||
982 | soundbus_dev_put(dev); | ||
983 | module_put(THIS_MODULE); | ||
984 | return err; | ||
985 | } | ||
986 | /* no errors any more, so let's add this to our list */ | ||
987 | list_add(&cii->list, &dev->codec_list); | ||
988 | |||
989 | dev->pcm->private_data = i2sdev; | ||
990 | dev->pcm->private_free = i2sbus_private_free; | ||
991 | |||
992 | /* well, we really should support scatter/gather DMA */ | ||
993 | snd_pcm_lib_preallocate_pages_for_all( | ||
994 | dev->pcm, SNDRV_DMA_TYPE_DEV, | ||
995 | snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)), | ||
996 | 64 * 1024, 64 * 1024); | ||
997 | |||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | void i2sbus_detach_codec(struct soundbus_dev *dev, void *data) | ||
1002 | { | ||
1003 | struct codec_info_item *cii = NULL, *i; | ||
1004 | |||
1005 | list_for_each_entry(i, &dev->codec_list, list) { | ||
1006 | if (i->codec_data == data) { | ||
1007 | cii = i; | ||
1008 | break; | ||
1009 | } | ||
1010 | } | ||
1011 | if (cii) { | ||
1012 | list_del(&cii->list); | ||
1013 | module_put(cii->codec->owner); | ||
1014 | kfree(cii); | ||
1015 | } | ||
1016 | /* no more codecs, but still a pcm? */ | ||
1017 | if (list_empty(&dev->codec_list) && dev->pcm) { | ||
1018 | /* the actual cleanup is done by the callback above! */ | ||
1019 | snd_device_free(dev->pcm->card, dev->pcm); | ||
1020 | } | ||
1021 | } | ||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h new file mode 100644 index 000000000000..cfa5162e3b0f --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * i2sbus driver -- private definitions | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | #ifndef __I2SBUS_H | ||
9 | #define __I2SBUS_H | ||
10 | #include <asm/dbdma.h> | ||
11 | #include <linux/interrupt.h> | ||
12 | #include <sound/pcm.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/mutex.h> | ||
15 | #include <asm/prom.h> | ||
16 | #include "i2sbus-interface.h" | ||
17 | #include "i2sbus-control.h" | ||
18 | #include "../soundbus.h" | ||
19 | |||
20 | struct i2sbus_control { | ||
21 | volatile struct i2s_control_regs __iomem *controlregs; | ||
22 | struct resource rsrc; | ||
23 | struct list_head list; | ||
24 | }; | ||
25 | |||
26 | #define MAX_DBDMA_COMMANDS 32 | ||
27 | |||
28 | struct dbdma_command_mem { | ||
29 | dma_addr_t bus_addr; | ||
30 | dma_addr_t bus_cmd_start; | ||
31 | struct dbdma_cmd *cmds; | ||
32 | void *space; | ||
33 | int size; | ||
34 | u32 running:1; | ||
35 | }; | ||
36 | |||
37 | struct pcm_info { | ||
38 | u32 created:1, /* has this direction been created with alsa? */ | ||
39 | active:1; /* is this stream active? */ | ||
40 | /* runtime information */ | ||
41 | struct snd_pcm_substream *substream; | ||
42 | int current_period; | ||
43 | u32 frame_count; | ||
44 | struct dbdma_command_mem dbdma_ring; | ||
45 | volatile struct dbdma_regs __iomem *dbdma; | ||
46 | }; | ||
47 | |||
48 | struct i2sbus_dev { | ||
49 | struct soundbus_dev sound; | ||
50 | struct macio_dev *macio; | ||
51 | struct i2sbus_control *control; | ||
52 | volatile struct i2s_interface_regs __iomem *intfregs; | ||
53 | |||
54 | struct resource resources[3]; | ||
55 | struct resource *allocated_resource[3]; | ||
56 | int interrupts[3]; | ||
57 | char rnames[3][32]; | ||
58 | |||
59 | /* info about currently active substreams */ | ||
60 | struct pcm_info out, in; | ||
61 | snd_pcm_format_t format; | ||
62 | unsigned int rate; | ||
63 | |||
64 | /* list for a single controller */ | ||
65 | struct list_head item; | ||
66 | /* number of bus on controller */ | ||
67 | int bus_number; | ||
68 | /* for use by control layer */ | ||
69 | struct pmf_function *enable, | ||
70 | *cell_enable, | ||
71 | *cell_disable, | ||
72 | *clock_enable, | ||
73 | *clock_disable; | ||
74 | |||
75 | /* locks */ | ||
76 | /* spinlock for low-level interrupt locking */ | ||
77 | spinlock_t low_lock; | ||
78 | /* mutex for high-level consistency */ | ||
79 | struct mutex lock; | ||
80 | }; | ||
81 | |||
82 | #define soundbus_dev_to_i2sbus_dev(sdev) \ | ||
83 | container_of(sdev, struct i2sbus_dev, sound) | ||
84 | |||
85 | /* pcm specific functions */ | ||
86 | extern int | ||
87 | i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, | ||
88 | struct codec_info *ci, void *data); | ||
89 | extern void | ||
90 | i2sbus_detach_codec(struct soundbus_dev *dev, void *data); | ||
91 | extern irqreturn_t | ||
92 | i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs); | ||
93 | extern irqreturn_t | ||
94 | i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs); | ||
95 | |||
96 | /* control specific functions */ | ||
97 | extern int i2sbus_control_init(struct macio_dev* dev, | ||
98 | struct i2sbus_control **c); | ||
99 | extern void i2sbus_control_destroy(struct i2sbus_control *c); | ||
100 | extern int i2sbus_control_add_dev(struct i2sbus_control *c, | ||
101 | struct i2sbus_dev *i2sdev); | ||
102 | extern void i2sbus_control_remove_dev(struct i2sbus_control *c, | ||
103 | struct i2sbus_dev *i2sdev); | ||
104 | extern int i2sbus_control_enable(struct i2sbus_control *c, | ||
105 | struct i2sbus_dev *i2sdev); | ||
106 | extern int i2sbus_control_cell(struct i2sbus_control *c, | ||
107 | struct i2sbus_dev *i2sdev, | ||
108 | int enable); | ||
109 | extern int i2sbus_control_clock(struct i2sbus_control *c, | ||
110 | struct i2sbus_dev *i2sdev, | ||
111 | int enable); | ||
112 | #endif /* __I2SBUS_H */ | ||
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h new file mode 100644 index 000000000000..5c27297835d7 --- /dev/null +++ b/sound/aoa/soundbus/soundbus.h | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * soundbus generic definitions | ||
3 | * | ||
4 | * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> | ||
5 | * | ||
6 | * GPL v2, can be found in COPYING. | ||
7 | */ | ||
8 | #ifndef __SOUNDBUS_H | ||
9 | #define __SOUNDBUS_H | ||
10 | |||
11 | #include <asm/of_device.h> | ||
12 | #include <sound/pcm.h> | ||
13 | #include <linux/list.h> | ||
14 | |||
15 | |||
16 | /* When switching from master to slave or the other way around, | ||
17 | * you don't want to have the codec chip acting as clock source | ||
18 | * while the bus still is. | ||
19 | * More importantly, while switch from slave to master, you need | ||
20 | * to turn off the chip's master function first, but then there's | ||
21 | * no clock for a while and other chips might reset, so we notify | ||
22 | * their drivers after having switched. | ||
23 | * The constants here are codec-point of view, so when we switch | ||
24 | * the soundbus to master we tell the codec we're going to switch | ||
25 | * and give it CLOCK_SWITCH_PREPARE_SLAVE! | ||
26 | */ | ||
27 | enum clock_switch { | ||
28 | CLOCK_SWITCH_PREPARE_SLAVE, | ||
29 | CLOCK_SWITCH_PREPARE_MASTER, | ||
30 | CLOCK_SWITCH_SLAVE, | ||
31 | CLOCK_SWITCH_MASTER, | ||
32 | CLOCK_SWITCH_NOTIFY, | ||
33 | }; | ||
34 | |||
35 | /* information on a transfer the codec can take */ | ||
36 | struct transfer_info { | ||
37 | u64 formats; /* SNDRV_PCM_FMTBIT_* */ | ||
38 | unsigned int rates; /* SNDRV_PCM_RATE_* */ | ||
39 | /* flags */ | ||
40 | u32 transfer_in:1, /* input = 1, output = 0 */ | ||
41 | must_be_clock_source:1; | ||
42 | /* for codecs to distinguish among their TIs */ | ||
43 | int tag; | ||
44 | }; | ||
45 | |||
46 | struct codec_info_item { | ||
47 | struct codec_info *codec; | ||
48 | void *codec_data; | ||
49 | struct soundbus_dev *sdev; | ||
50 | /* internal, to be used by the soundbus provider */ | ||
51 | struct list_head list; | ||
52 | }; | ||
53 | |||
54 | /* for prepare, where the codecs need to know | ||
55 | * what we're going to drive the bus with */ | ||
56 | struct bus_info { | ||
57 | /* see below */ | ||
58 | int sysclock_factor; | ||
59 | int bus_factor; | ||
60 | }; | ||
61 | |||
62 | /* information on the codec itself, plus function pointers */ | ||
63 | struct codec_info { | ||
64 | /* the module this lives in */ | ||
65 | struct module *owner; | ||
66 | |||
67 | /* supported transfer possibilities, array terminated by | ||
68 | * formats or rates being 0. */ | ||
69 | struct transfer_info *transfers; | ||
70 | |||
71 | /* Master clock speed factor | ||
72 | * to be used (master clock speed = sysclock_factor * sampling freq) | ||
73 | * Unused if the soundbus provider has no such notion. | ||
74 | */ | ||
75 | int sysclock_factor; | ||
76 | |||
77 | /* Bus factor, bus clock speed = bus_factor * sampling freq) | ||
78 | * Unused if the soundbus provider has no such notion. | ||
79 | */ | ||
80 | int bus_factor; | ||
81 | |||
82 | /* operations */ | ||
83 | /* clock switching, see above */ | ||
84 | int (*switch_clock)(struct codec_info_item *cii, | ||
85 | enum clock_switch clock); | ||
86 | |||
87 | /* called for each transfer_info when the user | ||
88 | * opens the pcm device to determine what the | ||
89 | * hardware can support at this point in time. | ||
90 | * That can depend on other user-switchable controls. | ||
91 | * Return 1 if usable, 0 if not. | ||
92 | * out points to another instance of a transfer_info | ||
93 | * which is initialised to the values in *ti, and | ||
94 | * it's format and rate values can be modified by | ||
95 | * the callback if it is necessary to further restrict | ||
96 | * the formats that can be used at the moment, for | ||
97 | * example when one codec has multiple logical codec | ||
98 | * info structs for multiple inputs. | ||
99 | */ | ||
100 | int (*usable)(struct codec_info_item *cii, | ||
101 | struct transfer_info *ti, | ||
102 | struct transfer_info *out); | ||
103 | |||
104 | /* called when pcm stream is opened, probably not implemented | ||
105 | * most of the time since it isn't too useful */ | ||
106 | int (*open)(struct codec_info_item *cii, | ||
107 | struct snd_pcm_substream *substream); | ||
108 | |||
109 | /* called when the pcm stream is closed, at this point | ||
110 | * the user choices can all be unlocked (see below) */ | ||
111 | int (*close)(struct codec_info_item *cii, | ||
112 | struct snd_pcm_substream *substream); | ||
113 | |||
114 | /* if the codec must forbid some user choices because | ||
115 | * they are not valid with the substream/transfer info, | ||
116 | * it must do so here. Example: no digital output for | ||
117 | * incompatible framerate, say 8KHz, on Onyx. | ||
118 | * If the selected stuff in the substream is NOT | ||
119 | * compatible, you have to reject this call! */ | ||
120 | int (*prepare)(struct codec_info_item *cii, | ||
121 | struct bus_info *bi, | ||
122 | struct snd_pcm_substream *substream); | ||
123 | |||
124 | /* start() is called before data is pushed to the codec. | ||
125 | * Note that start() must be atomic! */ | ||
126 | int (*start)(struct codec_info_item *cii, | ||
127 | struct snd_pcm_substream *substream); | ||
128 | |||
129 | /* stop() is called after data is no longer pushed to the codec. | ||
130 | * Note that stop() must be atomic! */ | ||
131 | int (*stop)(struct codec_info_item *cii, | ||
132 | struct snd_pcm_substream *substream); | ||
133 | |||
134 | int (*suspend)(struct codec_info_item *cii, pm_message_t state); | ||
135 | int (*resume)(struct codec_info_item *cii); | ||
136 | }; | ||
137 | |||
138 | /* information on a soundbus device */ | ||
139 | struct soundbus_dev { | ||
140 | /* the bus it belongs to */ | ||
141 | struct list_head onbuslist; | ||
142 | |||
143 | /* the of device it represents */ | ||
144 | struct of_device ofdev; | ||
145 | |||
146 | /* what modules go by */ | ||
147 | char modalias[32]; | ||
148 | |||
149 | /* These fields must be before attach_codec can be called. | ||
150 | * They should be set by the owner of the alsa card object | ||
151 | * that is needed, and whoever sets them must make sure | ||
152 | * that they are unique within that alsa card object. */ | ||
153 | char *pcmname; | ||
154 | int pcmid; | ||
155 | |||
156 | /* this is assigned by the soundbus provider in attach_codec */ | ||
157 | struct snd_pcm *pcm; | ||
158 | |||
159 | /* operations */ | ||
160 | /* attach a codec to this soundbus, give the alsa | ||
161 | * card object the PCMs for this soundbus should be in. | ||
162 | * The 'data' pointer must be unique, it is used as the | ||
163 | * key for detach_codec(). */ | ||
164 | int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card, | ||
165 | struct codec_info *ci, void *data); | ||
166 | void (*detach_codec)(struct soundbus_dev *dev, void *data); | ||
167 | /* TODO: suspend/resume */ | ||
168 | |||
169 | /* private for the soundbus provider */ | ||
170 | struct list_head codec_list; | ||
171 | u32 have_out:1, have_in:1; | ||
172 | }; | ||
173 | #define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev) | ||
174 | #define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev) | ||
175 | |||
176 | extern int soundbus_add_one(struct soundbus_dev *dev); | ||
177 | extern void soundbus_remove_one(struct soundbus_dev *dev); | ||
178 | |||
179 | extern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev); | ||
180 | extern void soundbus_dev_put(struct soundbus_dev *dev); | ||
181 | |||
182 | struct soundbus_driver { | ||
183 | char *name; | ||
184 | struct module *owner; | ||
185 | |||
186 | /* we don't implement any matching at all */ | ||
187 | |||
188 | int (*probe)(struct soundbus_dev* dev); | ||
189 | int (*remove)(struct soundbus_dev* dev); | ||
190 | |||
191 | int (*suspend)(struct soundbus_dev* dev, pm_message_t state); | ||
192 | int (*resume)(struct soundbus_dev* dev); | ||
193 | int (*shutdown)(struct soundbus_dev* dev); | ||
194 | |||
195 | struct device_driver driver; | ||
196 | }; | ||
197 | #define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver) | ||
198 | |||
199 | extern int soundbus_register_driver(struct soundbus_driver *drv); | ||
200 | extern void soundbus_unregister_driver(struct soundbus_driver *drv); | ||
201 | |||
202 | #endif /* __SOUNDBUS_H */ | ||
diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c new file mode 100644 index 000000000000..d31f8146952a --- /dev/null +++ b/sound/aoa/soundbus/sysfs.c | |||
@@ -0,0 +1,43 @@ | |||
1 | #include <linux/config.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/stat.h> | ||
4 | /* FIX UP */ | ||
5 | #include "soundbus.h" | ||
6 | |||
7 | #define soundbus_config_of_attr(field, format_string) \ | ||
8 | static ssize_t \ | ||
9 | field##_show (struct device *dev, struct device_attribute *attr, \ | ||
10 | char *buf) \ | ||
11 | { \ | ||
12 | struct soundbus_dev *mdev = to_soundbus_device (dev); \ | ||
13 | return sprintf (buf, format_string, mdev->ofdev.node->field); \ | ||
14 | } | ||
15 | |||
16 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | ||
17 | char *buf) | ||
18 | { | ||
19 | struct soundbus_dev *sdev = to_soundbus_device(dev); | ||
20 | struct of_device *of = &sdev->ofdev; | ||
21 | int length; | ||
22 | |||
23 | if (*sdev->modalias) { | ||
24 | strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1); | ||
25 | strcat(buf, "\n"); | ||
26 | length = strlen(buf); | ||
27 | } else { | ||
28 | length = sprintf(buf, "of:N%sT%s\n", | ||
29 | of->node->name, of->node->type); | ||
30 | } | ||
31 | |||
32 | return length; | ||
33 | } | ||
34 | |||
35 | soundbus_config_of_attr (name, "%s\n"); | ||
36 | soundbus_config_of_attr (type, "%s\n"); | ||
37 | |||
38 | struct device_attribute soundbus_dev_attrs[] = { | ||
39 | __ATTR_RO(name), | ||
40 | __ATTR_RO(type), | ||
41 | __ATTR_RO(modalias), | ||
42 | __ATTR_NULL | ||
43 | }; | ||
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c index 13057d92f08a..b88fb0c5a68a 100644 --- a/sound/arm/sa11xx-uda1341.c +++ b/sound/arm/sa11xx-uda1341.c | |||
@@ -112,7 +112,7 @@ MODULE_LICENSE("GPL"); | |||
112 | MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA"); | 112 | MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA"); |
113 | MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}"); | 113 | MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}"); |
114 | 114 | ||
115 | static char *id = NULL; /* ID for this card */ | 115 | static char *id; /* ID for this card */ |
116 | 116 | ||
117 | module_param(id, charp, 0444); | 117 | module_param(id, charp, 0444); |
118 | MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard."); | 118 | MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard."); |
@@ -984,11 +984,15 @@ static int __init sa11xx_uda1341_init(void) | |||
984 | if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0) | 984 | if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0) |
985 | return err; | 985 | return err; |
986 | device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0); | 986 | device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0); |
987 | if (IS_ERR(device)) { | 987 | if (!IS_ERR(device)) { |
988 | platform_driver_unregister(&sa11xx_uda1341_driver); | 988 | if (platform_get_drvdata(device)) |
989 | return PTR_ERR(device); | 989 | return 0; |
990 | } | 990 | platform_device_unregister(device); |
991 | return 0; | 991 | err = -ENODEV |
992 | } else | ||
993 | err = PTR_ERR(device); | ||
994 | platform_driver_unregister(&sa11xx_uda1341_driver); | ||
995 | return err; | ||
992 | } | 996 | } |
993 | 997 | ||
994 | static void __exit sa11xx_uda1341_exit(void) | 998 | static void __exit sa11xx_uda1341_exit(void) |
diff --git a/sound/core/control.c b/sound/core/control.c index 22565c9b9603..bb397eaa7187 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -176,6 +176,8 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask, | |||
176 | read_unlock(&card->ctl_files_rwlock); | 176 | read_unlock(&card->ctl_files_rwlock); |
177 | } | 177 | } |
178 | 178 | ||
179 | EXPORT_SYMBOL(snd_ctl_notify); | ||
180 | |||
179 | /** | 181 | /** |
180 | * snd_ctl_new - create a control instance from the template | 182 | * snd_ctl_new - create a control instance from the template |
181 | * @control: the control template | 183 | * @control: the control template |
@@ -204,6 +206,8 @@ struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, unsigned int acce | |||
204 | return kctl; | 206 | return kctl; |
205 | } | 207 | } |
206 | 208 | ||
209 | EXPORT_SYMBOL(snd_ctl_new); | ||
210 | |||
207 | /** | 211 | /** |
208 | * snd_ctl_new1 - create a control instance from the template | 212 | * snd_ctl_new1 - create a control instance from the template |
209 | * @ncontrol: the initialization record | 213 | * @ncontrol: the initialization record |
@@ -242,6 +246,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, | |||
242 | return snd_ctl_new(&kctl, access); | 246 | return snd_ctl_new(&kctl, access); |
243 | } | 247 | } |
244 | 248 | ||
249 | EXPORT_SYMBOL(snd_ctl_new1); | ||
250 | |||
245 | /** | 251 | /** |
246 | * snd_ctl_free_one - release the control instance | 252 | * snd_ctl_free_one - release the control instance |
247 | * @kcontrol: the control instance | 253 | * @kcontrol: the control instance |
@@ -259,6 +265,8 @@ void snd_ctl_free_one(struct snd_kcontrol *kcontrol) | |||
259 | } | 265 | } |
260 | } | 266 | } |
261 | 267 | ||
268 | EXPORT_SYMBOL(snd_ctl_free_one); | ||
269 | |||
262 | static unsigned int snd_ctl_hole_check(struct snd_card *card, | 270 | static unsigned int snd_ctl_hole_check(struct snd_card *card, |
263 | unsigned int count) | 271 | unsigned int count) |
264 | { | 272 | { |
@@ -347,6 +355,8 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
347 | return err; | 355 | return err; |
348 | } | 356 | } |
349 | 357 | ||
358 | EXPORT_SYMBOL(snd_ctl_add); | ||
359 | |||
350 | /** | 360 | /** |
351 | * snd_ctl_remove - remove the control from the card and release it | 361 | * snd_ctl_remove - remove the control from the card and release it |
352 | * @card: the card instance | 362 | * @card: the card instance |
@@ -373,6 +383,8 @@ int snd_ctl_remove(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
373 | return 0; | 383 | return 0; |
374 | } | 384 | } |
375 | 385 | ||
386 | EXPORT_SYMBOL(snd_ctl_remove); | ||
387 | |||
376 | /** | 388 | /** |
377 | * snd_ctl_remove_id - remove the control of the given id and release it | 389 | * snd_ctl_remove_id - remove the control of the given id and release it |
378 | * @card: the card instance | 390 | * @card: the card instance |
@@ -399,6 +411,8 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) | |||
399 | return ret; | 411 | return ret; |
400 | } | 412 | } |
401 | 413 | ||
414 | EXPORT_SYMBOL(snd_ctl_remove_id); | ||
415 | |||
402 | /** | 416 | /** |
403 | * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it | 417 | * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it |
404 | * @file: active control handle | 418 | * @file: active control handle |
@@ -461,6 +475,8 @@ int snd_ctl_rename_id(struct snd_card *card, struct snd_ctl_elem_id *src_id, | |||
461 | return 0; | 475 | return 0; |
462 | } | 476 | } |
463 | 477 | ||
478 | EXPORT_SYMBOL(snd_ctl_rename_id); | ||
479 | |||
464 | /** | 480 | /** |
465 | * snd_ctl_find_numid - find the control instance with the given number-id | 481 | * snd_ctl_find_numid - find the control instance with the given number-id |
466 | * @card: the card instance | 482 | * @card: the card instance |
@@ -487,6 +503,8 @@ struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numi | |||
487 | return NULL; | 503 | return NULL; |
488 | } | 504 | } |
489 | 505 | ||
506 | EXPORT_SYMBOL(snd_ctl_find_numid); | ||
507 | |||
490 | /** | 508 | /** |
491 | * snd_ctl_find_id - find the control instance with the given id | 509 | * snd_ctl_find_id - find the control instance with the given id |
492 | * @card: the card instance | 510 | * @card: the card instance |
@@ -527,6 +545,8 @@ struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, | |||
527 | return NULL; | 545 | return NULL; |
528 | } | 546 | } |
529 | 547 | ||
548 | EXPORT_SYMBOL(snd_ctl_find_id); | ||
549 | |||
530 | static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, | 550 | static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl, |
531 | unsigned int cmd, void __user *arg) | 551 | unsigned int cmd, void __user *arg) |
532 | { | 552 | { |
@@ -704,6 +724,8 @@ int snd_ctl_elem_read(struct snd_card *card, struct snd_ctl_elem_value *control) | |||
704 | return result; | 724 | return result; |
705 | } | 725 | } |
706 | 726 | ||
727 | EXPORT_SYMBOL(snd_ctl_elem_read); | ||
728 | |||
707 | static int snd_ctl_elem_read_user(struct snd_card *card, | 729 | static int snd_ctl_elem_read_user(struct snd_card *card, |
708 | struct snd_ctl_elem_value __user *_control) | 730 | struct snd_ctl_elem_value __user *_control) |
709 | { | 731 | { |
@@ -767,6 +789,8 @@ int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file, | |||
767 | return result; | 789 | return result; |
768 | } | 790 | } |
769 | 791 | ||
792 | EXPORT_SYMBOL(snd_ctl_elem_write); | ||
793 | |||
770 | static int snd_ctl_elem_write_user(struct snd_ctl_file *file, | 794 | static int snd_ctl_elem_write_user(struct snd_ctl_file *file, |
771 | struct snd_ctl_elem_value __user *_control) | 795 | struct snd_ctl_elem_value __user *_control) |
772 | { | 796 | { |
@@ -1199,11 +1223,15 @@ int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn) | |||
1199 | return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); | 1223 | return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls); |
1200 | } | 1224 | } |
1201 | 1225 | ||
1226 | EXPORT_SYMBOL(snd_ctl_register_ioctl); | ||
1227 | |||
1202 | #ifdef CONFIG_COMPAT | 1228 | #ifdef CONFIG_COMPAT |
1203 | int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) | 1229 | int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn) |
1204 | { | 1230 | { |
1205 | return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); | 1231 | return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls); |
1206 | } | 1232 | } |
1233 | |||
1234 | EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); | ||
1207 | #endif | 1235 | #endif |
1208 | 1236 | ||
1209 | /* | 1237 | /* |
@@ -1236,12 +1264,15 @@ int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn) | |||
1236 | return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); | 1264 | return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls); |
1237 | } | 1265 | } |
1238 | 1266 | ||
1267 | EXPORT_SYMBOL(snd_ctl_unregister_ioctl); | ||
1268 | |||
1239 | #ifdef CONFIG_COMPAT | 1269 | #ifdef CONFIG_COMPAT |
1240 | int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) | 1270 | int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn) |
1241 | { | 1271 | { |
1242 | return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); | 1272 | return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls); |
1243 | } | 1273 | } |
1244 | 1274 | ||
1275 | EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); | ||
1245 | #endif | 1276 | #endif |
1246 | 1277 | ||
1247 | static int snd_ctl_fasync(int fd, struct file * file, int on) | 1278 | static int snd_ctl_fasync(int fd, struct file * file, int on) |
diff --git a/sound/core/device.c b/sound/core/device.c index b1cf6ec56784..6ce4da4a1081 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -63,6 +63,8 @@ int snd_device_new(struct snd_card *card, snd_device_type_t type, | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | EXPORT_SYMBOL(snd_device_new); | ||
67 | |||
66 | /** | 68 | /** |
67 | * snd_device_free - release the device from the card | 69 | * snd_device_free - release the device from the card |
68 | * @card: the card instance | 70 | * @card: the card instance |
@@ -107,6 +109,8 @@ int snd_device_free(struct snd_card *card, void *device_data) | |||
107 | return -ENXIO; | 109 | return -ENXIO; |
108 | } | 110 | } |
109 | 111 | ||
112 | EXPORT_SYMBOL(snd_device_free); | ||
113 | |||
110 | /** | 114 | /** |
111 | * snd_device_disconnect - disconnect the device | 115 | * snd_device_disconnect - disconnect the device |
112 | * @card: the card instance | 116 | * @card: the card instance |
@@ -182,6 +186,8 @@ int snd_device_register(struct snd_card *card, void *device_data) | |||
182 | return -ENXIO; | 186 | return -ENXIO; |
183 | } | 187 | } |
184 | 188 | ||
189 | EXPORT_SYMBOL(snd_device_register); | ||
190 | |||
185 | /* | 191 | /* |
186 | * register all the devices on the card. | 192 | * register all the devices on the card. |
187 | * called from init.c | 193 | * called from init.c |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 2524e66eccdd..8bd0dcc93eba 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -486,7 +486,6 @@ static void __init snd_hwdep_proc_init(void) | |||
486 | struct snd_info_entry *entry; | 486 | struct snd_info_entry *entry; |
487 | 487 | ||
488 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { | 488 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { |
489 | entry->c.text.read_size = PAGE_SIZE; | ||
490 | entry->c.text.read = snd_hwdep_proc_read; | 489 | entry->c.text.read = snd_hwdep_proc_read; |
491 | if (snd_info_register(entry) < 0) { | 490 | if (snd_info_register(entry) < 0) { |
492 | snd_info_free_entry(entry); | 491 | snd_info_free_entry(entry); |
diff --git a/sound/core/info.c b/sound/core/info.c index 2582b74d3199..10c1772bf3ea 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | #include <sound/driver.h> | 22 | #include <sound/driver.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/vmalloc.h> | ||
25 | #include <linux/time.h> | 24 | #include <linux/time.h> |
26 | #include <linux/smp_lock.h> | 25 | #include <linux/smp_lock.h> |
27 | #include <linux/string.h> | 26 | #include <linux/string.h> |
@@ -82,6 +81,24 @@ static int snd_info_version_init(void); | |||
82 | static int snd_info_version_done(void); | 81 | static int snd_info_version_done(void); |
83 | 82 | ||
84 | 83 | ||
84 | /* resize the proc r/w buffer */ | ||
85 | static int resize_info_buffer(struct snd_info_buffer *buffer, | ||
86 | unsigned int nsize) | ||
87 | { | ||
88 | char *nbuf; | ||
89 | |||
90 | nsize = PAGE_ALIGN(nsize); | ||
91 | nbuf = kmalloc(nsize, GFP_KERNEL); | ||
92 | if (! nbuf) | ||
93 | return -ENOMEM; | ||
94 | |||
95 | memcpy(nbuf, buffer->buffer, buffer->len); | ||
96 | kfree(buffer->buffer); | ||
97 | buffer->buffer = nbuf; | ||
98 | buffer->len = nsize; | ||
99 | return 0; | ||
100 | } | ||
101 | |||
85 | /** | 102 | /** |
86 | * snd_iprintf - printf on the procfs buffer | 103 | * snd_iprintf - printf on the procfs buffer |
87 | * @buffer: the procfs buffer | 104 | * @buffer: the procfs buffer |
@@ -95,30 +112,43 @@ int snd_iprintf(struct snd_info_buffer *buffer, char *fmt,...) | |||
95 | { | 112 | { |
96 | va_list args; | 113 | va_list args; |
97 | int len, res; | 114 | int len, res; |
115 | int err = 0; | ||
98 | 116 | ||
117 | might_sleep(); | ||
99 | if (buffer->stop || buffer->error) | 118 | if (buffer->stop || buffer->error) |
100 | return 0; | 119 | return 0; |
101 | len = buffer->len - buffer->size; | 120 | len = buffer->len - buffer->size; |
102 | va_start(args, fmt); | 121 | va_start(args, fmt); |
103 | res = vsnprintf(buffer->curr, len, fmt, args); | 122 | for (;;) { |
104 | va_end(args); | 123 | res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args); |
105 | if (res >= len) { | 124 | if (res < len) |
106 | buffer->stop = 1; | 125 | break; |
107 | return 0; | 126 | err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE); |
127 | if (err < 0) | ||
128 | break; | ||
129 | len = buffer->len - buffer->size; | ||
108 | } | 130 | } |
131 | va_end(args); | ||
132 | |||
133 | if (err < 0) | ||
134 | return err; | ||
109 | buffer->curr += res; | 135 | buffer->curr += res; |
110 | buffer->size += res; | 136 | buffer->size += res; |
111 | return res; | 137 | return res; |
112 | } | 138 | } |
113 | 139 | ||
140 | EXPORT_SYMBOL(snd_iprintf); | ||
141 | |||
114 | /* | 142 | /* |
115 | 143 | ||
116 | */ | 144 | */ |
117 | 145 | ||
118 | static struct proc_dir_entry *snd_proc_root = NULL; | 146 | static struct proc_dir_entry *snd_proc_root; |
119 | struct snd_info_entry *snd_seq_root = NULL; | 147 | struct snd_info_entry *snd_seq_root; |
148 | EXPORT_SYMBOL(snd_seq_root); | ||
149 | |||
120 | #ifdef CONFIG_SND_OSSEMUL | 150 | #ifdef CONFIG_SND_OSSEMUL |
121 | struct snd_info_entry *snd_oss_root = NULL; | 151 | struct snd_info_entry *snd_oss_root; |
122 | #endif | 152 | #endif |
123 | 153 | ||
124 | static inline void snd_info_entry_prepare(struct proc_dir_entry *de) | 154 | static inline void snd_info_entry_prepare(struct proc_dir_entry *de) |
@@ -221,7 +251,7 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer | |||
221 | struct snd_info_private_data *data; | 251 | struct snd_info_private_data *data; |
222 | struct snd_info_entry *entry; | 252 | struct snd_info_entry *entry; |
223 | struct snd_info_buffer *buf; | 253 | struct snd_info_buffer *buf; |
224 | size_t size = 0; | 254 | ssize_t size = 0; |
225 | loff_t pos; | 255 | loff_t pos; |
226 | 256 | ||
227 | data = file->private_data; | 257 | data = file->private_data; |
@@ -237,14 +267,20 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer | |||
237 | buf = data->wbuffer; | 267 | buf = data->wbuffer; |
238 | if (buf == NULL) | 268 | if (buf == NULL) |
239 | return -EIO; | 269 | return -EIO; |
240 | if (pos >= buf->len) | 270 | mutex_lock(&entry->access); |
241 | return -ENOMEM; | 271 | if (pos + count >= buf->len) { |
242 | size = buf->len - pos; | 272 | if (resize_info_buffer(buf, pos + count)) { |
243 | size = min(count, size); | 273 | mutex_unlock(&entry->access); |
244 | if (copy_from_user(buf->buffer + pos, buffer, size)) | 274 | return -ENOMEM; |
275 | } | ||
276 | } | ||
277 | if (copy_from_user(buf->buffer + pos, buffer, count)) { | ||
278 | mutex_unlock(&entry->access); | ||
245 | return -EFAULT; | 279 | return -EFAULT; |
246 | if ((long)buf->size < pos + size) | 280 | } |
247 | buf->size = pos + size; | 281 | buf->size = pos + count; |
282 | mutex_unlock(&entry->access); | ||
283 | size = count; | ||
248 | break; | 284 | break; |
249 | case SNDRV_INFO_CONTENT_DATA: | 285 | case SNDRV_INFO_CONTENT_DATA: |
250 | if (entry->c.ops->write) | 286 | if (entry->c.ops->write) |
@@ -279,18 +315,14 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) | |||
279 | } | 315 | } |
280 | mode = file->f_flags & O_ACCMODE; | 316 | mode = file->f_flags & O_ACCMODE; |
281 | if (mode == O_RDONLY || mode == O_RDWR) { | 317 | if (mode == O_RDONLY || mode == O_RDWR) { |
282 | if ((entry->content == SNDRV_INFO_CONTENT_TEXT && | 318 | if ((entry->content == SNDRV_INFO_CONTENT_DATA && |
283 | !entry->c.text.read_size) || | ||
284 | (entry->content == SNDRV_INFO_CONTENT_DATA && | ||
285 | entry->c.ops->read == NULL)) { | 319 | entry->c.ops->read == NULL)) { |
286 | err = -ENODEV; | 320 | err = -ENODEV; |
287 | goto __error; | 321 | goto __error; |
288 | } | 322 | } |
289 | } | 323 | } |
290 | if (mode == O_WRONLY || mode == O_RDWR) { | 324 | if (mode == O_WRONLY || mode == O_RDWR) { |
291 | if ((entry->content == SNDRV_INFO_CONTENT_TEXT && | 325 | if ((entry->content == SNDRV_INFO_CONTENT_DATA && |
292 | !entry->c.text.write_size) || | ||
293 | (entry->content == SNDRV_INFO_CONTENT_DATA && | ||
294 | entry->c.ops->write == NULL)) { | 326 | entry->c.ops->write == NULL)) { |
295 | err = -ENODEV; | 327 | err = -ENODEV; |
296 | goto __error; | 328 | goto __error; |
@@ -306,49 +338,23 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) | |||
306 | case SNDRV_INFO_CONTENT_TEXT: | 338 | case SNDRV_INFO_CONTENT_TEXT: |
307 | if (mode == O_RDONLY || mode == O_RDWR) { | 339 | if (mode == O_RDONLY || mode == O_RDWR) { |
308 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | 340 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
309 | if (buffer == NULL) { | 341 | if (buffer == NULL) |
310 | kfree(data); | 342 | goto __nomem; |
311 | err = -ENOMEM; | ||
312 | goto __error; | ||
313 | } | ||
314 | buffer->len = (entry->c.text.read_size + | ||
315 | (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); | ||
316 | buffer->buffer = vmalloc(buffer->len); | ||
317 | if (buffer->buffer == NULL) { | ||
318 | kfree(buffer); | ||
319 | kfree(data); | ||
320 | err = -ENOMEM; | ||
321 | goto __error; | ||
322 | } | ||
323 | buffer->curr = buffer->buffer; | ||
324 | data->rbuffer = buffer; | 343 | data->rbuffer = buffer; |
344 | buffer->len = PAGE_SIZE; | ||
345 | buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); | ||
346 | if (buffer->buffer == NULL) | ||
347 | goto __nomem; | ||
325 | } | 348 | } |
326 | if (mode == O_WRONLY || mode == O_RDWR) { | 349 | if (mode == O_WRONLY || mode == O_RDWR) { |
327 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); | 350 | buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
328 | if (buffer == NULL) { | 351 | if (buffer == NULL) |
329 | if (mode == O_RDWR) { | 352 | goto __nomem; |
330 | vfree(data->rbuffer->buffer); | ||
331 | kfree(data->rbuffer); | ||
332 | } | ||
333 | kfree(data); | ||
334 | err = -ENOMEM; | ||
335 | goto __error; | ||
336 | } | ||
337 | buffer->len = (entry->c.text.write_size + | ||
338 | (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); | ||
339 | buffer->buffer = vmalloc(buffer->len); | ||
340 | if (buffer->buffer == NULL) { | ||
341 | if (mode == O_RDWR) { | ||
342 | vfree(data->rbuffer->buffer); | ||
343 | kfree(data->rbuffer); | ||
344 | } | ||
345 | kfree(buffer); | ||
346 | kfree(data); | ||
347 | err = -ENOMEM; | ||
348 | goto __error; | ||
349 | } | ||
350 | buffer->curr = buffer->buffer; | ||
351 | data->wbuffer = buffer; | 353 | data->wbuffer = buffer; |
354 | buffer->len = PAGE_SIZE; | ||
355 | buffer->buffer = kmalloc(buffer->len, GFP_KERNEL); | ||
356 | if (buffer->buffer == NULL) | ||
357 | goto __nomem; | ||
352 | } | 358 | } |
353 | break; | 359 | break; |
354 | case SNDRV_INFO_CONTENT_DATA: /* data */ | 360 | case SNDRV_INFO_CONTENT_DATA: /* data */ |
@@ -373,6 +379,17 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) | |||
373 | } | 379 | } |
374 | return 0; | 380 | return 0; |
375 | 381 | ||
382 | __nomem: | ||
383 | if (data->rbuffer) { | ||
384 | kfree(data->rbuffer->buffer); | ||
385 | kfree(data->rbuffer); | ||
386 | } | ||
387 | if (data->wbuffer) { | ||
388 | kfree(data->wbuffer->buffer); | ||
389 | kfree(data->wbuffer); | ||
390 | } | ||
391 | kfree(data); | ||
392 | err = -ENOMEM; | ||
376 | __error: | 393 | __error: |
377 | module_put(entry->module); | 394 | module_put(entry->module); |
378 | __error1: | 395 | __error1: |
@@ -391,11 +408,11 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) | |||
391 | entry = data->entry; | 408 | entry = data->entry; |
392 | switch (entry->content) { | 409 | switch (entry->content) { |
393 | case SNDRV_INFO_CONTENT_TEXT: | 410 | case SNDRV_INFO_CONTENT_TEXT: |
394 | if (mode == O_RDONLY || mode == O_RDWR) { | 411 | if (data->rbuffer) { |
395 | vfree(data->rbuffer->buffer); | 412 | kfree(data->rbuffer->buffer); |
396 | kfree(data->rbuffer); | 413 | kfree(data->rbuffer); |
397 | } | 414 | } |
398 | if (mode == O_WRONLY || mode == O_RDWR) { | 415 | if (data->wbuffer) { |
399 | if (entry->c.text.write) { | 416 | if (entry->c.text.write) { |
400 | entry->c.text.write(entry, data->wbuffer); | 417 | entry->c.text.write(entry, data->wbuffer); |
401 | if (data->wbuffer->error) { | 418 | if (data->wbuffer->error) { |
@@ -404,7 +421,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file) | |||
404 | data->wbuffer->error); | 421 | data->wbuffer->error); |
405 | } | 422 | } |
406 | } | 423 | } |
407 | vfree(data->wbuffer->buffer); | 424 | kfree(data->wbuffer->buffer); |
408 | kfree(data->wbuffer); | 425 | kfree(data->wbuffer); |
409 | } | 426 | } |
410 | break; | 427 | break; |
@@ -664,29 +681,29 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) | |||
664 | if (len <= 0 || buffer->stop || buffer->error) | 681 | if (len <= 0 || buffer->stop || buffer->error) |
665 | return 1; | 682 | return 1; |
666 | while (--len > 0) { | 683 | while (--len > 0) { |
667 | c = *buffer->curr++; | 684 | c = buffer->buffer[buffer->curr++]; |
668 | if (c == '\n') { | 685 | if (c == '\n') { |
669 | if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { | 686 | if (buffer->curr >= buffer->size) |
670 | buffer->stop = 1; | 687 | buffer->stop = 1; |
671 | } | ||
672 | break; | 688 | break; |
673 | } | 689 | } |
674 | *line++ = c; | 690 | *line++ = c; |
675 | if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { | 691 | if (buffer->curr >= buffer->size) { |
676 | buffer->stop = 1; | 692 | buffer->stop = 1; |
677 | break; | 693 | break; |
678 | } | 694 | } |
679 | } | 695 | } |
680 | while (c != '\n' && !buffer->stop) { | 696 | while (c != '\n' && !buffer->stop) { |
681 | c = *buffer->curr++; | 697 | c = buffer->buffer[buffer->curr++]; |
682 | if ((buffer->curr - buffer->buffer) >= (long)buffer->size) { | 698 | if (buffer->curr >= buffer->size) |
683 | buffer->stop = 1; | 699 | buffer->stop = 1; |
684 | } | ||
685 | } | 700 | } |
686 | *line = '\0'; | 701 | *line = '\0'; |
687 | return 0; | 702 | return 0; |
688 | } | 703 | } |
689 | 704 | ||
705 | EXPORT_SYMBOL(snd_info_get_line); | ||
706 | |||
690 | /** | 707 | /** |
691 | * snd_info_get_str - parse a string token | 708 | * snd_info_get_str - parse a string token |
692 | * @dest: the buffer to store the string token | 709 | * @dest: the buffer to store the string token |
@@ -723,6 +740,8 @@ char *snd_info_get_str(char *dest, char *src, int len) | |||
723 | return src; | 740 | return src; |
724 | } | 741 | } |
725 | 742 | ||
743 | EXPORT_SYMBOL(snd_info_get_str); | ||
744 | |||
726 | /** | 745 | /** |
727 | * snd_info_create_entry - create an info entry | 746 | * snd_info_create_entry - create an info entry |
728 | * @name: the proc file name | 747 | * @name: the proc file name |
@@ -774,6 +793,8 @@ struct snd_info_entry *snd_info_create_module_entry(struct module * module, | |||
774 | return entry; | 793 | return entry; |
775 | } | 794 | } |
776 | 795 | ||
796 | EXPORT_SYMBOL(snd_info_create_module_entry); | ||
797 | |||
777 | /** | 798 | /** |
778 | * snd_info_create_card_entry - create an info entry for the given card | 799 | * snd_info_create_card_entry - create an info entry for the given card |
779 | * @card: the card instance | 800 | * @card: the card instance |
@@ -797,6 +818,8 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, | |||
797 | return entry; | 818 | return entry; |
798 | } | 819 | } |
799 | 820 | ||
821 | EXPORT_SYMBOL(snd_info_create_card_entry); | ||
822 | |||
800 | static int snd_info_dev_free_entry(struct snd_device *device) | 823 | static int snd_info_dev_free_entry(struct snd_device *device) |
801 | { | 824 | { |
802 | struct snd_info_entry *entry = device->device_data; | 825 | struct snd_info_entry *entry = device->device_data; |
@@ -867,6 +890,8 @@ int snd_card_proc_new(struct snd_card *card, const char *name, | |||
867 | return 0; | 890 | return 0; |
868 | } | 891 | } |
869 | 892 | ||
893 | EXPORT_SYMBOL(snd_card_proc_new); | ||
894 | |||
870 | /** | 895 | /** |
871 | * snd_info_free_entry - release the info entry | 896 | * snd_info_free_entry - release the info entry |
872 | * @entry: the info entry | 897 | * @entry: the info entry |
@@ -883,6 +908,8 @@ void snd_info_free_entry(struct snd_info_entry * entry) | |||
883 | kfree(entry); | 908 | kfree(entry); |
884 | } | 909 | } |
885 | 910 | ||
911 | EXPORT_SYMBOL(snd_info_free_entry); | ||
912 | |||
886 | /** | 913 | /** |
887 | * snd_info_register - register the info entry | 914 | * snd_info_register - register the info entry |
888 | * @entry: the info entry | 915 | * @entry: the info entry |
@@ -913,6 +940,8 @@ int snd_info_register(struct snd_info_entry * entry) | |||
913 | return 0; | 940 | return 0; |
914 | } | 941 | } |
915 | 942 | ||
943 | EXPORT_SYMBOL(snd_info_register); | ||
944 | |||
916 | /** | 945 | /** |
917 | * snd_info_unregister - de-register the info entry | 946 | * snd_info_unregister - de-register the info entry |
918 | * @entry: the info entry | 947 | * @entry: the info entry |
@@ -937,11 +966,13 @@ int snd_info_unregister(struct snd_info_entry * entry) | |||
937 | return 0; | 966 | return 0; |
938 | } | 967 | } |
939 | 968 | ||
969 | EXPORT_SYMBOL(snd_info_unregister); | ||
970 | |||
940 | /* | 971 | /* |
941 | 972 | ||
942 | */ | 973 | */ |
943 | 974 | ||
944 | static struct snd_info_entry *snd_info_version_entry = NULL; | 975 | static struct snd_info_entry *snd_info_version_entry; |
945 | 976 | ||
946 | static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 977 | static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
947 | { | 978 | { |
@@ -958,7 +989,6 @@ static int __init snd_info_version_init(void) | |||
958 | entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); | 989 | entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL); |
959 | if (entry == NULL) | 990 | if (entry == NULL) |
960 | return -ENOMEM; | 991 | return -ENOMEM; |
961 | entry->c.text.read_size = 256; | ||
962 | entry->c.text.read = snd_info_version_read; | 992 | entry->c.text.read = snd_info_version_read; |
963 | if (snd_info_register(entry) < 0) { | 993 | if (snd_info_register(entry) < 0) { |
964 | snd_info_free_entry(entry); | 994 | snd_info_free_entry(entry); |
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index f9ce854b3d11..bb2c40d0ab66 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c | |||
@@ -64,6 +64,8 @@ int snd_oss_info_register(int dev, int num, char *string) | |||
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | EXPORT_SYMBOL(snd_oss_info_register); | ||
68 | |||
67 | extern void snd_card_info_read_oss(struct snd_info_buffer *buffer); | 69 | extern void snd_card_info_read_oss(struct snd_info_buffer *buffer); |
68 | 70 | ||
69 | static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) | 71 | static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev) |
@@ -117,7 +119,6 @@ int snd_info_minor_register(void) | |||
117 | 119 | ||
118 | memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); | 120 | memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings)); |
119 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) { | 121 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) { |
120 | entry->c.text.read_size = 2048; | ||
121 | entry->c.text.read = snd_sndstat_proc_read; | 122 | entry->c.text.read = snd_sndstat_proc_read; |
122 | if (snd_info_register(entry) < 0) { | 123 | if (snd_info_register(entry) < 0) { |
123 | snd_info_free_entry(entry); | 124 | snd_info_free_entry(entry); |
diff --git a/sound/core/init.c b/sound/core/init.c index 39ed2e5bb0af..4d9258884e44 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -38,12 +38,15 @@ struct snd_shutdown_f_ops { | |||
38 | struct snd_shutdown_f_ops *next; | 38 | struct snd_shutdown_f_ops *next; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | unsigned int snd_cards_lock = 0; /* locked for registering/using */ | 41 | static unsigned int snd_cards_lock; /* locked for registering/using */ |
42 | struct snd_card *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL}; | 42 | struct snd_card *snd_cards[SNDRV_CARDS]; |
43 | DEFINE_RWLOCK(snd_card_rwlock); | 43 | EXPORT_SYMBOL(snd_cards); |
44 | |||
45 | static DEFINE_MUTEX(snd_card_mutex); | ||
44 | 46 | ||
45 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 47 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) |
46 | int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); | 48 | int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); |
49 | EXPORT_SYMBOL(snd_mixer_oss_notify_callback); | ||
47 | #endif | 50 | #endif |
48 | 51 | ||
49 | #ifdef CONFIG_PROC_FS | 52 | #ifdef CONFIG_PROC_FS |
@@ -66,7 +69,6 @@ static inline int init_info_for_card(struct snd_card *card) | |||
66 | snd_printd("unable to create card entry\n"); | 69 | snd_printd("unable to create card entry\n"); |
67 | return err; | 70 | return err; |
68 | } | 71 | } |
69 | entry->c.text.read_size = PAGE_SIZE; | ||
70 | entry->c.text.read = snd_card_id_read; | 72 | entry->c.text.read = snd_card_id_read; |
71 | if (snd_info_register(entry) < 0) { | 73 | if (snd_info_register(entry) < 0) { |
72 | snd_info_free_entry(entry); | 74 | snd_info_free_entry(entry); |
@@ -110,7 +112,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
110 | strlcpy(card->id, xid, sizeof(card->id)); | 112 | strlcpy(card->id, xid, sizeof(card->id)); |
111 | } | 113 | } |
112 | err = 0; | 114 | err = 0; |
113 | write_lock(&snd_card_rwlock); | 115 | mutex_lock(&snd_card_mutex); |
114 | if (idx < 0) { | 116 | if (idx < 0) { |
115 | int idx2; | 117 | int idx2; |
116 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) | 118 | for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) |
@@ -128,12 +130,12 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
128 | else | 130 | else |
129 | err = -ENODEV; | 131 | err = -ENODEV; |
130 | if (idx < 0 || err < 0) { | 132 | if (idx < 0 || err < 0) { |
131 | write_unlock(&snd_card_rwlock); | 133 | mutex_unlock(&snd_card_mutex); |
132 | snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1); | 134 | snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1); |
133 | goto __error; | 135 | goto __error; |
134 | } | 136 | } |
135 | snd_cards_lock |= 1 << idx; /* lock it */ | 137 | snd_cards_lock |= 1 << idx; /* lock it */ |
136 | write_unlock(&snd_card_rwlock); | 138 | mutex_unlock(&snd_card_mutex); |
137 | card->number = idx; | 139 | card->number = idx; |
138 | card->module = module; | 140 | card->module = module; |
139 | INIT_LIST_HEAD(&card->devices); | 141 | INIT_LIST_HEAD(&card->devices); |
@@ -169,6 +171,19 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
169 | return NULL; | 171 | return NULL; |
170 | } | 172 | } |
171 | 173 | ||
174 | EXPORT_SYMBOL(snd_card_new); | ||
175 | |||
176 | /* return non-zero if a card is already locked */ | ||
177 | int snd_card_locked(int card) | ||
178 | { | ||
179 | int locked; | ||
180 | |||
181 | mutex_lock(&snd_card_mutex); | ||
182 | locked = snd_cards_lock & (1 << card); | ||
183 | mutex_unlock(&snd_card_mutex); | ||
184 | return locked; | ||
185 | } | ||
186 | |||
172 | static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig) | 187 | static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig) |
173 | { | 188 | { |
174 | return -ENODEV; | 189 | return -ENODEV; |
@@ -236,9 +251,9 @@ int snd_card_disconnect(struct snd_card *card) | |||
236 | spin_unlock(&card->files_lock); | 251 | spin_unlock(&card->files_lock); |
237 | 252 | ||
238 | /* phase 1: disable fops (user space) operations for ALSA API */ | 253 | /* phase 1: disable fops (user space) operations for ALSA API */ |
239 | write_lock(&snd_card_rwlock); | 254 | mutex_lock(&snd_card_mutex); |
240 | snd_cards[card->number] = NULL; | 255 | snd_cards[card->number] = NULL; |
241 | write_unlock(&snd_card_rwlock); | 256 | mutex_unlock(&snd_card_mutex); |
242 | 257 | ||
243 | /* phase 2: replace file->f_op with special dummy operations */ | 258 | /* phase 2: replace file->f_op with special dummy operations */ |
244 | 259 | ||
@@ -298,6 +313,8 @@ int snd_card_disconnect(struct snd_card *card) | |||
298 | return 0; | 313 | return 0; |
299 | } | 314 | } |
300 | 315 | ||
316 | EXPORT_SYMBOL(snd_card_disconnect); | ||
317 | |||
301 | /** | 318 | /** |
302 | * snd_card_free - frees given soundcard structure | 319 | * snd_card_free - frees given soundcard structure |
303 | * @card: soundcard structure | 320 | * @card: soundcard structure |
@@ -315,9 +332,9 @@ int snd_card_free(struct snd_card *card) | |||
315 | 332 | ||
316 | if (card == NULL) | 333 | if (card == NULL) |
317 | return -EINVAL; | 334 | return -EINVAL; |
318 | write_lock(&snd_card_rwlock); | 335 | mutex_lock(&snd_card_mutex); |
319 | snd_cards[card->number] = NULL; | 336 | snd_cards[card->number] = NULL; |
320 | write_unlock(&snd_card_rwlock); | 337 | mutex_unlock(&snd_card_mutex); |
321 | 338 | ||
322 | #ifdef CONFIG_PM | 339 | #ifdef CONFIG_PM |
323 | wake_up(&card->power_sleep); | 340 | wake_up(&card->power_sleep); |
@@ -353,13 +370,15 @@ int snd_card_free(struct snd_card *card) | |||
353 | card->s_f_ops = s_f_ops->next; | 370 | card->s_f_ops = s_f_ops->next; |
354 | kfree(s_f_ops); | 371 | kfree(s_f_ops); |
355 | } | 372 | } |
356 | write_lock(&snd_card_rwlock); | 373 | mutex_lock(&snd_card_mutex); |
357 | snd_cards_lock &= ~(1 << card->number); | 374 | snd_cards_lock &= ~(1 << card->number); |
358 | write_unlock(&snd_card_rwlock); | 375 | mutex_unlock(&snd_card_mutex); |
359 | kfree(card); | 376 | kfree(card); |
360 | return 0; | 377 | return 0; |
361 | } | 378 | } |
362 | 379 | ||
380 | EXPORT_SYMBOL(snd_card_free); | ||
381 | |||
363 | static void snd_card_free_thread(void * __card) | 382 | static void snd_card_free_thread(void * __card) |
364 | { | 383 | { |
365 | struct snd_card *card = __card; | 384 | struct snd_card *card = __card; |
@@ -405,6 +424,8 @@ int snd_card_free_in_thread(struct snd_card *card) | |||
405 | return -EFAULT; | 424 | return -EFAULT; |
406 | } | 425 | } |
407 | 426 | ||
427 | EXPORT_SYMBOL(snd_card_free_in_thread); | ||
428 | |||
408 | static void choose_default_id(struct snd_card *card) | 429 | static void choose_default_id(struct snd_card *card) |
409 | { | 430 | { |
410 | int i, len, idx_flag = 0, loops = SNDRV_CARDS; | 431 | int i, len, idx_flag = 0, loops = SNDRV_CARDS; |
@@ -487,16 +508,16 @@ int snd_card_register(struct snd_card *card) | |||
487 | snd_assert(card != NULL, return -EINVAL); | 508 | snd_assert(card != NULL, return -EINVAL); |
488 | if ((err = snd_device_register_all(card)) < 0) | 509 | if ((err = snd_device_register_all(card)) < 0) |
489 | return err; | 510 | return err; |
490 | write_lock(&snd_card_rwlock); | 511 | mutex_lock(&snd_card_mutex); |
491 | if (snd_cards[card->number]) { | 512 | if (snd_cards[card->number]) { |
492 | /* already registered */ | 513 | /* already registered */ |
493 | write_unlock(&snd_card_rwlock); | 514 | mutex_unlock(&snd_card_mutex); |
494 | return 0; | 515 | return 0; |
495 | } | 516 | } |
496 | if (card->id[0] == '\0') | 517 | if (card->id[0] == '\0') |
497 | choose_default_id(card); | 518 | choose_default_id(card); |
498 | snd_cards[card->number] = card; | 519 | snd_cards[card->number] = card; |
499 | write_unlock(&snd_card_rwlock); | 520 | mutex_unlock(&snd_card_mutex); |
500 | init_info_for_card(card); | 521 | init_info_for_card(card); |
501 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | 522 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) |
502 | if (snd_mixer_oss_notify_callback) | 523 | if (snd_mixer_oss_notify_callback) |
@@ -505,8 +526,10 @@ int snd_card_register(struct snd_card *card) | |||
505 | return 0; | 526 | return 0; |
506 | } | 527 | } |
507 | 528 | ||
529 | EXPORT_SYMBOL(snd_card_register); | ||
530 | |||
508 | #ifdef CONFIG_PROC_FS | 531 | #ifdef CONFIG_PROC_FS |
509 | static struct snd_info_entry *snd_card_info_entry = NULL; | 532 | static struct snd_info_entry *snd_card_info_entry; |
510 | 533 | ||
511 | static void snd_card_info_read(struct snd_info_entry *entry, | 534 | static void snd_card_info_read(struct snd_info_entry *entry, |
512 | struct snd_info_buffer *buffer) | 535 | struct snd_info_buffer *buffer) |
@@ -515,7 +538,7 @@ static void snd_card_info_read(struct snd_info_entry *entry, | |||
515 | struct snd_card *card; | 538 | struct snd_card *card; |
516 | 539 | ||
517 | for (idx = count = 0; idx < SNDRV_CARDS; idx++) { | 540 | for (idx = count = 0; idx < SNDRV_CARDS; idx++) { |
518 | read_lock(&snd_card_rwlock); | 541 | mutex_lock(&snd_card_mutex); |
519 | if ((card = snd_cards[idx]) != NULL) { | 542 | if ((card = snd_cards[idx]) != NULL) { |
520 | count++; | 543 | count++; |
521 | snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n", | 544 | snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n", |
@@ -526,7 +549,7 @@ static void snd_card_info_read(struct snd_info_entry *entry, | |||
526 | snd_iprintf(buffer, " %s\n", | 549 | snd_iprintf(buffer, " %s\n", |
527 | card->longname); | 550 | card->longname); |
528 | } | 551 | } |
529 | read_unlock(&snd_card_rwlock); | 552 | mutex_unlock(&snd_card_mutex); |
530 | } | 553 | } |
531 | if (!count) | 554 | if (!count) |
532 | snd_iprintf(buffer, "--- no soundcards ---\n"); | 555 | snd_iprintf(buffer, "--- no soundcards ---\n"); |
@@ -540,12 +563,12 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer) | |||
540 | struct snd_card *card; | 563 | struct snd_card *card; |
541 | 564 | ||
542 | for (idx = count = 0; idx < SNDRV_CARDS; idx++) { | 565 | for (idx = count = 0; idx < SNDRV_CARDS; idx++) { |
543 | read_lock(&snd_card_rwlock); | 566 | mutex_lock(&snd_card_mutex); |
544 | if ((card = snd_cards[idx]) != NULL) { | 567 | if ((card = snd_cards[idx]) != NULL) { |
545 | count++; | 568 | count++; |
546 | snd_iprintf(buffer, "%s\n", card->longname); | 569 | snd_iprintf(buffer, "%s\n", card->longname); |
547 | } | 570 | } |
548 | read_unlock(&snd_card_rwlock); | 571 | mutex_unlock(&snd_card_mutex); |
549 | } | 572 | } |
550 | if (!count) { | 573 | if (!count) { |
551 | snd_iprintf(buffer, "--- no soundcards ---\n"); | 574 | snd_iprintf(buffer, "--- no soundcards ---\n"); |
@@ -563,11 +586,11 @@ static void snd_card_module_info_read(struct snd_info_entry *entry, | |||
563 | struct snd_card *card; | 586 | struct snd_card *card; |
564 | 587 | ||
565 | for (idx = 0; idx < SNDRV_CARDS; idx++) { | 588 | for (idx = 0; idx < SNDRV_CARDS; idx++) { |
566 | read_lock(&snd_card_rwlock); | 589 | mutex_lock(&snd_card_mutex); |
567 | if ((card = snd_cards[idx]) != NULL) | 590 | if ((card = snd_cards[idx]) != NULL) |
568 | snd_iprintf(buffer, "%2i %s\n", | 591 | snd_iprintf(buffer, "%2i %s\n", |
569 | idx, card->module->name); | 592 | idx, card->module->name); |
570 | read_unlock(&snd_card_rwlock); | 593 | mutex_unlock(&snd_card_mutex); |
571 | } | 594 | } |
572 | } | 595 | } |
573 | #endif | 596 | #endif |
@@ -579,7 +602,6 @@ int __init snd_card_info_init(void) | |||
579 | entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); | 602 | entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); |
580 | if (! entry) | 603 | if (! entry) |
581 | return -ENOMEM; | 604 | return -ENOMEM; |
582 | entry->c.text.read_size = PAGE_SIZE; | ||
583 | entry->c.text.read = snd_card_info_read; | 605 | entry->c.text.read = snd_card_info_read; |
584 | if (snd_info_register(entry) < 0) { | 606 | if (snd_info_register(entry) < 0) { |
585 | snd_info_free_entry(entry); | 607 | snd_info_free_entry(entry); |
@@ -590,7 +612,6 @@ int __init snd_card_info_init(void) | |||
590 | #ifdef MODULE | 612 | #ifdef MODULE |
591 | entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); | 613 | entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); |
592 | if (entry) { | 614 | if (entry) { |
593 | entry->c.text.read_size = PAGE_SIZE; | ||
594 | entry->c.text.read = snd_card_module_info_read; | 615 | entry->c.text.read = snd_card_module_info_read; |
595 | if (snd_info_register(entry) < 0) | 616 | if (snd_info_register(entry) < 0) |
596 | snd_info_free_entry(entry); | 617 | snd_info_free_entry(entry); |
@@ -644,6 +665,8 @@ int snd_component_add(struct snd_card *card, const char *component) | |||
644 | return 0; | 665 | return 0; |
645 | } | 666 | } |
646 | 667 | ||
668 | EXPORT_SYMBOL(snd_component_add); | ||
669 | |||
647 | /** | 670 | /** |
648 | * snd_card_file_add - add the file to the file list of the card | 671 | * snd_card_file_add - add the file to the file list of the card |
649 | * @card: soundcard structure | 672 | * @card: soundcard structure |
@@ -676,6 +699,8 @@ int snd_card_file_add(struct snd_card *card, struct file *file) | |||
676 | return 0; | 699 | return 0; |
677 | } | 700 | } |
678 | 701 | ||
702 | EXPORT_SYMBOL(snd_card_file_add); | ||
703 | |||
679 | /** | 704 | /** |
680 | * snd_card_file_remove - remove the file from the file list | 705 | * snd_card_file_remove - remove the file from the file list |
681 | * @card: soundcard structure | 706 | * @card: soundcard structure |
@@ -717,6 +742,8 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) | |||
717 | return 0; | 742 | return 0; |
718 | } | 743 | } |
719 | 744 | ||
745 | EXPORT_SYMBOL(snd_card_file_remove); | ||
746 | |||
720 | #ifdef CONFIG_PM | 747 | #ifdef CONFIG_PM |
721 | /** | 748 | /** |
722 | * snd_power_wait - wait until the power-state is changed. | 749 | * snd_power_wait - wait until the power-state is changed. |
@@ -753,4 +780,5 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state) | |||
753 | return result; | 780 | return result; |
754 | } | 781 | } |
755 | 782 | ||
783 | EXPORT_SYMBOL(snd_power_wait); | ||
756 | #endif /* CONFIG_PM */ | 784 | #endif /* CONFIG_PM */ |
diff --git a/sound/core/isadma.c b/sound/core/isadma.c index 1a378951da5b..d52398727f0a 100644 --- a/sound/core/isadma.c +++ b/sound/core/isadma.c | |||
@@ -56,6 +56,8 @@ void snd_dma_program(unsigned long dma, | |||
56 | release_dma_lock(flags); | 56 | release_dma_lock(flags); |
57 | } | 57 | } |
58 | 58 | ||
59 | EXPORT_SYMBOL(snd_dma_program); | ||
60 | |||
59 | /** | 61 | /** |
60 | * snd_dma_disable - stop the ISA DMA transfer | 62 | * snd_dma_disable - stop the ISA DMA transfer |
61 | * @dma: the dma number | 63 | * @dma: the dma number |
@@ -72,6 +74,8 @@ void snd_dma_disable(unsigned long dma) | |||
72 | release_dma_lock(flags); | 74 | release_dma_lock(flags); |
73 | } | 75 | } |
74 | 76 | ||
77 | EXPORT_SYMBOL(snd_dma_disable); | ||
78 | |||
75 | /** | 79 | /** |
76 | * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes | 80 | * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes |
77 | * @dma: the dma number | 81 | * @dma: the dma number |
@@ -101,3 +105,5 @@ unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) | |||
101 | else | 105 | else |
102 | return size - result; | 106 | return size - result; |
103 | } | 107 | } |
108 | |||
109 | EXPORT_SYMBOL(snd_dma_pointer); | ||
diff --git a/sound/core/memory.c b/sound/core/memory.c index 862d62d2e144..fe59850be868 100644 --- a/sound/core/memory.c +++ b/sound/core/memory.c | |||
@@ -21,6 +21,7 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
24 | #include <linux/module.h> | ||
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | 27 | ||
@@ -55,6 +56,8 @@ int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size | |||
55 | #endif | 56 | #endif |
56 | } | 57 | } |
57 | 58 | ||
59 | EXPORT_SYMBOL(copy_to_user_fromio); | ||
60 | |||
58 | /** | 61 | /** |
59 | * copy_from_user_toio - copy data from user-space to mmio-space | 62 | * copy_from_user_toio - copy data from user-space to mmio-space |
60 | * @dst: the destination pointer on mmio-space | 63 | * @dst: the destination pointer on mmio-space |
@@ -85,3 +88,5 @@ int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size | |||
85 | return 0; | 88 | return 0; |
86 | #endif | 89 | #endif |
87 | } | 90 | } |
91 | |||
92 | EXPORT_SYMBOL(copy_from_user_toio); | ||
diff --git a/sound/core/misc.c b/sound/core/misc.c index b53e563c09e6..03fc711f4127 100644 --- a/sound/core/misc.c +++ b/sound/core/misc.c | |||
@@ -34,6 +34,8 @@ void release_and_free_resource(struct resource *res) | |||
34 | } | 34 | } |
35 | } | 35 | } |
36 | 36 | ||
37 | EXPORT_SYMBOL(release_and_free_resource); | ||
38 | |||
37 | #ifdef CONFIG_SND_VERBOSE_PRINTK | 39 | #ifdef CONFIG_SND_VERBOSE_PRINTK |
38 | void snd_verbose_printk(const char *file, int line, const char *format, ...) | 40 | void snd_verbose_printk(const char *file, int line, const char *format, ...) |
39 | { | 41 | { |
@@ -51,6 +53,8 @@ void snd_verbose_printk(const char *file, int line, const char *format, ...) | |||
51 | vprintk(format, args); | 53 | vprintk(format, args); |
52 | va_end(args); | 54 | va_end(args); |
53 | } | 55 | } |
56 | |||
57 | EXPORT_SYMBOL(snd_verbose_printk); | ||
54 | #endif | 58 | #endif |
55 | 59 | ||
56 | #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) | 60 | #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) |
@@ -71,4 +75,6 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) | |||
71 | va_end(args); | 75 | va_end(args); |
72 | 76 | ||
73 | } | 77 | } |
78 | |||
79 | EXPORT_SYMBOL(snd_verbose_printd); | ||
74 | #endif | 80 | #endif |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 9c68bc3f97aa..71b5080fa66d 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -1182,9 +1182,7 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer) | |||
1182 | return; | 1182 | return; |
1183 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 1183 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
1184 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 1184 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
1185 | entry->c.text.read_size = 8192; | ||
1186 | entry->c.text.read = snd_mixer_oss_proc_read; | 1185 | entry->c.text.read = snd_mixer_oss_proc_read; |
1187 | entry->c.text.write_size = 8192; | ||
1188 | entry->c.text.write = snd_mixer_oss_proc_write; | 1186 | entry->c.text.write = snd_mixer_oss_proc_write; |
1189 | entry->private_data = mixer; | 1187 | entry->private_data = mixer; |
1190 | if (snd_info_register(entry) < 0) { | 1188 | if (snd_info_register(entry) < 0) { |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index ac990bf0b48f..f5ff4f4a16ee 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -45,7 +45,7 @@ | |||
45 | 45 | ||
46 | #define OSS_ALSAEMULVER _SIOR ('M', 249, int) | 46 | #define OSS_ALSAEMULVER _SIOR ('M', 249, int) |
47 | 47 | ||
48 | static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; | 48 | static int dsp_map[SNDRV_CARDS]; |
49 | static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; | 49 | static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; |
50 | static int nonblock_open = 1; | 50 | static int nonblock_open = 1; |
51 | 51 | ||
@@ -78,6 +78,487 @@ static inline void snd_leave_user(mm_segment_t fs) | |||
78 | set_fs(fs); | 78 | set_fs(fs); |
79 | } | 79 | } |
80 | 80 | ||
81 | /* | ||
82 | * helper functions to process hw_params | ||
83 | */ | ||
84 | static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin) | ||
85 | { | ||
86 | int changed = 0; | ||
87 | if (i->min < min) { | ||
88 | i->min = min; | ||
89 | i->openmin = openmin; | ||
90 | changed = 1; | ||
91 | } else if (i->min == min && !i->openmin && openmin) { | ||
92 | i->openmin = 1; | ||
93 | changed = 1; | ||
94 | } | ||
95 | if (i->integer) { | ||
96 | if (i->openmin) { | ||
97 | i->min++; | ||
98 | i->openmin = 0; | ||
99 | } | ||
100 | } | ||
101 | if (snd_interval_checkempty(i)) { | ||
102 | snd_interval_none(i); | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | return changed; | ||
106 | } | ||
107 | |||
108 | static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax) | ||
109 | { | ||
110 | int changed = 0; | ||
111 | if (i->max > max) { | ||
112 | i->max = max; | ||
113 | i->openmax = openmax; | ||
114 | changed = 1; | ||
115 | } else if (i->max == max && !i->openmax && openmax) { | ||
116 | i->openmax = 1; | ||
117 | changed = 1; | ||
118 | } | ||
119 | if (i->integer) { | ||
120 | if (i->openmax) { | ||
121 | i->max--; | ||
122 | i->openmax = 0; | ||
123 | } | ||
124 | } | ||
125 | if (snd_interval_checkempty(i)) { | ||
126 | snd_interval_none(i); | ||
127 | return -EINVAL; | ||
128 | } | ||
129 | return changed; | ||
130 | } | ||
131 | |||
132 | static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) | ||
133 | { | ||
134 | struct snd_interval t; | ||
135 | t.empty = 0; | ||
136 | t.min = t.max = val; | ||
137 | t.openmin = t.openmax = 0; | ||
138 | t.integer = 1; | ||
139 | return snd_interval_refine(i, &t); | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * snd_pcm_hw_param_value_min | ||
144 | * @params: the hw_params instance | ||
145 | * @var: parameter to retrieve | ||
146 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
147 | * | ||
148 | * Return the minimum value for field PAR. | ||
149 | */ | ||
150 | static unsigned int | ||
151 | snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, | ||
152 | snd_pcm_hw_param_t var, int *dir) | ||
153 | { | ||
154 | if (hw_is_mask(var)) { | ||
155 | if (dir) | ||
156 | *dir = 0; | ||
157 | return snd_mask_min(hw_param_mask_c(params, var)); | ||
158 | } | ||
159 | if (hw_is_interval(var)) { | ||
160 | const struct snd_interval *i = hw_param_interval_c(params, var); | ||
161 | if (dir) | ||
162 | *dir = i->openmin; | ||
163 | return snd_interval_min(i); | ||
164 | } | ||
165 | return -EINVAL; | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * snd_pcm_hw_param_value_max | ||
170 | * @params: the hw_params instance | ||
171 | * @var: parameter to retrieve | ||
172 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
173 | * | ||
174 | * Return the maximum value for field PAR. | ||
175 | */ | ||
176 | static unsigned int | ||
177 | snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, | ||
178 | snd_pcm_hw_param_t var, int *dir) | ||
179 | { | ||
180 | if (hw_is_mask(var)) { | ||
181 | if (dir) | ||
182 | *dir = 0; | ||
183 | return snd_mask_max(hw_param_mask_c(params, var)); | ||
184 | } | ||
185 | if (hw_is_interval(var)) { | ||
186 | const struct snd_interval *i = hw_param_interval_c(params, var); | ||
187 | if (dir) | ||
188 | *dir = - (int) i->openmax; | ||
189 | return snd_interval_max(i); | ||
190 | } | ||
191 | return -EINVAL; | ||
192 | } | ||
193 | |||
194 | static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params, | ||
195 | snd_pcm_hw_param_t var, | ||
196 | const struct snd_mask *val) | ||
197 | { | ||
198 | int changed; | ||
199 | changed = snd_mask_refine(hw_param_mask(params, var), val); | ||
200 | if (changed) { | ||
201 | params->cmask |= 1 << var; | ||
202 | params->rmask |= 1 << var; | ||
203 | } | ||
204 | return changed; | ||
205 | } | ||
206 | |||
207 | static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, | ||
208 | struct snd_pcm_hw_params *params, | ||
209 | snd_pcm_hw_param_t var, | ||
210 | const struct snd_mask *val) | ||
211 | { | ||
212 | int changed = _snd_pcm_hw_param_mask(params, var, val); | ||
213 | if (changed < 0) | ||
214 | return changed; | ||
215 | if (params->rmask) { | ||
216 | int err = snd_pcm_hw_refine(pcm, params); | ||
217 | if (err < 0) | ||
218 | return err; | ||
219 | } | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, | ||
224 | snd_pcm_hw_param_t var, unsigned int val, | ||
225 | int dir) | ||
226 | { | ||
227 | int changed; | ||
228 | int open = 0; | ||
229 | if (dir) { | ||
230 | if (dir > 0) { | ||
231 | open = 1; | ||
232 | } else if (dir < 0) { | ||
233 | if (val > 0) { | ||
234 | open = 1; | ||
235 | val--; | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | if (hw_is_mask(var)) | ||
240 | changed = snd_mask_refine_min(hw_param_mask(params, var), | ||
241 | val + !!open); | ||
242 | else if (hw_is_interval(var)) | ||
243 | changed = snd_interval_refine_min(hw_param_interval(params, var), | ||
244 | val, open); | ||
245 | else | ||
246 | return -EINVAL; | ||
247 | if (changed) { | ||
248 | params->cmask |= 1 << var; | ||
249 | params->rmask |= 1 << var; | ||
250 | } | ||
251 | return changed; | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * snd_pcm_hw_param_min | ||
256 | * @pcm: PCM instance | ||
257 | * @params: the hw_params instance | ||
258 | * @var: parameter to retrieve | ||
259 | * @val: minimal value | ||
260 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
261 | * | ||
262 | * Inside configuration space defined by PARAMS remove from PAR all | ||
263 | * values < VAL. Reduce configuration space accordingly. | ||
264 | * Return new minimum or -EINVAL if the configuration space is empty | ||
265 | */ | ||
266 | static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, | ||
267 | struct snd_pcm_hw_params *params, | ||
268 | snd_pcm_hw_param_t var, unsigned int val, | ||
269 | int *dir) | ||
270 | { | ||
271 | int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); | ||
272 | if (changed < 0) | ||
273 | return changed; | ||
274 | if (params->rmask) { | ||
275 | int err = snd_pcm_hw_refine(pcm, params); | ||
276 | if (err < 0) | ||
277 | return err; | ||
278 | } | ||
279 | return snd_pcm_hw_param_value_min(params, var, dir); | ||
280 | } | ||
281 | |||
282 | static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params, | ||
283 | snd_pcm_hw_param_t var, unsigned int val, | ||
284 | int dir) | ||
285 | { | ||
286 | int changed; | ||
287 | int open = 0; | ||
288 | if (dir) { | ||
289 | if (dir < 0) { | ||
290 | open = 1; | ||
291 | } else if (dir > 0) { | ||
292 | open = 1; | ||
293 | val++; | ||
294 | } | ||
295 | } | ||
296 | if (hw_is_mask(var)) { | ||
297 | if (val == 0 && open) { | ||
298 | snd_mask_none(hw_param_mask(params, var)); | ||
299 | changed = -EINVAL; | ||
300 | } else | ||
301 | changed = snd_mask_refine_max(hw_param_mask(params, var), | ||
302 | val - !!open); | ||
303 | } else if (hw_is_interval(var)) | ||
304 | changed = snd_interval_refine_max(hw_param_interval(params, var), | ||
305 | val, open); | ||
306 | else | ||
307 | return -EINVAL; | ||
308 | if (changed) { | ||
309 | params->cmask |= 1 << var; | ||
310 | params->rmask |= 1 << var; | ||
311 | } | ||
312 | return changed; | ||
313 | } | ||
314 | |||
315 | /** | ||
316 | * snd_pcm_hw_param_max | ||
317 | * @pcm: PCM instance | ||
318 | * @params: the hw_params instance | ||
319 | * @var: parameter to retrieve | ||
320 | * @val: maximal value | ||
321 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
322 | * | ||
323 | * Inside configuration space defined by PARAMS remove from PAR all | ||
324 | * values >= VAL + 1. Reduce configuration space accordingly. | ||
325 | * Return new maximum or -EINVAL if the configuration space is empty | ||
326 | */ | ||
327 | static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, | ||
328 | struct snd_pcm_hw_params *params, | ||
329 | snd_pcm_hw_param_t var, unsigned int val, | ||
330 | int *dir) | ||
331 | { | ||
332 | int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); | ||
333 | if (changed < 0) | ||
334 | return changed; | ||
335 | if (params->rmask) { | ||
336 | int err = snd_pcm_hw_refine(pcm, params); | ||
337 | if (err < 0) | ||
338 | return err; | ||
339 | } | ||
340 | return snd_pcm_hw_param_value_max(params, var, dir); | ||
341 | } | ||
342 | |||
343 | static int boundary_sub(int a, int adir, | ||
344 | int b, int bdir, | ||
345 | int *c, int *cdir) | ||
346 | { | ||
347 | adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0); | ||
348 | bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0); | ||
349 | *c = a - b; | ||
350 | *cdir = adir - bdir; | ||
351 | if (*cdir == -2) { | ||
352 | (*c)--; | ||
353 | } else if (*cdir == 2) { | ||
354 | (*c)++; | ||
355 | } | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static int boundary_lt(unsigned int a, int adir, | ||
360 | unsigned int b, int bdir) | ||
361 | { | ||
362 | if (adir < 0) { | ||
363 | a--; | ||
364 | adir = 1; | ||
365 | } else if (adir > 0) | ||
366 | adir = 1; | ||
367 | if (bdir < 0) { | ||
368 | b--; | ||
369 | bdir = 1; | ||
370 | } else if (bdir > 0) | ||
371 | bdir = 1; | ||
372 | return a < b || (a == b && adir < bdir); | ||
373 | } | ||
374 | |||
375 | /* Return 1 if min is nearer to best than max */ | ||
376 | static int boundary_nearer(int min, int mindir, | ||
377 | int best, int bestdir, | ||
378 | int max, int maxdir) | ||
379 | { | ||
380 | int dmin, dmindir; | ||
381 | int dmax, dmaxdir; | ||
382 | boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir); | ||
383 | boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir); | ||
384 | return boundary_lt(dmin, dmindir, dmax, dmaxdir); | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * snd_pcm_hw_param_near | ||
389 | * @pcm: PCM instance | ||
390 | * @params: the hw_params instance | ||
391 | * @var: parameter to retrieve | ||
392 | * @best: value to set | ||
393 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
394 | * | ||
395 | * Inside configuration space defined by PARAMS set PAR to the available value | ||
396 | * nearest to VAL. Reduce configuration space accordingly. | ||
397 | * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS, | ||
398 | * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. | ||
399 | * Return the value found. | ||
400 | */ | ||
401 | static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, | ||
402 | struct snd_pcm_hw_params *params, | ||
403 | snd_pcm_hw_param_t var, unsigned int best, | ||
404 | int *dir) | ||
405 | { | ||
406 | struct snd_pcm_hw_params *save = NULL; | ||
407 | int v; | ||
408 | unsigned int saved_min; | ||
409 | int last = 0; | ||
410 | int min, max; | ||
411 | int mindir, maxdir; | ||
412 | int valdir = dir ? *dir : 0; | ||
413 | /* FIXME */ | ||
414 | if (best > INT_MAX) | ||
415 | best = INT_MAX; | ||
416 | min = max = best; | ||
417 | mindir = maxdir = valdir; | ||
418 | if (maxdir > 0) | ||
419 | maxdir = 0; | ||
420 | else if (maxdir == 0) | ||
421 | maxdir = -1; | ||
422 | else { | ||
423 | maxdir = 1; | ||
424 | max--; | ||
425 | } | ||
426 | save = kmalloc(sizeof(*save), GFP_KERNEL); | ||
427 | if (save == NULL) | ||
428 | return -ENOMEM; | ||
429 | *save = *params; | ||
430 | saved_min = min; | ||
431 | min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir); | ||
432 | if (min >= 0) { | ||
433 | struct snd_pcm_hw_params *params1; | ||
434 | if (max < 0) | ||
435 | goto _end; | ||
436 | if ((unsigned int)min == saved_min && mindir == valdir) | ||
437 | goto _end; | ||
438 | params1 = kmalloc(sizeof(*params1), GFP_KERNEL); | ||
439 | if (params1 == NULL) { | ||
440 | kfree(save); | ||
441 | return -ENOMEM; | ||
442 | } | ||
443 | *params1 = *save; | ||
444 | max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir); | ||
445 | if (max < 0) { | ||
446 | kfree(params1); | ||
447 | goto _end; | ||
448 | } | ||
449 | if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) { | ||
450 | *params = *params1; | ||
451 | last = 1; | ||
452 | } | ||
453 | kfree(params1); | ||
454 | } else { | ||
455 | *params = *save; | ||
456 | max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); | ||
457 | snd_assert(max >= 0, return -EINVAL); | ||
458 | last = 1; | ||
459 | } | ||
460 | _end: | ||
461 | kfree(save); | ||
462 | if (last) | ||
463 | v = snd_pcm_hw_param_last(pcm, params, var, dir); | ||
464 | else | ||
465 | v = snd_pcm_hw_param_first(pcm, params, var, dir); | ||
466 | snd_assert(v >= 0, return -EINVAL); | ||
467 | return v; | ||
468 | } | ||
469 | |||
470 | static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, | ||
471 | snd_pcm_hw_param_t var, unsigned int val, | ||
472 | int dir) | ||
473 | { | ||
474 | int changed; | ||
475 | if (hw_is_mask(var)) { | ||
476 | struct snd_mask *m = hw_param_mask(params, var); | ||
477 | if (val == 0 && dir < 0) { | ||
478 | changed = -EINVAL; | ||
479 | snd_mask_none(m); | ||
480 | } else { | ||
481 | if (dir > 0) | ||
482 | val++; | ||
483 | else if (dir < 0) | ||
484 | val--; | ||
485 | changed = snd_mask_refine_set(hw_param_mask(params, var), val); | ||
486 | } | ||
487 | } else if (hw_is_interval(var)) { | ||
488 | struct snd_interval *i = hw_param_interval(params, var); | ||
489 | if (val == 0 && dir < 0) { | ||
490 | changed = -EINVAL; | ||
491 | snd_interval_none(i); | ||
492 | } else if (dir == 0) | ||
493 | changed = snd_interval_refine_set(i, val); | ||
494 | else { | ||
495 | struct snd_interval t; | ||
496 | t.openmin = 1; | ||
497 | t.openmax = 1; | ||
498 | t.empty = 0; | ||
499 | t.integer = 0; | ||
500 | if (dir < 0) { | ||
501 | t.min = val - 1; | ||
502 | t.max = val; | ||
503 | } else { | ||
504 | t.min = val; | ||
505 | t.max = val+1; | ||
506 | } | ||
507 | changed = snd_interval_refine(i, &t); | ||
508 | } | ||
509 | } else | ||
510 | return -EINVAL; | ||
511 | if (changed) { | ||
512 | params->cmask |= 1 << var; | ||
513 | params->rmask |= 1 << var; | ||
514 | } | ||
515 | return changed; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * snd_pcm_hw_param_set | ||
520 | * @pcm: PCM instance | ||
521 | * @params: the hw_params instance | ||
522 | * @var: parameter to retrieve | ||
523 | * @val: value to set | ||
524 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
525 | * | ||
526 | * Inside configuration space defined by PARAMS remove from PAR all | ||
527 | * values != VAL. Reduce configuration space accordingly. | ||
528 | * Return VAL or -EINVAL if the configuration space is empty | ||
529 | */ | ||
530 | static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, | ||
531 | struct snd_pcm_hw_params *params, | ||
532 | snd_pcm_hw_param_t var, unsigned int val, | ||
533 | int dir) | ||
534 | { | ||
535 | int changed = _snd_pcm_hw_param_set(params, var, val, dir); | ||
536 | if (changed < 0) | ||
537 | return changed; | ||
538 | if (params->rmask) { | ||
539 | int err = snd_pcm_hw_refine(pcm, params); | ||
540 | if (err < 0) | ||
541 | return err; | ||
542 | } | ||
543 | return snd_pcm_hw_param_value(params, var, NULL); | ||
544 | } | ||
545 | |||
546 | static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, | ||
547 | snd_pcm_hw_param_t var) | ||
548 | { | ||
549 | int changed; | ||
550 | changed = snd_interval_setinteger(hw_param_interval(params, var)); | ||
551 | if (changed) { | ||
552 | params->cmask |= 1 << var; | ||
553 | params->rmask |= 1 << var; | ||
554 | } | ||
555 | return changed; | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * plugin | ||
560 | */ | ||
561 | |||
81 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | 562 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS |
82 | static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) | 563 | static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream) |
83 | { | 564 | { |
@@ -203,7 +684,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
203 | oss_buffer_size = snd_pcm_plug_client_size(substream, | 684 | oss_buffer_size = snd_pcm_plug_client_size(substream, |
204 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; | 685 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; |
205 | oss_buffer_size = 1 << ld2(oss_buffer_size); | 686 | oss_buffer_size = 1 << ld2(oss_buffer_size); |
206 | if (atomic_read(&runtime->mmap_count)) { | 687 | if (atomic_read(&substream->mmap_count)) { |
207 | if (oss_buffer_size > runtime->oss.mmap_bytes) | 688 | if (oss_buffer_size > runtime->oss.mmap_bytes) |
208 | oss_buffer_size = runtime->oss.mmap_bytes; | 689 | oss_buffer_size = runtime->oss.mmap_bytes; |
209 | } | 690 | } |
@@ -338,7 +819,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
338 | goto failure; | 819 | goto failure; |
339 | } | 820 | } |
340 | 821 | ||
341 | if (atomic_read(&runtime->mmap_count)) | 822 | if (atomic_read(&substream->mmap_count)) |
342 | direct = 1; | 823 | direct = 1; |
343 | else | 824 | else |
344 | direct = substream->oss.setup.direct; | 825 | direct = substream->oss.setup.direct; |
@@ -347,7 +828,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
347 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); | 828 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); |
348 | _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); | 829 | _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); |
349 | snd_mask_none(&mask); | 830 | snd_mask_none(&mask); |
350 | if (atomic_read(&runtime->mmap_count)) | 831 | if (atomic_read(&substream->mmap_count)) |
351 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); | 832 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); |
352 | else { | 833 | else { |
353 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); | 834 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); |
@@ -466,7 +947,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
466 | } else { | 947 | } else { |
467 | sw_params->start_threshold = runtime->boundary; | 948 | sw_params->start_threshold = runtime->boundary; |
468 | } | 949 | } |
469 | if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 950 | if (atomic_read(&substream->mmap_count) || |
951 | substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
470 | sw_params->stop_threshold = runtime->boundary; | 952 | sw_params->stop_threshold = runtime->boundary; |
471 | else | 953 | else |
472 | sw_params->stop_threshold = runtime->buffer_size; | 954 | sw_params->stop_threshold = runtime->buffer_size; |
@@ -476,7 +958,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
476 | sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 958 | sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
477 | 1 : runtime->period_size; | 959 | 1 : runtime->period_size; |
478 | sw_params->xfer_align = 1; | 960 | sw_params->xfer_align = 1; |
479 | if (atomic_read(&runtime->mmap_count) || | 961 | if (atomic_read(&substream->mmap_count) || |
480 | substream->oss.setup.nosilence) { | 962 | substream->oss.setup.nosilence) { |
481 | sw_params->silence_threshold = 0; | 963 | sw_params->silence_threshold = 0; |
482 | sw_params->silence_size = 0; | 964 | sw_params->silence_size = 0; |
@@ -820,7 +1302,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
820 | ssize_t tmp; | 1302 | ssize_t tmp; |
821 | struct snd_pcm_runtime *runtime = substream->runtime; | 1303 | struct snd_pcm_runtime *runtime = substream->runtime; |
822 | 1304 | ||
823 | if (atomic_read(&runtime->mmap_count)) | 1305 | if (atomic_read(&substream->mmap_count)) |
824 | return -ENXIO; | 1306 | return -ENXIO; |
825 | 1307 | ||
826 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) | 1308 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) |
@@ -850,7 +1332,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
850 | if (runtime->oss.period_ptr == 0 || | 1332 | if (runtime->oss.period_ptr == 0 || |
851 | runtime->oss.period_ptr == runtime->oss.buffer_used) | 1333 | runtime->oss.period_ptr == runtime->oss.buffer_used) |
852 | runtime->oss.buffer_used = 0; | 1334 | runtime->oss.buffer_used = 0; |
853 | else if ((substream->ffile->f_flags & O_NONBLOCK) != 0) | 1335 | else if ((substream->f_flags & O_NONBLOCK) != 0) |
854 | return xfer > 0 ? xfer : -EAGAIN; | 1336 | return xfer > 0 ? xfer : -EAGAIN; |
855 | } | 1337 | } |
856 | } else { | 1338 | } else { |
@@ -863,7 +1345,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
863 | buf += tmp; | 1345 | buf += tmp; |
864 | bytes -= tmp; | 1346 | bytes -= tmp; |
865 | xfer += tmp; | 1347 | xfer += tmp; |
866 | if ((substream->ffile->f_flags & O_NONBLOCK) != 0 && | 1348 | if ((substream->f_flags & O_NONBLOCK) != 0 && |
867 | tmp != runtime->oss.period_bytes) | 1349 | tmp != runtime->oss.period_bytes) |
868 | break; | 1350 | break; |
869 | } | 1351 | } |
@@ -910,7 +1392,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use | |||
910 | ssize_t tmp; | 1392 | ssize_t tmp; |
911 | struct snd_pcm_runtime *runtime = substream->runtime; | 1393 | struct snd_pcm_runtime *runtime = substream->runtime; |
912 | 1394 | ||
913 | if (atomic_read(&runtime->mmap_count)) | 1395 | if (atomic_read(&substream->mmap_count)) |
914 | return -ENXIO; | 1396 | return -ENXIO; |
915 | 1397 | ||
916 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) | 1398 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) |
@@ -1040,7 +1522,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1040 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; | 1522 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; |
1041 | if (substream != NULL) { | 1523 | if (substream != NULL) { |
1042 | runtime = substream->runtime; | 1524 | runtime = substream->runtime; |
1043 | if (atomic_read(&runtime->mmap_count)) | 1525 | if (atomic_read(&substream->mmap_count)) |
1044 | goto __direct; | 1526 | goto __direct; |
1045 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) | 1527 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) |
1046 | return err; | 1528 | return err; |
@@ -1101,10 +1583,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1101 | * finish sync: drain the buffer | 1583 | * finish sync: drain the buffer |
1102 | */ | 1584 | */ |
1103 | __direct: | 1585 | __direct: |
1104 | saved_f_flags = substream->ffile->f_flags; | 1586 | saved_f_flags = substream->f_flags; |
1105 | substream->ffile->f_flags &= ~O_NONBLOCK; | 1587 | substream->f_flags &= ~O_NONBLOCK; |
1106 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); | 1588 | err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); |
1107 | substream->ffile->f_flags = saved_f_flags; | 1589 | substream->f_flags = saved_f_flags; |
1108 | if (err < 0) | 1590 | if (err < 0) |
1109 | return err; | 1591 | return err; |
1110 | runtime->oss.prepare = 1; | 1592 | runtime->oss.prepare = 1; |
@@ -1209,7 +1691,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
1209 | 1691 | ||
1210 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) | 1692 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) |
1211 | return err; | 1693 | return err; |
1212 | if (atomic_read(&substream->runtime->mmap_count)) | 1694 | if (atomic_read(&substream->mmap_count)) |
1213 | direct = 1; | 1695 | direct = 1; |
1214 | else | 1696 | else |
1215 | direct = substream->oss.setup.direct; | 1697 | direct = substream->oss.setup.direct; |
@@ -1419,7 +1901,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1419 | if (trigger & PCM_ENABLE_OUTPUT) { | 1901 | if (trigger & PCM_ENABLE_OUTPUT) { |
1420 | if (runtime->oss.trigger) | 1902 | if (runtime->oss.trigger) |
1421 | goto _skip1; | 1903 | goto _skip1; |
1422 | if (atomic_read(&psubstream->runtime->mmap_count)) | 1904 | if (atomic_read(&psubstream->mmap_count)) |
1423 | snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); | 1905 | snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); |
1424 | runtime->oss.trigger = 1; | 1906 | runtime->oss.trigger = 1; |
1425 | runtime->start_threshold = 1; | 1907 | runtime->start_threshold = 1; |
@@ -1537,7 +2019,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream | |||
1537 | if (err < 0) | 2019 | if (err < 0) |
1538 | return err; | 2020 | return err; |
1539 | info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); | 2021 | info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); |
1540 | if (atomic_read(&runtime->mmap_count)) { | 2022 | if (atomic_read(&substream->mmap_count)) { |
1541 | snd_pcm_sframes_t n; | 2023 | snd_pcm_sframes_t n; |
1542 | n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; | 2024 | n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; |
1543 | if (n < 0) | 2025 | if (n < 0) |
@@ -1683,9 +2165,9 @@ static void snd_pcm_oss_init_substream(struct snd_pcm_substream *substream, | |||
1683 | substream->oss.oss = 1; | 2165 | substream->oss.oss = 1; |
1684 | substream->oss.setup = *setup; | 2166 | substream->oss.setup = *setup; |
1685 | if (setup->nonblock) | 2167 | if (setup->nonblock) |
1686 | substream->ffile->f_flags |= O_NONBLOCK; | 2168 | substream->f_flags |= O_NONBLOCK; |
1687 | else if (setup->block) | 2169 | else if (setup->block) |
1688 | substream->ffile->f_flags &= ~O_NONBLOCK; | 2170 | substream->f_flags &= ~O_NONBLOCK; |
1689 | runtime = substream->runtime; | 2171 | runtime = substream->runtime; |
1690 | runtime->oss.params = 1; | 2172 | runtime->oss.params = 1; |
1691 | runtime->oss.trigger = 1; | 2173 | runtime->oss.trigger = 1; |
@@ -1742,6 +2224,7 @@ static int snd_pcm_oss_open_file(struct file *file, | |||
1742 | (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) | 2224 | (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX)) |
1743 | f_mode = FMODE_WRITE; | 2225 | f_mode = FMODE_WRITE; |
1744 | 2226 | ||
2227 | file->f_flags &= ~O_APPEND; | ||
1745 | for (idx = 0; idx < 2; idx++) { | 2228 | for (idx = 0; idx < 2; idx++) { |
1746 | if (setup[idx].disable) | 2229 | if (setup[idx].disable) |
1747 | continue; | 2230 | continue; |
@@ -2059,6 +2542,7 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun | |||
2059 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; | 2542 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; |
2060 | if (substream == NULL) | 2543 | if (substream == NULL) |
2061 | return -ENXIO; | 2544 | return -ENXIO; |
2545 | substream->f_flags = file->f_flags & O_NONBLOCK; | ||
2062 | #ifndef OSS_DEBUG | 2546 | #ifndef OSS_DEBUG |
2063 | return snd_pcm_oss_read1(substream, buf, count); | 2547 | return snd_pcm_oss_read1(substream, buf, count); |
2064 | #else | 2548 | #else |
@@ -2080,6 +2564,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size | |||
2080 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; | 2564 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; |
2081 | if (substream == NULL) | 2565 | if (substream == NULL) |
2082 | return -ENXIO; | 2566 | return -ENXIO; |
2567 | substream->f_flags = file->f_flags & O_NONBLOCK; | ||
2083 | result = snd_pcm_oss_write1(substream, buf, count); | 2568 | result = snd_pcm_oss_write1(substream, buf, count); |
2084 | #ifdef OSS_DEBUG | 2569 | #ifdef OSS_DEBUG |
2085 | printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); | 2570 | printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result); |
@@ -2090,7 +2575,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size | |||
2090 | static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) | 2575 | static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) |
2091 | { | 2576 | { |
2092 | struct snd_pcm_runtime *runtime = substream->runtime; | 2577 | struct snd_pcm_runtime *runtime = substream->runtime; |
2093 | if (atomic_read(&runtime->mmap_count)) | 2578 | if (atomic_read(&substream->mmap_count)) |
2094 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; | 2579 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; |
2095 | else | 2580 | else |
2096 | return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; | 2581 | return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; |
@@ -2099,7 +2584,7 @@ static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) | |||
2099 | static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) | 2584 | static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) |
2100 | { | 2585 | { |
2101 | struct snd_pcm_runtime *runtime = substream->runtime; | 2586 | struct snd_pcm_runtime *runtime = substream->runtime; |
2102 | if (atomic_read(&runtime->mmap_count)) | 2587 | if (atomic_read(&substream->mmap_count)) |
2103 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; | 2588 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; |
2104 | else | 2589 | else |
2105 | return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; | 2590 | return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; |
@@ -2342,9 +2827,7 @@ static void snd_pcm_oss_proc_init(struct snd_pcm *pcm) | |||
2342 | if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { | 2827 | if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) { |
2343 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 2828 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
2344 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 2829 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
2345 | entry->c.text.read_size = 8192; | ||
2346 | entry->c.text.read = snd_pcm_oss_proc_read; | 2830 | entry->c.text.read = snd_pcm_oss_proc_read; |
2347 | entry->c.text.write_size = 8192; | ||
2348 | entry->c.text.write = snd_pcm_oss_proc_write; | 2831 | entry->c.text.write = snd_pcm_oss_proc_write; |
2349 | entry->private_data = pstr; | 2832 | entry->private_data = pstr; |
2350 | if (snd_info_register(entry) < 0) { | 2833 | if (snd_info_register(entry) < 0) { |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 84b00038236d..7581edd7b9ff 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -351,10 +351,8 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, | |||
351 | snd_iprintf(buffer, "closed\n"); | 351 | snd_iprintf(buffer, "closed\n"); |
352 | return; | 352 | return; |
353 | } | 353 | } |
354 | snd_pcm_stream_lock_irq(substream); | ||
355 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { | 354 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { |
356 | snd_iprintf(buffer, "no setup\n"); | 355 | snd_iprintf(buffer, "no setup\n"); |
357 | snd_pcm_stream_unlock_irq(substream); | ||
358 | return; | 356 | return; |
359 | } | 357 | } |
360 | snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); | 358 | snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access)); |
@@ -375,7 +373,6 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, | |||
375 | snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); | 373 | snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames); |
376 | } | 374 | } |
377 | #endif | 375 | #endif |
378 | snd_pcm_stream_unlock_irq(substream); | ||
379 | } | 376 | } |
380 | 377 | ||
381 | static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, | 378 | static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, |
@@ -387,10 +384,8 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, | |||
387 | snd_iprintf(buffer, "closed\n"); | 384 | snd_iprintf(buffer, "closed\n"); |
388 | return; | 385 | return; |
389 | } | 386 | } |
390 | snd_pcm_stream_lock_irq(substream); | ||
391 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { | 387 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { |
392 | snd_iprintf(buffer, "no setup\n"); | 388 | snd_iprintf(buffer, "no setup\n"); |
393 | snd_pcm_stream_unlock_irq(substream); | ||
394 | return; | 389 | return; |
395 | } | 390 | } |
396 | snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); | 391 | snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode)); |
@@ -403,7 +398,6 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, | |||
403 | snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); | 398 | snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold); |
404 | snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); | 399 | snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size); |
405 | snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); | 400 | snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary); |
406 | snd_pcm_stream_unlock_irq(substream); | ||
407 | } | 401 | } |
408 | 402 | ||
409 | static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, | 403 | static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry, |
@@ -472,7 +466,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) | |||
472 | pstr->proc_root = entry; | 466 | pstr->proc_root = entry; |
473 | 467 | ||
474 | if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) { | 468 | if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) { |
475 | snd_info_set_text_ops(entry, pstr, 256, snd_pcm_stream_proc_info_read); | 469 | snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read); |
476 | if (snd_info_register(entry) < 0) { | 470 | if (snd_info_register(entry) < 0) { |
477 | snd_info_free_entry(entry); | 471 | snd_info_free_entry(entry); |
478 | entry = NULL; | 472 | entry = NULL; |
@@ -483,9 +477,7 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) | |||
483 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG | 477 | #ifdef CONFIG_SND_PCM_XRUN_DEBUG |
484 | if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", | 478 | if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug", |
485 | pstr->proc_root)) != NULL) { | 479 | pstr->proc_root)) != NULL) { |
486 | entry->c.text.read_size = 64; | ||
487 | entry->c.text.read = snd_pcm_xrun_debug_read; | 480 | entry->c.text.read = snd_pcm_xrun_debug_read; |
488 | entry->c.text.write_size = 64; | ||
489 | entry->c.text.write = snd_pcm_xrun_debug_write; | 481 | entry->c.text.write = snd_pcm_xrun_debug_write; |
490 | entry->mode |= S_IWUSR; | 482 | entry->mode |= S_IWUSR; |
491 | entry->private_data = pstr; | 483 | entry->private_data = pstr; |
@@ -537,7 +529,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) | |||
537 | substream->proc_root = entry; | 529 | substream->proc_root = entry; |
538 | 530 | ||
539 | if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) { | 531 | if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) { |
540 | snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_info_read); | 532 | snd_info_set_text_ops(entry, substream, |
533 | snd_pcm_substream_proc_info_read); | ||
541 | if (snd_info_register(entry) < 0) { | 534 | if (snd_info_register(entry) < 0) { |
542 | snd_info_free_entry(entry); | 535 | snd_info_free_entry(entry); |
543 | entry = NULL; | 536 | entry = NULL; |
@@ -546,7 +539,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) | |||
546 | substream->proc_info_entry = entry; | 539 | substream->proc_info_entry = entry; |
547 | 540 | ||
548 | if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) { | 541 | if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) { |
549 | snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_hw_params_read); | 542 | snd_info_set_text_ops(entry, substream, |
543 | snd_pcm_substream_proc_hw_params_read); | ||
550 | if (snd_info_register(entry) < 0) { | 544 | if (snd_info_register(entry) < 0) { |
551 | snd_info_free_entry(entry); | 545 | snd_info_free_entry(entry); |
552 | entry = NULL; | 546 | entry = NULL; |
@@ -555,7 +549,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) | |||
555 | substream->proc_hw_params_entry = entry; | 549 | substream->proc_hw_params_entry = entry; |
556 | 550 | ||
557 | if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) { | 551 | if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) { |
558 | snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_sw_params_read); | 552 | snd_info_set_text_ops(entry, substream, |
553 | snd_pcm_substream_proc_sw_params_read); | ||
559 | if (snd_info_register(entry) < 0) { | 554 | if (snd_info_register(entry) < 0) { |
560 | snd_info_free_entry(entry); | 555 | snd_info_free_entry(entry); |
561 | entry = NULL; | 556 | entry = NULL; |
@@ -564,7 +559,8 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) | |||
564 | substream->proc_sw_params_entry = entry; | 559 | substream->proc_sw_params_entry = entry; |
565 | 560 | ||
566 | if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) { | 561 | if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) { |
567 | snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_status_read); | 562 | snd_info_set_text_ops(entry, substream, |
563 | snd_pcm_substream_proc_status_read); | ||
568 | if (snd_info_register(entry) < 0) { | 564 | if (snd_info_register(entry) < 0) { |
569 | snd_info_free_entry(entry); | 565 | snd_info_free_entry(entry); |
570 | entry = NULL; | 566 | entry = NULL; |
@@ -666,11 +662,14 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) | |||
666 | INIT_LIST_HEAD(&substream->self_group.substreams); | 662 | INIT_LIST_HEAD(&substream->self_group.substreams); |
667 | list_add_tail(&substream->link_list, &substream->self_group.substreams); | 663 | list_add_tail(&substream->link_list, &substream->self_group.substreams); |
668 | spin_lock_init(&substream->timer_lock); | 664 | spin_lock_init(&substream->timer_lock); |
665 | atomic_set(&substream->mmap_count, 0); | ||
669 | prev = substream; | 666 | prev = substream; |
670 | } | 667 | } |
671 | return 0; | 668 | return 0; |
672 | } | 669 | } |
673 | 670 | ||
671 | EXPORT_SYMBOL(snd_pcm_new_stream); | ||
672 | |||
674 | /** | 673 | /** |
675 | * snd_pcm_new - create a new PCM instance | 674 | * snd_pcm_new - create a new PCM instance |
676 | * @card: the card instance | 675 | * @card: the card instance |
@@ -730,6 +729,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, | |||
730 | return 0; | 729 | return 0; |
731 | } | 730 | } |
732 | 731 | ||
732 | EXPORT_SYMBOL(snd_pcm_new); | ||
733 | |||
733 | static void snd_pcm_free_stream(struct snd_pcm_str * pstr) | 734 | static void snd_pcm_free_stream(struct snd_pcm_str * pstr) |
734 | { | 735 | { |
735 | struct snd_pcm_substream *substream, *substream_next; | 736 | struct snd_pcm_substream *substream, *substream_next; |
@@ -829,6 +830,26 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
829 | return -EINVAL; | 830 | return -EINVAL; |
830 | } | 831 | } |
831 | 832 | ||
833 | if (file->f_flags & O_APPEND) { | ||
834 | if (prefer_subdevice < 0) { | ||
835 | if (pstr->substream_count > 1) | ||
836 | return -EINVAL; /* must be unique */ | ||
837 | substream = pstr->substream; | ||
838 | } else { | ||
839 | for (substream = pstr->substream; substream; | ||
840 | substream = substream->next) | ||
841 | if (substream->number == prefer_subdevice) | ||
842 | break; | ||
843 | } | ||
844 | if (! substream) | ||
845 | return -ENODEV; | ||
846 | if (! SUBSTREAM_BUSY(substream)) | ||
847 | return -EBADFD; | ||
848 | substream->ref_count++; | ||
849 | *rsubstream = substream; | ||
850 | return 0; | ||
851 | } | ||
852 | |||
832 | if (prefer_subdevice >= 0) { | 853 | if (prefer_subdevice >= 0) { |
833 | for (substream = pstr->substream; substream; substream = substream->next) | 854 | for (substream = pstr->substream; substream; substream = substream->next) |
834 | if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) | 855 | if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice) |
@@ -864,7 +885,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
864 | memset((void*)runtime->control, 0, size); | 885 | memset((void*)runtime->control, 0, size); |
865 | 886 | ||
866 | init_waitqueue_head(&runtime->sleep); | 887 | init_waitqueue_head(&runtime->sleep); |
867 | atomic_set(&runtime->mmap_count, 0); | ||
868 | init_timer(&runtime->tick_timer); | 888 | init_timer(&runtime->tick_timer); |
869 | runtime->tick_timer.function = snd_pcm_tick_timer_func; | 889 | runtime->tick_timer.function = snd_pcm_tick_timer_func; |
870 | runtime->tick_timer.data = (unsigned long) substream; | 890 | runtime->tick_timer.data = (unsigned long) substream; |
@@ -873,7 +893,8 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
873 | 893 | ||
874 | substream->runtime = runtime; | 894 | substream->runtime = runtime; |
875 | substream->private_data = pcm->private_data; | 895 | substream->private_data = pcm->private_data; |
876 | substream->ffile = file; | 896 | substream->ref_count = 1; |
897 | substream->f_flags = file->f_flags; | ||
877 | pstr->substream_opened++; | 898 | pstr->substream_opened++; |
878 | *rsubstream = substream; | 899 | *rsubstream = substream; |
879 | return 0; | 900 | return 0; |
@@ -882,7 +903,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
882 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream) | 903 | void snd_pcm_detach_substream(struct snd_pcm_substream *substream) |
883 | { | 904 | { |
884 | struct snd_pcm_runtime *runtime; | 905 | struct snd_pcm_runtime *runtime; |
885 | substream->file = NULL; | 906 | |
886 | runtime = substream->runtime; | 907 | runtime = substream->runtime; |
887 | snd_assert(runtime != NULL, return); | 908 | snd_assert(runtime != NULL, return); |
888 | if (runtime->private_free != NULL) | 909 | if (runtime->private_free != NULL) |
@@ -1022,6 +1043,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) | |||
1022 | return 0; | 1043 | return 0; |
1023 | } | 1044 | } |
1024 | 1045 | ||
1046 | EXPORT_SYMBOL(snd_pcm_notify); | ||
1047 | |||
1025 | #ifdef CONFIG_PROC_FS | 1048 | #ifdef CONFIG_PROC_FS |
1026 | /* | 1049 | /* |
1027 | * Info interface | 1050 | * Info interface |
@@ -1049,15 +1072,14 @@ static void snd_pcm_proc_read(struct snd_info_entry *entry, | |||
1049 | mutex_unlock(®ister_mutex); | 1072 | mutex_unlock(®ister_mutex); |
1050 | } | 1073 | } |
1051 | 1074 | ||
1052 | static struct snd_info_entry *snd_pcm_proc_entry = NULL; | 1075 | static struct snd_info_entry *snd_pcm_proc_entry; |
1053 | 1076 | ||
1054 | static void snd_pcm_proc_init(void) | 1077 | static void snd_pcm_proc_init(void) |
1055 | { | 1078 | { |
1056 | struct snd_info_entry *entry; | 1079 | struct snd_info_entry *entry; |
1057 | 1080 | ||
1058 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { | 1081 | if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) { |
1059 | snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, | 1082 | snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read); |
1060 | snd_pcm_proc_read); | ||
1061 | if (snd_info_register(entry) < 0) { | 1083 | if (snd_info_register(entry) < 0) { |
1062 | snd_info_free_entry(entry); | 1084 | snd_info_free_entry(entry); |
1063 | entry = NULL; | 1085 | entry = NULL; |
@@ -1099,33 +1121,3 @@ static void __exit alsa_pcm_exit(void) | |||
1099 | 1121 | ||
1100 | module_init(alsa_pcm_init) | 1122 | module_init(alsa_pcm_init) |
1101 | module_exit(alsa_pcm_exit) | 1123 | module_exit(alsa_pcm_exit) |
1102 | |||
1103 | EXPORT_SYMBOL(snd_pcm_new); | ||
1104 | EXPORT_SYMBOL(snd_pcm_new_stream); | ||
1105 | EXPORT_SYMBOL(snd_pcm_notify); | ||
1106 | EXPORT_SYMBOL(snd_pcm_open_substream); | ||
1107 | EXPORT_SYMBOL(snd_pcm_release_substream); | ||
1108 | /* pcm_native.c */ | ||
1109 | EXPORT_SYMBOL(snd_pcm_link_rwlock); | ||
1110 | #ifdef CONFIG_PM | ||
1111 | EXPORT_SYMBOL(snd_pcm_suspend); | ||
1112 | EXPORT_SYMBOL(snd_pcm_suspend_all); | ||
1113 | #endif | ||
1114 | EXPORT_SYMBOL(snd_pcm_kernel_ioctl); | ||
1115 | EXPORT_SYMBOL(snd_pcm_mmap_data); | ||
1116 | #if SNDRV_PCM_INFO_MMAP_IOMEM | ||
1117 | EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); | ||
1118 | #endif | ||
1119 | /* pcm_misc.c */ | ||
1120 | EXPORT_SYMBOL(snd_pcm_format_signed); | ||
1121 | EXPORT_SYMBOL(snd_pcm_format_unsigned); | ||
1122 | EXPORT_SYMBOL(snd_pcm_format_linear); | ||
1123 | EXPORT_SYMBOL(snd_pcm_format_little_endian); | ||
1124 | EXPORT_SYMBOL(snd_pcm_format_big_endian); | ||
1125 | EXPORT_SYMBOL(snd_pcm_format_width); | ||
1126 | EXPORT_SYMBOL(snd_pcm_format_physical_width); | ||
1127 | EXPORT_SYMBOL(snd_pcm_format_size); | ||
1128 | EXPORT_SYMBOL(snd_pcm_format_silence_64); | ||
1129 | EXPORT_SYMBOL(snd_pcm_format_set_silence); | ||
1130 | EXPORT_SYMBOL(snd_pcm_build_linear_format); | ||
1131 | EXPORT_SYMBOL(snd_pcm_limit_hw_rates); | ||
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index e5133033de5e..2b8aab6fd6cd 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -497,9 +497,9 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l | |||
497 | case SNDRV_PCM_IOCTL_LINK: | 497 | case SNDRV_PCM_IOCTL_LINK: |
498 | case SNDRV_PCM_IOCTL_UNLINK: | 498 | case SNDRV_PCM_IOCTL_UNLINK: |
499 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 499 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
500 | return snd_pcm_playback_ioctl1(substream, cmd, argp); | 500 | return snd_pcm_playback_ioctl1(file, substream, cmd, argp); |
501 | else | 501 | else |
502 | return snd_pcm_capture_ioctl1(substream, cmd, argp); | 502 | return snd_pcm_capture_ioctl1(file, substream, cmd, argp); |
503 | case SNDRV_PCM_IOCTL_HW_REFINE32: | 503 | case SNDRV_PCM_IOCTL_HW_REFINE32: |
504 | return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); | 504 | return snd_pcm_ioctl_hw_params_compat(substream, 1, argp); |
505 | case SNDRV_PCM_IOCTL_HW_PARAMS32: | 505 | case SNDRV_PCM_IOCTL_HW_PARAMS32: |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index eedc6cb038bb..0bb142a28539 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
@@ -289,6 +289,7 @@ void snd_pcm_set_ops(struct snd_pcm *pcm, int direction, struct snd_pcm_ops *ops | |||
289 | substream->ops = ops; | 289 | substream->ops = ops; |
290 | } | 290 | } |
291 | 291 | ||
292 | EXPORT_SYMBOL(snd_pcm_set_ops); | ||
292 | 293 | ||
293 | /** | 294 | /** |
294 | * snd_pcm_sync - set the PCM sync id | 295 | * snd_pcm_sync - set the PCM sync id |
@@ -306,13 +307,12 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream) | |||
306 | runtime->sync.id32[3] = -1; | 307 | runtime->sync.id32[3] = -1; |
307 | } | 308 | } |
308 | 309 | ||
310 | EXPORT_SYMBOL(snd_pcm_set_sync); | ||
311 | |||
309 | /* | 312 | /* |
310 | * Standard ioctl routine | 313 | * Standard ioctl routine |
311 | */ | 314 | */ |
312 | 315 | ||
313 | /* Code taken from alsa-lib */ | ||
314 | #define assert(a) snd_assert((a), return -EINVAL) | ||
315 | |||
316 | static inline unsigned int div32(unsigned int a, unsigned int b, | 316 | static inline unsigned int div32(unsigned int a, unsigned int b, |
317 | unsigned int *r) | 317 | unsigned int *r) |
318 | { | 318 | { |
@@ -369,56 +369,6 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b, | |||
369 | return n; | 369 | return n; |
370 | } | 370 | } |
371 | 371 | ||
372 | static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin) | ||
373 | { | ||
374 | int changed = 0; | ||
375 | assert(!snd_interval_empty(i)); | ||
376 | if (i->min < min) { | ||
377 | i->min = min; | ||
378 | i->openmin = openmin; | ||
379 | changed = 1; | ||
380 | } else if (i->min == min && !i->openmin && openmin) { | ||
381 | i->openmin = 1; | ||
382 | changed = 1; | ||
383 | } | ||
384 | if (i->integer) { | ||
385 | if (i->openmin) { | ||
386 | i->min++; | ||
387 | i->openmin = 0; | ||
388 | } | ||
389 | } | ||
390 | if (snd_interval_checkempty(i)) { | ||
391 | snd_interval_none(i); | ||
392 | return -EINVAL; | ||
393 | } | ||
394 | return changed; | ||
395 | } | ||
396 | |||
397 | static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax) | ||
398 | { | ||
399 | int changed = 0; | ||
400 | assert(!snd_interval_empty(i)); | ||
401 | if (i->max > max) { | ||
402 | i->max = max; | ||
403 | i->openmax = openmax; | ||
404 | changed = 1; | ||
405 | } else if (i->max == max && !i->openmax && openmax) { | ||
406 | i->openmax = 1; | ||
407 | changed = 1; | ||
408 | } | ||
409 | if (i->integer) { | ||
410 | if (i->openmax) { | ||
411 | i->max--; | ||
412 | i->openmax = 0; | ||
413 | } | ||
414 | } | ||
415 | if (snd_interval_checkempty(i)) { | ||
416 | snd_interval_none(i); | ||
417 | return -EINVAL; | ||
418 | } | ||
419 | return changed; | ||
420 | } | ||
421 | |||
422 | /** | 372 | /** |
423 | * snd_interval_refine - refine the interval value of configurator | 373 | * snd_interval_refine - refine the interval value of configurator |
424 | * @i: the interval value to refine | 374 | * @i: the interval value to refine |
@@ -433,7 +383,7 @@ static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int | |||
433 | int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) | 383 | int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) |
434 | { | 384 | { |
435 | int changed = 0; | 385 | int changed = 0; |
436 | assert(!snd_interval_empty(i)); | 386 | snd_assert(!snd_interval_empty(i), return -EINVAL); |
437 | if (i->min < v->min) { | 387 | if (i->min < v->min) { |
438 | i->min = v->min; | 388 | i->min = v->min; |
439 | i->openmin = v->openmin; | 389 | i->openmin = v->openmin; |
@@ -472,9 +422,11 @@ int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v) | |||
472 | return changed; | 422 | return changed; |
473 | } | 423 | } |
474 | 424 | ||
425 | EXPORT_SYMBOL(snd_interval_refine); | ||
426 | |||
475 | static int snd_interval_refine_first(struct snd_interval *i) | 427 | static int snd_interval_refine_first(struct snd_interval *i) |
476 | { | 428 | { |
477 | assert(!snd_interval_empty(i)); | 429 | snd_assert(!snd_interval_empty(i), return -EINVAL); |
478 | if (snd_interval_single(i)) | 430 | if (snd_interval_single(i)) |
479 | return 0; | 431 | return 0; |
480 | i->max = i->min; | 432 | i->max = i->min; |
@@ -486,7 +438,7 @@ static int snd_interval_refine_first(struct snd_interval *i) | |||
486 | 438 | ||
487 | static int snd_interval_refine_last(struct snd_interval *i) | 439 | static int snd_interval_refine_last(struct snd_interval *i) |
488 | { | 440 | { |
489 | assert(!snd_interval_empty(i)); | 441 | snd_assert(!snd_interval_empty(i), return -EINVAL); |
490 | if (snd_interval_single(i)) | 442 | if (snd_interval_single(i)) |
491 | return 0; | 443 | return 0; |
492 | i->min = i->max; | 444 | i->min = i->max; |
@@ -496,16 +448,6 @@ static int snd_interval_refine_last(struct snd_interval *i) | |||
496 | return 1; | 448 | return 1; |
497 | } | 449 | } |
498 | 450 | ||
499 | static int snd_interval_refine_set(struct snd_interval *i, unsigned int val) | ||
500 | { | ||
501 | struct snd_interval t; | ||
502 | t.empty = 0; | ||
503 | t.min = t.max = val; | ||
504 | t.openmin = t.openmax = 0; | ||
505 | t.integer = 1; | ||
506 | return snd_interval_refine(i, &t); | ||
507 | } | ||
508 | |||
509 | void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c) | 451 | void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c) |
510 | { | 452 | { |
511 | if (a->empty || b->empty) { | 453 | if (a->empty || b->empty) { |
@@ -621,7 +563,6 @@ void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k, | |||
621 | c->integer = 0; | 563 | c->integer = 0; |
622 | } | 564 | } |
623 | 565 | ||
624 | #undef assert | ||
625 | /* ---- */ | 566 | /* ---- */ |
626 | 567 | ||
627 | 568 | ||
@@ -727,6 +668,8 @@ int snd_interval_ratnum(struct snd_interval *i, | |||
727 | return err; | 668 | return err; |
728 | } | 669 | } |
729 | 670 | ||
671 | EXPORT_SYMBOL(snd_interval_ratnum); | ||
672 | |||
730 | /** | 673 | /** |
731 | * snd_interval_ratden - refine the interval value | 674 | * snd_interval_ratden - refine the interval value |
732 | * @i: interval to refine | 675 | * @i: interval to refine |
@@ -877,6 +820,8 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int * | |||
877 | return changed; | 820 | return changed; |
878 | } | 821 | } |
879 | 822 | ||
823 | EXPORT_SYMBOL(snd_interval_list); | ||
824 | |||
880 | static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step) | 825 | static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step) |
881 | { | 826 | { |
882 | unsigned int n; | 827 | unsigned int n; |
@@ -953,6 +898,8 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond, | |||
953 | return 0; | 898 | return 0; |
954 | } | 899 | } |
955 | 900 | ||
901 | EXPORT_SYMBOL(snd_pcm_hw_rule_add); | ||
902 | |||
956 | /** | 903 | /** |
957 | * snd_pcm_hw_constraint_mask | 904 | * snd_pcm_hw_constraint_mask |
958 | * @runtime: PCM runtime instance | 905 | * @runtime: PCM runtime instance |
@@ -1007,6 +954,8 @@ int snd_pcm_hw_constraint_integer(struct snd_pcm_runtime *runtime, snd_pcm_hw_pa | |||
1007 | return snd_interval_setinteger(constrs_interval(constrs, var)); | 954 | return snd_interval_setinteger(constrs_interval(constrs, var)); |
1008 | } | 955 | } |
1009 | 956 | ||
957 | EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); | ||
958 | |||
1010 | /** | 959 | /** |
1011 | * snd_pcm_hw_constraint_minmax | 960 | * snd_pcm_hw_constraint_minmax |
1012 | * @runtime: PCM runtime instance | 961 | * @runtime: PCM runtime instance |
@@ -1028,6 +977,8 @@ int snd_pcm_hw_constraint_minmax(struct snd_pcm_runtime *runtime, snd_pcm_hw_par | |||
1028 | return snd_interval_refine(constrs_interval(constrs, var), &t); | 977 | return snd_interval_refine(constrs_interval(constrs, var), &t); |
1029 | } | 978 | } |
1030 | 979 | ||
980 | EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); | ||
981 | |||
1031 | static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, | 982 | static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params, |
1032 | struct snd_pcm_hw_rule *rule) | 983 | struct snd_pcm_hw_rule *rule) |
1033 | { | 984 | { |
@@ -1055,6 +1006,8 @@ int snd_pcm_hw_constraint_list(struct snd_pcm_runtime *runtime, | |||
1055 | var, -1); | 1006 | var, -1); |
1056 | } | 1007 | } |
1057 | 1008 | ||
1009 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); | ||
1010 | |||
1058 | static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, | 1011 | static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params, |
1059 | struct snd_pcm_hw_rule *rule) | 1012 | struct snd_pcm_hw_rule *rule) |
1060 | { | 1013 | { |
@@ -1087,6 +1040,8 @@ int snd_pcm_hw_constraint_ratnums(struct snd_pcm_runtime *runtime, | |||
1087 | var, -1); | 1040 | var, -1); |
1088 | } | 1041 | } |
1089 | 1042 | ||
1043 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); | ||
1044 | |||
1090 | static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, | 1045 | static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params, |
1091 | struct snd_pcm_hw_rule *rule) | 1046 | struct snd_pcm_hw_rule *rule) |
1092 | { | 1047 | { |
@@ -1118,6 +1073,8 @@ int snd_pcm_hw_constraint_ratdens(struct snd_pcm_runtime *runtime, | |||
1118 | var, -1); | 1073 | var, -1); |
1119 | } | 1074 | } |
1120 | 1075 | ||
1076 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); | ||
1077 | |||
1121 | static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, | 1078 | static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params, |
1122 | struct snd_pcm_hw_rule *rule) | 1079 | struct snd_pcm_hw_rule *rule) |
1123 | { | 1080 | { |
@@ -1149,6 +1106,8 @@ int snd_pcm_hw_constraint_msbits(struct snd_pcm_runtime *runtime, | |||
1149 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); | 1106 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1); |
1150 | } | 1107 | } |
1151 | 1108 | ||
1109 | EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); | ||
1110 | |||
1152 | static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, | 1111 | static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params, |
1153 | struct snd_pcm_hw_rule *rule) | 1112 | struct snd_pcm_hw_rule *rule) |
1154 | { | 1113 | { |
@@ -1173,6 +1132,8 @@ int snd_pcm_hw_constraint_step(struct snd_pcm_runtime *runtime, | |||
1173 | var, -1); | 1132 | var, -1); |
1174 | } | 1133 | } |
1175 | 1134 | ||
1135 | EXPORT_SYMBOL(snd_pcm_hw_constraint_step); | ||
1136 | |||
1176 | static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) | 1137 | static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) |
1177 | { | 1138 | { |
1178 | static int pow2_sizes[] = { | 1139 | static int pow2_sizes[] = { |
@@ -1200,11 +1161,7 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime, | |||
1200 | var, -1); | 1161 | var, -1); |
1201 | } | 1162 | } |
1202 | 1163 | ||
1203 | /* To use the same code we have in alsa-lib */ | 1164 | EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); |
1204 | #define assert(i) snd_assert((i), return -EINVAL) | ||
1205 | #ifndef INT_MIN | ||
1206 | #define INT_MIN ((int)((unsigned int)INT_MAX+1)) | ||
1207 | #endif | ||
1208 | 1165 | ||
1209 | static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, | 1166 | static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, |
1210 | snd_pcm_hw_param_t var) | 1167 | snd_pcm_hw_param_t var) |
@@ -1224,18 +1181,6 @@ static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params, | |||
1224 | snd_BUG(); | 1181 | snd_BUG(); |
1225 | } | 1182 | } |
1226 | 1183 | ||
1227 | #if 0 | ||
1228 | /* | ||
1229 | * snd_pcm_hw_param_any | ||
1230 | */ | ||
1231 | int snd_pcm_hw_param_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, | ||
1232 | snd_pcm_hw_param_t var) | ||
1233 | { | ||
1234 | _snd_pcm_hw_param_any(params, var); | ||
1235 | return snd_pcm_hw_refine(pcm, params); | ||
1236 | } | ||
1237 | #endif /* 0 */ | ||
1238 | |||
1239 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) | 1184 | void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) |
1240 | { | 1185 | { |
1241 | unsigned int k; | 1186 | unsigned int k; |
@@ -1247,18 +1192,7 @@ void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params) | |||
1247 | params->info = ~0U; | 1192 | params->info = ~0U; |
1248 | } | 1193 | } |
1249 | 1194 | ||
1250 | #if 0 | 1195 | EXPORT_SYMBOL(_snd_pcm_hw_params_any); |
1251 | /* | ||
1252 | * snd_pcm_hw_params_any | ||
1253 | * | ||
1254 | * Fill PARAMS with full configuration space boundaries | ||
1255 | */ | ||
1256 | int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params) | ||
1257 | { | ||
1258 | _snd_pcm_hw_params_any(params); | ||
1259 | return snd_pcm_hw_refine(pcm, params); | ||
1260 | } | ||
1261 | #endif /* 0 */ | ||
1262 | 1196 | ||
1263 | /** | 1197 | /** |
1264 | * snd_pcm_hw_param_value | 1198 | * snd_pcm_hw_param_value |
@@ -1269,8 +1203,8 @@ int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_param | |||
1269 | * Return the value for field PAR if it's fixed in configuration space | 1203 | * Return the value for field PAR if it's fixed in configuration space |
1270 | * defined by PARAMS. Return -EINVAL otherwise | 1204 | * defined by PARAMS. Return -EINVAL otherwise |
1271 | */ | 1205 | */ |
1272 | static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, | 1206 | int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, |
1273 | snd_pcm_hw_param_t var, int *dir) | 1207 | snd_pcm_hw_param_t var, int *dir) |
1274 | { | 1208 | { |
1275 | if (hw_is_mask(var)) { | 1209 | if (hw_is_mask(var)) { |
1276 | const struct snd_mask *mask = hw_param_mask_c(params, var); | 1210 | const struct snd_mask *mask = hw_param_mask_c(params, var); |
@@ -1288,61 +1222,10 @@ static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, | |||
1288 | *dir = i->openmin; | 1222 | *dir = i->openmin; |
1289 | return snd_interval_value(i); | 1223 | return snd_interval_value(i); |
1290 | } | 1224 | } |
1291 | assert(0); | ||
1292 | return -EINVAL; | ||
1293 | } | ||
1294 | |||
1295 | /** | ||
1296 | * snd_pcm_hw_param_value_min | ||
1297 | * @params: the hw_params instance | ||
1298 | * @var: parameter to retrieve | ||
1299 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
1300 | * | ||
1301 | * Return the minimum value for field PAR. | ||
1302 | */ | ||
1303 | unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params, | ||
1304 | snd_pcm_hw_param_t var, int *dir) | ||
1305 | { | ||
1306 | if (hw_is_mask(var)) { | ||
1307 | if (dir) | ||
1308 | *dir = 0; | ||
1309 | return snd_mask_min(hw_param_mask_c(params, var)); | ||
1310 | } | ||
1311 | if (hw_is_interval(var)) { | ||
1312 | const struct snd_interval *i = hw_param_interval_c(params, var); | ||
1313 | if (dir) | ||
1314 | *dir = i->openmin; | ||
1315 | return snd_interval_min(i); | ||
1316 | } | ||
1317 | assert(0); | ||
1318 | return -EINVAL; | 1225 | return -EINVAL; |
1319 | } | 1226 | } |
1320 | 1227 | ||
1321 | /** | 1228 | EXPORT_SYMBOL(snd_pcm_hw_param_value); |
1322 | * snd_pcm_hw_param_value_max | ||
1323 | * @params: the hw_params instance | ||
1324 | * @var: parameter to retrieve | ||
1325 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
1326 | * | ||
1327 | * Return the maximum value for field PAR. | ||
1328 | */ | ||
1329 | unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params, | ||
1330 | snd_pcm_hw_param_t var, int *dir) | ||
1331 | { | ||
1332 | if (hw_is_mask(var)) { | ||
1333 | if (dir) | ||
1334 | *dir = 0; | ||
1335 | return snd_mask_max(hw_param_mask_c(params, var)); | ||
1336 | } | ||
1337 | if (hw_is_interval(var)) { | ||
1338 | const struct snd_interval *i = hw_param_interval_c(params, var); | ||
1339 | if (dir) | ||
1340 | *dir = - (int) i->openmax; | ||
1341 | return snd_interval_max(i); | ||
1342 | } | ||
1343 | assert(0); | ||
1344 | return -EINVAL; | ||
1345 | } | ||
1346 | 1229 | ||
1347 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, | 1230 | void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, |
1348 | snd_pcm_hw_param_t var) | 1231 | snd_pcm_hw_param_t var) |
@@ -1360,42 +1243,7 @@ void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, | |||
1360 | } | 1243 | } |
1361 | } | 1244 | } |
1362 | 1245 | ||
1363 | int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params, | 1246 | EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); |
1364 | snd_pcm_hw_param_t var) | ||
1365 | { | ||
1366 | int changed; | ||
1367 | assert(hw_is_interval(var)); | ||
1368 | changed = snd_interval_setinteger(hw_param_interval(params, var)); | ||
1369 | if (changed) { | ||
1370 | params->cmask |= 1 << var; | ||
1371 | params->rmask |= 1 << var; | ||
1372 | } | ||
1373 | return changed; | ||
1374 | } | ||
1375 | |||
1376 | #if 0 | ||
1377 | /* | ||
1378 | * snd_pcm_hw_param_setinteger | ||
1379 | * | ||
1380 | * Inside configuration space defined by PARAMS remove from PAR all | ||
1381 | * non integer values. Reduce configuration space accordingly. | ||
1382 | * Return -EINVAL if the configuration space is empty | ||
1383 | */ | ||
1384 | int snd_pcm_hw_param_setinteger(struct snd_pcm_substream *pcm, | ||
1385 | struct snd_pcm_hw_params *params, | ||
1386 | snd_pcm_hw_param_t var) | ||
1387 | { | ||
1388 | int changed = _snd_pcm_hw_param_setinteger(params, var); | ||
1389 | if (changed < 0) | ||
1390 | return changed; | ||
1391 | if (params->rmask) { | ||
1392 | int err = snd_pcm_hw_refine(pcm, params); | ||
1393 | if (err < 0) | ||
1394 | return err; | ||
1395 | } | ||
1396 | return 0; | ||
1397 | } | ||
1398 | #endif /* 0 */ | ||
1399 | 1247 | ||
1400 | static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, | 1248 | static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, |
1401 | snd_pcm_hw_param_t var) | 1249 | snd_pcm_hw_param_t var) |
@@ -1405,10 +1253,8 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, | |||
1405 | changed = snd_mask_refine_first(hw_param_mask(params, var)); | 1253 | changed = snd_mask_refine_first(hw_param_mask(params, var)); |
1406 | else if (hw_is_interval(var)) | 1254 | else if (hw_is_interval(var)) |
1407 | changed = snd_interval_refine_first(hw_param_interval(params, var)); | 1255 | changed = snd_interval_refine_first(hw_param_interval(params, var)); |
1408 | else { | 1256 | else |
1409 | assert(0); | ||
1410 | return -EINVAL; | 1257 | return -EINVAL; |
1411 | } | ||
1412 | if (changed) { | 1258 | if (changed) { |
1413 | params->cmask |= 1 << var; | 1259 | params->cmask |= 1 << var; |
1414 | params->rmask |= 1 << var; | 1260 | params->rmask |= 1 << var; |
@@ -1428,20 +1274,22 @@ static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params, | |||
1428 | * values > minimum. Reduce configuration space accordingly. | 1274 | * values > minimum. Reduce configuration space accordingly. |
1429 | * Return the minimum. | 1275 | * Return the minimum. |
1430 | */ | 1276 | */ |
1431 | static int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, | 1277 | int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, |
1432 | struct snd_pcm_hw_params *params, | 1278 | struct snd_pcm_hw_params *params, |
1433 | snd_pcm_hw_param_t var, int *dir) | 1279 | snd_pcm_hw_param_t var, int *dir) |
1434 | { | 1280 | { |
1435 | int changed = _snd_pcm_hw_param_first(params, var); | 1281 | int changed = _snd_pcm_hw_param_first(params, var); |
1436 | if (changed < 0) | 1282 | if (changed < 0) |
1437 | return changed; | 1283 | return changed; |
1438 | if (params->rmask) { | 1284 | if (params->rmask) { |
1439 | int err = snd_pcm_hw_refine(pcm, params); | 1285 | int err = snd_pcm_hw_refine(pcm, params); |
1440 | assert(err >= 0); | 1286 | snd_assert(err >= 0, return err); |
1441 | } | 1287 | } |
1442 | return snd_pcm_hw_param_value(params, var, dir); | 1288 | return snd_pcm_hw_param_value(params, var, dir); |
1443 | } | 1289 | } |
1444 | 1290 | ||
1291 | EXPORT_SYMBOL(snd_pcm_hw_param_first); | ||
1292 | |||
1445 | static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, | 1293 | static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, |
1446 | snd_pcm_hw_param_t var) | 1294 | snd_pcm_hw_param_t var) |
1447 | { | 1295 | { |
@@ -1450,10 +1298,8 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, | |||
1450 | changed = snd_mask_refine_last(hw_param_mask(params, var)); | 1298 | changed = snd_mask_refine_last(hw_param_mask(params, var)); |
1451 | else if (hw_is_interval(var)) | 1299 | else if (hw_is_interval(var)) |
1452 | changed = snd_interval_refine_last(hw_param_interval(params, var)); | 1300 | changed = snd_interval_refine_last(hw_param_interval(params, var)); |
1453 | else { | 1301 | else |
1454 | assert(0); | ||
1455 | return -EINVAL; | 1302 | return -EINVAL; |
1456 | } | ||
1457 | if (changed) { | 1303 | if (changed) { |
1458 | params->cmask |= 1 << var; | 1304 | params->cmask |= 1 << var; |
1459 | params->rmask |= 1 << var; | 1305 | params->rmask |= 1 << var; |
@@ -1473,381 +1319,21 @@ static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params, | |||
1473 | * values < maximum. Reduce configuration space accordingly. | 1319 | * values < maximum. Reduce configuration space accordingly. |
1474 | * Return the maximum. | 1320 | * Return the maximum. |
1475 | */ | 1321 | */ |
1476 | static int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, | 1322 | int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, |
1477 | struct snd_pcm_hw_params *params, | 1323 | struct snd_pcm_hw_params *params, |
1478 | snd_pcm_hw_param_t var, int *dir) | 1324 | snd_pcm_hw_param_t var, int *dir) |
1479 | { | 1325 | { |
1480 | int changed = _snd_pcm_hw_param_last(params, var); | 1326 | int changed = _snd_pcm_hw_param_last(params, var); |
1481 | if (changed < 0) | 1327 | if (changed < 0) |
1482 | return changed; | 1328 | return changed; |
1483 | if (params->rmask) { | 1329 | if (params->rmask) { |
1484 | int err = snd_pcm_hw_refine(pcm, params); | 1330 | int err = snd_pcm_hw_refine(pcm, params); |
1485 | assert(err >= 0); | 1331 | snd_assert(err >= 0, return err); |
1486 | } | 1332 | } |
1487 | return snd_pcm_hw_param_value(params, var, dir); | 1333 | return snd_pcm_hw_param_value(params, var, dir); |
1488 | } | 1334 | } |
1489 | 1335 | ||
1490 | int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params, | 1336 | EXPORT_SYMBOL(snd_pcm_hw_param_last); |
1491 | snd_pcm_hw_param_t var, unsigned int val, int dir) | ||
1492 | { | ||
1493 | int changed; | ||
1494 | int open = 0; | ||
1495 | if (dir) { | ||
1496 | if (dir > 0) { | ||
1497 | open = 1; | ||
1498 | } else if (dir < 0) { | ||
1499 | if (val > 0) { | ||
1500 | open = 1; | ||
1501 | val--; | ||
1502 | } | ||
1503 | } | ||
1504 | } | ||
1505 | if (hw_is_mask(var)) | ||
1506 | changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!open); | ||
1507 | else if (hw_is_interval(var)) | ||
1508 | changed = snd_interval_refine_min(hw_param_interval(params, var), val, open); | ||
1509 | else { | ||
1510 | assert(0); | ||
1511 | return -EINVAL; | ||
1512 | } | ||
1513 | if (changed) { | ||
1514 | params->cmask |= 1 << var; | ||
1515 | params->rmask |= 1 << var; | ||
1516 | } | ||
1517 | return changed; | ||
1518 | } | ||
1519 | |||
1520 | /** | ||
1521 | * snd_pcm_hw_param_min | ||
1522 | * @pcm: PCM instance | ||
1523 | * @params: the hw_params instance | ||
1524 | * @var: parameter to retrieve | ||
1525 | * @val: minimal value | ||
1526 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
1527 | * | ||
1528 | * Inside configuration space defined by PARAMS remove from PAR all | ||
1529 | * values < VAL. Reduce configuration space accordingly. | ||
1530 | * Return new minimum or -EINVAL if the configuration space is empty | ||
1531 | */ | ||
1532 | static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, | ||
1533 | snd_pcm_hw_param_t var, unsigned int val, | ||
1534 | int *dir) | ||
1535 | { | ||
1536 | int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0); | ||
1537 | if (changed < 0) | ||
1538 | return changed; | ||
1539 | if (params->rmask) { | ||
1540 | int err = snd_pcm_hw_refine(pcm, params); | ||
1541 | if (err < 0) | ||
1542 | return err; | ||
1543 | } | ||
1544 | return snd_pcm_hw_param_value_min(params, var, dir); | ||
1545 | } | ||
1546 | |||
1547 | static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params, | ||
1548 | snd_pcm_hw_param_t var, unsigned int val, | ||
1549 | int dir) | ||
1550 | { | ||
1551 | int changed; | ||
1552 | int open = 0; | ||
1553 | if (dir) { | ||
1554 | if (dir < 0) { | ||
1555 | open = 1; | ||
1556 | } else if (dir > 0) { | ||
1557 | open = 1; | ||
1558 | val++; | ||
1559 | } | ||
1560 | } | ||
1561 | if (hw_is_mask(var)) { | ||
1562 | if (val == 0 && open) { | ||
1563 | snd_mask_none(hw_param_mask(params, var)); | ||
1564 | changed = -EINVAL; | ||
1565 | } else | ||
1566 | changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!open); | ||
1567 | } else if (hw_is_interval(var)) | ||
1568 | changed = snd_interval_refine_max(hw_param_interval(params, var), val, open); | ||
1569 | else { | ||
1570 | assert(0); | ||
1571 | return -EINVAL; | ||
1572 | } | ||
1573 | if (changed) { | ||
1574 | params->cmask |= 1 << var; | ||
1575 | params->rmask |= 1 << var; | ||
1576 | } | ||
1577 | return changed; | ||
1578 | } | ||
1579 | |||
1580 | /** | ||
1581 | * snd_pcm_hw_param_max | ||
1582 | * @pcm: PCM instance | ||
1583 | * @params: the hw_params instance | ||
1584 | * @var: parameter to retrieve | ||
1585 | * @val: maximal value | ||
1586 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
1587 | * | ||
1588 | * Inside configuration space defined by PARAMS remove from PAR all | ||
1589 | * values >= VAL + 1. Reduce configuration space accordingly. | ||
1590 | * Return new maximum or -EINVAL if the configuration space is empty | ||
1591 | */ | ||
1592 | static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, | ||
1593 | snd_pcm_hw_param_t var, unsigned int val, | ||
1594 | int *dir) | ||
1595 | { | ||
1596 | int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0); | ||
1597 | if (changed < 0) | ||
1598 | return changed; | ||
1599 | if (params->rmask) { | ||
1600 | int err = snd_pcm_hw_refine(pcm, params); | ||
1601 | if (err < 0) | ||
1602 | return err; | ||
1603 | } | ||
1604 | return snd_pcm_hw_param_value_max(params, var, dir); | ||
1605 | } | ||
1606 | |||
1607 | int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params, | ||
1608 | snd_pcm_hw_param_t var, unsigned int val, int dir) | ||
1609 | { | ||
1610 | int changed; | ||
1611 | if (hw_is_mask(var)) { | ||
1612 | struct snd_mask *m = hw_param_mask(params, var); | ||
1613 | if (val == 0 && dir < 0) { | ||
1614 | changed = -EINVAL; | ||
1615 | snd_mask_none(m); | ||
1616 | } else { | ||
1617 | if (dir > 0) | ||
1618 | val++; | ||
1619 | else if (dir < 0) | ||
1620 | val--; | ||
1621 | changed = snd_mask_refine_set(hw_param_mask(params, var), val); | ||
1622 | } | ||
1623 | } else if (hw_is_interval(var)) { | ||
1624 | struct snd_interval *i = hw_param_interval(params, var); | ||
1625 | if (val == 0 && dir < 0) { | ||
1626 | changed = -EINVAL; | ||
1627 | snd_interval_none(i); | ||
1628 | } else if (dir == 0) | ||
1629 | changed = snd_interval_refine_set(i, val); | ||
1630 | else { | ||
1631 | struct snd_interval t; | ||
1632 | t.openmin = 1; | ||
1633 | t.openmax = 1; | ||
1634 | t.empty = 0; | ||
1635 | t.integer = 0; | ||
1636 | if (dir < 0) { | ||
1637 | t.min = val - 1; | ||
1638 | t.max = val; | ||
1639 | } else { | ||
1640 | t.min = val; | ||
1641 | t.max = val+1; | ||
1642 | } | ||
1643 | changed = snd_interval_refine(i, &t); | ||
1644 | } | ||
1645 | } else { | ||
1646 | assert(0); | ||
1647 | return -EINVAL; | ||
1648 | } | ||
1649 | if (changed) { | ||
1650 | params->cmask |= 1 << var; | ||
1651 | params->rmask |= 1 << var; | ||
1652 | } | ||
1653 | return changed; | ||
1654 | } | ||
1655 | |||
1656 | /** | ||
1657 | * snd_pcm_hw_param_set | ||
1658 | * @pcm: PCM instance | ||
1659 | * @params: the hw_params instance | ||
1660 | * @var: parameter to retrieve | ||
1661 | * @val: value to set | ||
1662 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
1663 | * | ||
1664 | * Inside configuration space defined by PARAMS remove from PAR all | ||
1665 | * values != VAL. Reduce configuration space accordingly. | ||
1666 | * Return VAL or -EINVAL if the configuration space is empty | ||
1667 | */ | ||
1668 | int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, | ||
1669 | snd_pcm_hw_param_t var, unsigned int val, int dir) | ||
1670 | { | ||
1671 | int changed = _snd_pcm_hw_param_set(params, var, val, dir); | ||
1672 | if (changed < 0) | ||
1673 | return changed; | ||
1674 | if (params->rmask) { | ||
1675 | int err = snd_pcm_hw_refine(pcm, params); | ||
1676 | if (err < 0) | ||
1677 | return err; | ||
1678 | } | ||
1679 | return snd_pcm_hw_param_value(params, var, NULL); | ||
1680 | } | ||
1681 | |||
1682 | static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params, | ||
1683 | snd_pcm_hw_param_t var, const struct snd_mask *val) | ||
1684 | { | ||
1685 | int changed; | ||
1686 | assert(hw_is_mask(var)); | ||
1687 | changed = snd_mask_refine(hw_param_mask(params, var), val); | ||
1688 | if (changed) { | ||
1689 | params->cmask |= 1 << var; | ||
1690 | params->rmask |= 1 << var; | ||
1691 | } | ||
1692 | return changed; | ||
1693 | } | ||
1694 | |||
1695 | /** | ||
1696 | * snd_pcm_hw_param_mask | ||
1697 | * @pcm: PCM instance | ||
1698 | * @params: the hw_params instance | ||
1699 | * @var: parameter to retrieve | ||
1700 | * @val: mask to apply | ||
1701 | * | ||
1702 | * Inside configuration space defined by PARAMS remove from PAR all values | ||
1703 | * not contained in MASK. Reduce configuration space accordingly. | ||
1704 | * This function can be called only for SNDRV_PCM_HW_PARAM_ACCESS, | ||
1705 | * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. | ||
1706 | * Return 0 on success or -EINVAL | ||
1707 | * if the configuration space is empty | ||
1708 | */ | ||
1709 | int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, | ||
1710 | snd_pcm_hw_param_t var, const struct snd_mask *val) | ||
1711 | { | ||
1712 | int changed = _snd_pcm_hw_param_mask(params, var, val); | ||
1713 | if (changed < 0) | ||
1714 | return changed; | ||
1715 | if (params->rmask) { | ||
1716 | int err = snd_pcm_hw_refine(pcm, params); | ||
1717 | if (err < 0) | ||
1718 | return err; | ||
1719 | } | ||
1720 | return 0; | ||
1721 | } | ||
1722 | |||
1723 | static int boundary_sub(int a, int adir, | ||
1724 | int b, int bdir, | ||
1725 | int *c, int *cdir) | ||
1726 | { | ||
1727 | adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0); | ||
1728 | bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0); | ||
1729 | *c = a - b; | ||
1730 | *cdir = adir - bdir; | ||
1731 | if (*cdir == -2) { | ||
1732 | assert(*c > INT_MIN); | ||
1733 | (*c)--; | ||
1734 | } else if (*cdir == 2) { | ||
1735 | assert(*c < INT_MAX); | ||
1736 | (*c)++; | ||
1737 | } | ||
1738 | return 0; | ||
1739 | } | ||
1740 | |||
1741 | static int boundary_lt(unsigned int a, int adir, | ||
1742 | unsigned int b, int bdir) | ||
1743 | { | ||
1744 | assert(a > 0 || adir >= 0); | ||
1745 | assert(b > 0 || bdir >= 0); | ||
1746 | if (adir < 0) { | ||
1747 | a--; | ||
1748 | adir = 1; | ||
1749 | } else if (adir > 0) | ||
1750 | adir = 1; | ||
1751 | if (bdir < 0) { | ||
1752 | b--; | ||
1753 | bdir = 1; | ||
1754 | } else if (bdir > 0) | ||
1755 | bdir = 1; | ||
1756 | return a < b || (a == b && adir < bdir); | ||
1757 | } | ||
1758 | |||
1759 | /* Return 1 if min is nearer to best than max */ | ||
1760 | static int boundary_nearer(int min, int mindir, | ||
1761 | int best, int bestdir, | ||
1762 | int max, int maxdir) | ||
1763 | { | ||
1764 | int dmin, dmindir; | ||
1765 | int dmax, dmaxdir; | ||
1766 | boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir); | ||
1767 | boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir); | ||
1768 | return boundary_lt(dmin, dmindir, dmax, dmaxdir); | ||
1769 | } | ||
1770 | |||
1771 | /** | ||
1772 | * snd_pcm_hw_param_near | ||
1773 | * @pcm: PCM instance | ||
1774 | * @params: the hw_params instance | ||
1775 | * @var: parameter to retrieve | ||
1776 | * @best: value to set | ||
1777 | * @dir: pointer to the direction (-1,0,1) or NULL | ||
1778 | * | ||
1779 | * Inside configuration space defined by PARAMS set PAR to the available value | ||
1780 | * nearest to VAL. Reduce configuration space accordingly. | ||
1781 | * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS, | ||
1782 | * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT. | ||
1783 | * Return the value found. | ||
1784 | */ | ||
1785 | int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params, | ||
1786 | snd_pcm_hw_param_t var, unsigned int best, int *dir) | ||
1787 | { | ||
1788 | struct snd_pcm_hw_params *save = NULL; | ||
1789 | int v; | ||
1790 | unsigned int saved_min; | ||
1791 | int last = 0; | ||
1792 | int min, max; | ||
1793 | int mindir, maxdir; | ||
1794 | int valdir = dir ? *dir : 0; | ||
1795 | /* FIXME */ | ||
1796 | if (best > INT_MAX) | ||
1797 | best = INT_MAX; | ||
1798 | min = max = best; | ||
1799 | mindir = maxdir = valdir; | ||
1800 | if (maxdir > 0) | ||
1801 | maxdir = 0; | ||
1802 | else if (maxdir == 0) | ||
1803 | maxdir = -1; | ||
1804 | else { | ||
1805 | maxdir = 1; | ||
1806 | max--; | ||
1807 | } | ||
1808 | save = kmalloc(sizeof(*save), GFP_KERNEL); | ||
1809 | if (save == NULL) | ||
1810 | return -ENOMEM; | ||
1811 | *save = *params; | ||
1812 | saved_min = min; | ||
1813 | min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir); | ||
1814 | if (min >= 0) { | ||
1815 | struct snd_pcm_hw_params *params1; | ||
1816 | if (max < 0) | ||
1817 | goto _end; | ||
1818 | if ((unsigned int)min == saved_min && mindir == valdir) | ||
1819 | goto _end; | ||
1820 | params1 = kmalloc(sizeof(*params1), GFP_KERNEL); | ||
1821 | if (params1 == NULL) { | ||
1822 | kfree(save); | ||
1823 | return -ENOMEM; | ||
1824 | } | ||
1825 | *params1 = *save; | ||
1826 | max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir); | ||
1827 | if (max < 0) { | ||
1828 | kfree(params1); | ||
1829 | goto _end; | ||
1830 | } | ||
1831 | if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) { | ||
1832 | *params = *params1; | ||
1833 | last = 1; | ||
1834 | } | ||
1835 | kfree(params1); | ||
1836 | } else { | ||
1837 | *params = *save; | ||
1838 | max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir); | ||
1839 | assert(max >= 0); | ||
1840 | last = 1; | ||
1841 | } | ||
1842 | _end: | ||
1843 | kfree(save); | ||
1844 | if (last) | ||
1845 | v = snd_pcm_hw_param_last(pcm, params, var, dir); | ||
1846 | else | ||
1847 | v = snd_pcm_hw_param_first(pcm, params, var, dir); | ||
1848 | assert(v >= 0); | ||
1849 | return v; | ||
1850 | } | ||
1851 | 1337 | ||
1852 | /** | 1338 | /** |
1853 | * snd_pcm_hw_param_choose | 1339 | * snd_pcm_hw_param_choose |
@@ -1859,39 +1345,32 @@ int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, struct snd_pcm_hw_param | |||
1859 | * first access, first format, first subformat, min channels, | 1345 | * first access, first format, first subformat, min channels, |
1860 | * min rate, min period time, max buffer size, min tick time | 1346 | * min rate, min period time, max buffer size, min tick time |
1861 | */ | 1347 | */ |
1862 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params) | 1348 | int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, |
1863 | { | 1349 | struct snd_pcm_hw_params *params) |
1864 | int err; | 1350 | { |
1865 | 1351 | static int vars[] = { | |
1866 | err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_ACCESS, NULL); | 1352 | SNDRV_PCM_HW_PARAM_ACCESS, |
1867 | assert(err >= 0); | 1353 | SNDRV_PCM_HW_PARAM_FORMAT, |
1868 | 1354 | SNDRV_PCM_HW_PARAM_SUBFORMAT, | |
1869 | err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_FORMAT, NULL); | 1355 | SNDRV_PCM_HW_PARAM_CHANNELS, |
1870 | assert(err >= 0); | 1356 | SNDRV_PCM_HW_PARAM_RATE, |
1871 | 1357 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | |
1872 | err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_SUBFORMAT, NULL); | 1358 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, |
1873 | assert(err >= 0); | 1359 | SNDRV_PCM_HW_PARAM_TICK_TIME, |
1874 | 1360 | -1 | |
1875 | err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_CHANNELS, NULL); | 1361 | }; |
1876 | assert(err >= 0); | 1362 | int err, *v; |
1877 | |||
1878 | err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_RATE, NULL); | ||
1879 | assert(err >= 0); | ||
1880 | |||
1881 | err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_PERIOD_TIME, NULL); | ||
1882 | assert(err >= 0); | ||
1883 | |||
1884 | err = snd_pcm_hw_param_last(pcm, params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL); | ||
1885 | assert(err >= 0); | ||
1886 | |||
1887 | err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_TICK_TIME, NULL); | ||
1888 | assert(err >= 0); | ||
1889 | 1363 | ||
1364 | for (v = vars; *v != -1; v++) { | ||
1365 | if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE) | ||
1366 | err = snd_pcm_hw_param_first(pcm, params, *v, NULL); | ||
1367 | else | ||
1368 | err = snd_pcm_hw_param_last(pcm, params, *v, NULL); | ||
1369 | snd_assert(err >= 0, return err); | ||
1370 | } | ||
1890 | return 0; | 1371 | return 0; |
1891 | } | 1372 | } |
1892 | 1373 | ||
1893 | #undef assert | ||
1894 | |||
1895 | static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, | 1374 | static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream, |
1896 | void *arg) | 1375 | void *arg) |
1897 | { | 1376 | { |
@@ -1967,6 +1446,8 @@ int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | |||
1967 | return -ENXIO; | 1446 | return -ENXIO; |
1968 | } | 1447 | } |
1969 | 1448 | ||
1449 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); | ||
1450 | |||
1970 | /* | 1451 | /* |
1971 | * Conditions | 1452 | * Conditions |
1972 | */ | 1453 | */ |
@@ -2101,6 +1582,8 @@ void snd_pcm_period_elapsed(struct snd_pcm_substream *substream) | |||
2101 | kill_fasync(&runtime->fasync, SIGIO, POLL_IN); | 1582 | kill_fasync(&runtime->fasync, SIGIO, POLL_IN); |
2102 | } | 1583 | } |
2103 | 1584 | ||
1585 | EXPORT_SYMBOL(snd_pcm_period_elapsed); | ||
1586 | |||
2104 | static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, | 1587 | static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream, |
2105 | unsigned int hwoff, | 1588 | unsigned int hwoff, |
2106 | unsigned long data, unsigned int off, | 1589 | unsigned long data, unsigned int off, |
@@ -2299,7 +1782,7 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v | |||
2299 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 1782 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2300 | return -EBADFD; | 1783 | return -EBADFD; |
2301 | 1784 | ||
2302 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 1785 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
2303 | 1786 | ||
2304 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && | 1787 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED && |
2305 | runtime->channels > 1) | 1788 | runtime->channels > 1) |
@@ -2308,6 +1791,8 @@ snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const v | |||
2308 | snd_pcm_lib_write_transfer); | 1791 | snd_pcm_lib_write_transfer); |
2309 | } | 1792 | } |
2310 | 1793 | ||
1794 | EXPORT_SYMBOL(snd_pcm_lib_write); | ||
1795 | |||
2311 | static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, | 1796 | static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream, |
2312 | unsigned int hwoff, | 1797 | unsigned int hwoff, |
2313 | unsigned long data, unsigned int off, | 1798 | unsigned long data, unsigned int off, |
@@ -2362,7 +1847,7 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, | |||
2362 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 1847 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2363 | return -EBADFD; | 1848 | return -EBADFD; |
2364 | 1849 | ||
2365 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 1850 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
2366 | 1851 | ||
2367 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | 1852 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
2368 | return -EINVAL; | 1853 | return -EINVAL; |
@@ -2370,6 +1855,8 @@ snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream, | |||
2370 | nonblock, snd_pcm_lib_writev_transfer); | 1855 | nonblock, snd_pcm_lib_writev_transfer); |
2371 | } | 1856 | } |
2372 | 1857 | ||
1858 | EXPORT_SYMBOL(snd_pcm_lib_writev); | ||
1859 | |||
2373 | static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, | 1860 | static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, |
2374 | unsigned int hwoff, | 1861 | unsigned int hwoff, |
2375 | unsigned long data, unsigned int off, | 1862 | unsigned long data, unsigned int off, |
@@ -2572,12 +2059,14 @@ snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __u | |||
2572 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2059 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2573 | return -EBADFD; | 2060 | return -EBADFD; |
2574 | 2061 | ||
2575 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2062 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
2576 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) | 2063 | if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED) |
2577 | return -EINVAL; | 2064 | return -EINVAL; |
2578 | return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); | 2065 | return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer); |
2579 | } | 2066 | } |
2580 | 2067 | ||
2068 | EXPORT_SYMBOL(snd_pcm_lib_read); | ||
2069 | |||
2581 | static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, | 2070 | static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream, |
2582 | unsigned int hwoff, | 2071 | unsigned int hwoff, |
2583 | unsigned long data, unsigned int off, | 2072 | unsigned long data, unsigned int off, |
@@ -2629,58 +2118,10 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | |||
2629 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 2118 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
2630 | return -EBADFD; | 2119 | return -EBADFD; |
2631 | 2120 | ||
2632 | nonblock = !!(substream->ffile->f_flags & O_NONBLOCK); | 2121 | nonblock = !!(substream->f_flags & O_NONBLOCK); |
2633 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) | 2122 | if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) |
2634 | return -EINVAL; | 2123 | return -EINVAL; |
2635 | return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); | 2124 | return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer); |
2636 | } | 2125 | } |
2637 | 2126 | ||
2638 | /* | ||
2639 | * Exported symbols | ||
2640 | */ | ||
2641 | |||
2642 | EXPORT_SYMBOL(snd_interval_refine); | ||
2643 | EXPORT_SYMBOL(snd_interval_list); | ||
2644 | EXPORT_SYMBOL(snd_interval_ratnum); | ||
2645 | EXPORT_SYMBOL(_snd_pcm_hw_params_any); | ||
2646 | EXPORT_SYMBOL(_snd_pcm_hw_param_min); | ||
2647 | EXPORT_SYMBOL(_snd_pcm_hw_param_set); | ||
2648 | EXPORT_SYMBOL(_snd_pcm_hw_param_setempty); | ||
2649 | EXPORT_SYMBOL(_snd_pcm_hw_param_setinteger); | ||
2650 | EXPORT_SYMBOL(snd_pcm_hw_param_value_min); | ||
2651 | EXPORT_SYMBOL(snd_pcm_hw_param_value_max); | ||
2652 | EXPORT_SYMBOL(snd_pcm_hw_param_mask); | ||
2653 | EXPORT_SYMBOL(snd_pcm_hw_param_first); | ||
2654 | EXPORT_SYMBOL(snd_pcm_hw_param_last); | ||
2655 | EXPORT_SYMBOL(snd_pcm_hw_param_near); | ||
2656 | EXPORT_SYMBOL(snd_pcm_hw_param_set); | ||
2657 | EXPORT_SYMBOL(snd_pcm_hw_refine); | ||
2658 | EXPORT_SYMBOL(snd_pcm_hw_constraints_init); | ||
2659 | EXPORT_SYMBOL(snd_pcm_hw_constraints_complete); | ||
2660 | EXPORT_SYMBOL(snd_pcm_hw_constraint_list); | ||
2661 | EXPORT_SYMBOL(snd_pcm_hw_constraint_step); | ||
2662 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums); | ||
2663 | EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens); | ||
2664 | EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits); | ||
2665 | EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax); | ||
2666 | EXPORT_SYMBOL(snd_pcm_hw_constraint_integer); | ||
2667 | EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2); | ||
2668 | EXPORT_SYMBOL(snd_pcm_hw_rule_add); | ||
2669 | EXPORT_SYMBOL(snd_pcm_set_ops); | ||
2670 | EXPORT_SYMBOL(snd_pcm_set_sync); | ||
2671 | EXPORT_SYMBOL(snd_pcm_lib_ioctl); | ||
2672 | EXPORT_SYMBOL(snd_pcm_stop); | ||
2673 | EXPORT_SYMBOL(snd_pcm_period_elapsed); | ||
2674 | EXPORT_SYMBOL(snd_pcm_lib_write); | ||
2675 | EXPORT_SYMBOL(snd_pcm_lib_read); | ||
2676 | EXPORT_SYMBOL(snd_pcm_lib_writev); | ||
2677 | EXPORT_SYMBOL(snd_pcm_lib_readv); | 2127 | EXPORT_SYMBOL(snd_pcm_lib_readv); |
2678 | EXPORT_SYMBOL(snd_pcm_lib_buffer_bytes); | ||
2679 | EXPORT_SYMBOL(snd_pcm_lib_period_bytes); | ||
2680 | /* pcm_memory.c */ | ||
2681 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); | ||
2682 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); | ||
2683 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); | ||
2684 | EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); | ||
2685 | EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); | ||
2686 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); | ||
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 428f8c169ee1..067d2056db9a 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
@@ -126,6 +126,8 @@ int snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm) | |||
126 | return 0; | 126 | return 0; |
127 | } | 127 | } |
128 | 128 | ||
129 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all); | ||
130 | |||
129 | #ifdef CONFIG_SND_VERBOSE_PROCFS | 131 | #ifdef CONFIG_SND_VERBOSE_PROCFS |
130 | /* | 132 | /* |
131 | * read callback for prealloc proc file | 133 | * read callback for prealloc proc file |
@@ -191,9 +193,7 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream) | |||
191 | struct snd_info_entry *entry; | 193 | struct snd_info_entry *entry; |
192 | 194 | ||
193 | if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { | 195 | if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) { |
194 | entry->c.text.read_size = 64; | ||
195 | entry->c.text.read = snd_pcm_lib_preallocate_proc_read; | 196 | entry->c.text.read = snd_pcm_lib_preallocate_proc_read; |
196 | entry->c.text.write_size = 64; | ||
197 | entry->c.text.write = snd_pcm_lib_preallocate_proc_write; | 197 | entry->c.text.write = snd_pcm_lib_preallocate_proc_write; |
198 | entry->mode |= S_IWUSR; | 198 | entry->mode |= S_IWUSR; |
199 | entry->private_data = substream; | 199 | entry->private_data = substream; |
@@ -253,6 +253,8 @@ int snd_pcm_lib_preallocate_pages(struct snd_pcm_substream *substream, | |||
253 | return snd_pcm_lib_preallocate_pages1(substream, size, max); | 253 | return snd_pcm_lib_preallocate_pages1(substream, size, max); |
254 | } | 254 | } |
255 | 255 | ||
256 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages); | ||
257 | |||
256 | /** | 258 | /** |
257 | * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams) | 259 | * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams) |
258 | * @pcm: the pcm instance | 260 | * @pcm: the pcm instance |
@@ -280,6 +282,8 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, | |||
280 | return 0; | 282 | return 0; |
281 | } | 283 | } |
282 | 284 | ||
285 | EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); | ||
286 | |||
283 | /** | 287 | /** |
284 | * snd_pcm_sgbuf_ops_page - get the page struct at the given offset | 288 | * snd_pcm_sgbuf_ops_page - get the page struct at the given offset |
285 | * @substream: the pcm substream instance | 289 | * @substream: the pcm substream instance |
@@ -298,6 +302,8 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne | |||
298 | return sgbuf->page_table[idx]; | 302 | return sgbuf->page_table[idx]; |
299 | } | 303 | } |
300 | 304 | ||
305 | EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); | ||
306 | |||
301 | /** | 307 | /** |
302 | * snd_pcm_lib_malloc_pages - allocate the DMA buffer | 308 | * snd_pcm_lib_malloc_pages - allocate the DMA buffer |
303 | * @substream: the substream to allocate the DMA buffer to | 309 | * @substream: the substream to allocate the DMA buffer to |
@@ -349,6 +355,8 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size) | |||
349 | return 1; /* area was changed */ | 355 | return 1; /* area was changed */ |
350 | } | 356 | } |
351 | 357 | ||
358 | EXPORT_SYMBOL(snd_pcm_lib_malloc_pages); | ||
359 | |||
352 | /** | 360 | /** |
353 | * snd_pcm_lib_free_pages - release the allocated DMA buffer. | 361 | * snd_pcm_lib_free_pages - release the allocated DMA buffer. |
354 | * @substream: the substream to release the DMA buffer | 362 | * @substream: the substream to release the DMA buffer |
@@ -374,3 +382,5 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream) | |||
374 | snd_pcm_set_runtime_buffer(substream, NULL); | 382 | snd_pcm_set_runtime_buffer(substream, NULL); |
375 | return 0; | 383 | return 0; |
376 | } | 384 | } |
385 | |||
386 | EXPORT_SYMBOL(snd_pcm_lib_free_pages); | ||
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 593c77f4d181..0019c59a779d 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c | |||
@@ -207,6 +207,8 @@ int snd_pcm_format_signed(snd_pcm_format_t format) | |||
207 | return val; | 207 | return val; |
208 | } | 208 | } |
209 | 209 | ||
210 | EXPORT_SYMBOL(snd_pcm_format_signed); | ||
211 | |||
210 | /** | 212 | /** |
211 | * snd_pcm_format_unsigned - Check the PCM format is unsigned linear | 213 | * snd_pcm_format_unsigned - Check the PCM format is unsigned linear |
212 | * @format: the format to check | 214 | * @format: the format to check |
@@ -224,6 +226,8 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format) | |||
224 | return !val; | 226 | return !val; |
225 | } | 227 | } |
226 | 228 | ||
229 | EXPORT_SYMBOL(snd_pcm_format_unsigned); | ||
230 | |||
227 | /** | 231 | /** |
228 | * snd_pcm_format_linear - Check the PCM format is linear | 232 | * snd_pcm_format_linear - Check the PCM format is linear |
229 | * @format: the format to check | 233 | * @format: the format to check |
@@ -235,6 +239,8 @@ int snd_pcm_format_linear(snd_pcm_format_t format) | |||
235 | return snd_pcm_format_signed(format) >= 0; | 239 | return snd_pcm_format_signed(format) >= 0; |
236 | } | 240 | } |
237 | 241 | ||
242 | EXPORT_SYMBOL(snd_pcm_format_linear); | ||
243 | |||
238 | /** | 244 | /** |
239 | * snd_pcm_format_little_endian - Check the PCM format is little-endian | 245 | * snd_pcm_format_little_endian - Check the PCM format is little-endian |
240 | * @format: the format to check | 246 | * @format: the format to check |
@@ -252,6 +258,8 @@ int snd_pcm_format_little_endian(snd_pcm_format_t format) | |||
252 | return val; | 258 | return val; |
253 | } | 259 | } |
254 | 260 | ||
261 | EXPORT_SYMBOL(snd_pcm_format_little_endian); | ||
262 | |||
255 | /** | 263 | /** |
256 | * snd_pcm_format_big_endian - Check the PCM format is big-endian | 264 | * snd_pcm_format_big_endian - Check the PCM format is big-endian |
257 | * @format: the format to check | 265 | * @format: the format to check |
@@ -269,6 +277,8 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format) | |||
269 | return !val; | 277 | return !val; |
270 | } | 278 | } |
271 | 279 | ||
280 | EXPORT_SYMBOL(snd_pcm_format_big_endian); | ||
281 | |||
272 | /** | 282 | /** |
273 | * snd_pcm_format_width - return the bit-width of the format | 283 | * snd_pcm_format_width - return the bit-width of the format |
274 | * @format: the format to check | 284 | * @format: the format to check |
@@ -286,6 +296,8 @@ int snd_pcm_format_width(snd_pcm_format_t format) | |||
286 | return val; | 296 | return val; |
287 | } | 297 | } |
288 | 298 | ||
299 | EXPORT_SYMBOL(snd_pcm_format_width); | ||
300 | |||
289 | /** | 301 | /** |
290 | * snd_pcm_format_physical_width - return the physical bit-width of the format | 302 | * snd_pcm_format_physical_width - return the physical bit-width of the format |
291 | * @format: the format to check | 303 | * @format: the format to check |
@@ -303,6 +315,8 @@ int snd_pcm_format_physical_width(snd_pcm_format_t format) | |||
303 | return val; | 315 | return val; |
304 | } | 316 | } |
305 | 317 | ||
318 | EXPORT_SYMBOL(snd_pcm_format_physical_width); | ||
319 | |||
306 | /** | 320 | /** |
307 | * snd_pcm_format_size - return the byte size of samples on the given format | 321 | * snd_pcm_format_size - return the byte size of samples on the given format |
308 | * @format: the format to check | 322 | * @format: the format to check |
@@ -318,6 +332,8 @@ ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples) | |||
318 | return samples * phys_width / 8; | 332 | return samples * phys_width / 8; |
319 | } | 333 | } |
320 | 334 | ||
335 | EXPORT_SYMBOL(snd_pcm_format_size); | ||
336 | |||
321 | /** | 337 | /** |
322 | * snd_pcm_format_silence_64 - return the silent data in 8 bytes array | 338 | * snd_pcm_format_silence_64 - return the silent data in 8 bytes array |
323 | * @format: the format to check | 339 | * @format: the format to check |
@@ -333,6 +349,8 @@ const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) | |||
333 | return pcm_formats[format].silence; | 349 | return pcm_formats[format].silence; |
334 | } | 350 | } |
335 | 351 | ||
352 | EXPORT_SYMBOL(snd_pcm_format_silence_64); | ||
353 | |||
336 | /** | 354 | /** |
337 | * snd_pcm_format_set_silence - set the silence data on the buffer | 355 | * snd_pcm_format_set_silence - set the silence data on the buffer |
338 | * @format: the PCM format | 356 | * @format: the PCM format |
@@ -402,6 +420,8 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int | |||
402 | return 0; | 420 | return 0; |
403 | } | 421 | } |
404 | 422 | ||
423 | EXPORT_SYMBOL(snd_pcm_format_set_silence); | ||
424 | |||
405 | /* [width][unsigned][bigendian] */ | 425 | /* [width][unsigned][bigendian] */ |
406 | static int linear_formats[4][2][2] = { | 426 | static int linear_formats[4][2][2] = { |
407 | {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8}, | 427 | {{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8}, |
@@ -432,6 +452,8 @@ snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_end | |||
432 | return linear_formats[width][!!unsignd][!!big_endian]; | 452 | return linear_formats[width][!!unsignd][!!big_endian]; |
433 | } | 453 | } |
434 | 454 | ||
455 | EXPORT_SYMBOL(snd_pcm_build_linear_format); | ||
456 | |||
435 | /** | 457 | /** |
436 | * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields | 458 | * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields |
437 | * @runtime: the runtime instance | 459 | * @runtime: the runtime instance |
@@ -463,3 +485,5 @@ int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) | |||
463 | } | 485 | } |
464 | return 0; | 486 | return 0; |
465 | } | 487 | } |
488 | |||
489 | EXPORT_SYMBOL(snd_pcm_limit_hw_rates); | ||
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0860c5a84502..439f047929e1 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -71,8 +71,9 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream); | |||
71 | */ | 71 | */ |
72 | 72 | ||
73 | DEFINE_RWLOCK(snd_pcm_link_rwlock); | 73 | DEFINE_RWLOCK(snd_pcm_link_rwlock); |
74 | static DECLARE_RWSEM(snd_pcm_link_rwsem); | 74 | EXPORT_SYMBOL(snd_pcm_link_rwlock); |
75 | 75 | ||
76 | static DECLARE_RWSEM(snd_pcm_link_rwsem); | ||
76 | 77 | ||
77 | static inline mm_segment_t snd_enter_user(void) | 78 | static inline mm_segment_t snd_enter_user(void) |
78 | { | 79 | { |
@@ -319,6 +320,8 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream, | |||
319 | return 0; | 320 | return 0; |
320 | } | 321 | } |
321 | 322 | ||
323 | EXPORT_SYMBOL(snd_pcm_hw_refine); | ||
324 | |||
322 | static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, | 325 | static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream, |
323 | struct snd_pcm_hw_params __user * _params) | 326 | struct snd_pcm_hw_params __user * _params) |
324 | { | 327 | { |
@@ -369,7 +372,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | |||
369 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 372 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
370 | if (!substream->oss.oss) | 373 | if (!substream->oss.oss) |
371 | #endif | 374 | #endif |
372 | if (atomic_read(&runtime->mmap_count)) | 375 | if (atomic_read(&substream->mmap_count)) |
373 | return -EBADFD; | 376 | return -EBADFD; |
374 | 377 | ||
375 | params->rmask = ~0U; | 378 | params->rmask = ~0U; |
@@ -482,7 +485,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) | |||
482 | return -EBADFD; | 485 | return -EBADFD; |
483 | } | 486 | } |
484 | snd_pcm_stream_unlock_irq(substream); | 487 | snd_pcm_stream_unlock_irq(substream); |
485 | if (atomic_read(&runtime->mmap_count)) | 488 | if (atomic_read(&substream->mmap_count)) |
486 | return -EBADFD; | 489 | return -EBADFD; |
487 | if (substream->ops->hw_free) | 490 | if (substream->ops->hw_free) |
488 | result = substream->ops->hw_free(substream); | 491 | result = substream->ops->hw_free(substream); |
@@ -936,6 +939,8 @@ int snd_pcm_stop(struct snd_pcm_substream *substream, int state) | |||
936 | return snd_pcm_action(&snd_pcm_action_stop, substream, state); | 939 | return snd_pcm_action(&snd_pcm_action_stop, substream, state); |
937 | } | 940 | } |
938 | 941 | ||
942 | EXPORT_SYMBOL(snd_pcm_stop); | ||
943 | |||
939 | /** | 944 | /** |
940 | * snd_pcm_drain_done | 945 | * snd_pcm_drain_done |
941 | * @substream: the PCM substream | 946 | * @substream: the PCM substream |
@@ -1085,6 +1090,8 @@ int snd_pcm_suspend(struct snd_pcm_substream *substream) | |||
1085 | return err; | 1090 | return err; |
1086 | } | 1091 | } |
1087 | 1092 | ||
1093 | EXPORT_SYMBOL(snd_pcm_suspend); | ||
1094 | |||
1088 | /** | 1095 | /** |
1089 | * snd_pcm_suspend_all | 1096 | * snd_pcm_suspend_all |
1090 | * @pcm: the PCM instance | 1097 | * @pcm: the PCM instance |
@@ -1114,6 +1121,8 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm) | |||
1114 | return 0; | 1121 | return 0; |
1115 | } | 1122 | } |
1116 | 1123 | ||
1124 | EXPORT_SYMBOL(snd_pcm_suspend_all); | ||
1125 | |||
1117 | /* resume */ | 1126 | /* resume */ |
1118 | 1127 | ||
1119 | static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state) | 1128 | static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state) |
@@ -1275,13 +1284,16 @@ static int snd_pcm_reset(struct snd_pcm_substream *substream) | |||
1275 | /* | 1284 | /* |
1276 | * prepare ioctl | 1285 | * prepare ioctl |
1277 | */ | 1286 | */ |
1278 | static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state) | 1287 | /* we use the second argument for updating f_flags */ |
1288 | static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, | ||
1289 | int f_flags) | ||
1279 | { | 1290 | { |
1280 | struct snd_pcm_runtime *runtime = substream->runtime; | 1291 | struct snd_pcm_runtime *runtime = substream->runtime; |
1281 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) | 1292 | if (runtime->status->state == SNDRV_PCM_STATE_OPEN) |
1282 | return -EBADFD; | 1293 | return -EBADFD; |
1283 | if (snd_pcm_running(substream)) | 1294 | if (snd_pcm_running(substream)) |
1284 | return -EBUSY; | 1295 | return -EBUSY; |
1296 | substream->f_flags = f_flags; | ||
1285 | return 0; | 1297 | return 0; |
1286 | } | 1298 | } |
1287 | 1299 | ||
@@ -1310,17 +1322,26 @@ static struct action_ops snd_pcm_action_prepare = { | |||
1310 | /** | 1322 | /** |
1311 | * snd_pcm_prepare | 1323 | * snd_pcm_prepare |
1312 | * @substream: the PCM substream instance | 1324 | * @substream: the PCM substream instance |
1325 | * @file: file to refer f_flags | ||
1313 | * | 1326 | * |
1314 | * Prepare the PCM substream to be triggerable. | 1327 | * Prepare the PCM substream to be triggerable. |
1315 | */ | 1328 | */ |
1316 | static int snd_pcm_prepare(struct snd_pcm_substream *substream) | 1329 | static int snd_pcm_prepare(struct snd_pcm_substream *substream, |
1330 | struct file *file) | ||
1317 | { | 1331 | { |
1318 | int res; | 1332 | int res; |
1319 | struct snd_card *card = substream->pcm->card; | 1333 | struct snd_card *card = substream->pcm->card; |
1334 | int f_flags; | ||
1335 | |||
1336 | if (file) | ||
1337 | f_flags = file->f_flags; | ||
1338 | else | ||
1339 | f_flags = substream->f_flags; | ||
1320 | 1340 | ||
1321 | snd_power_lock(card); | 1341 | snd_power_lock(card); |
1322 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) | 1342 | if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0) |
1323 | res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0); | 1343 | res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, |
1344 | substream, f_flags); | ||
1324 | snd_power_unlock(card); | 1345 | snd_power_unlock(card); |
1325 | return res; | 1346 | return res; |
1326 | } | 1347 | } |
@@ -1331,7 +1352,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream) | |||
1331 | 1352 | ||
1332 | static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) | 1353 | static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state) |
1333 | { | 1354 | { |
1334 | if (substream->ffile->f_flags & O_NONBLOCK) | 1355 | if (substream->f_flags & O_NONBLOCK) |
1335 | return -EAGAIN; | 1356 | return -EAGAIN; |
1336 | substream->runtime->trigger_master = substream; | 1357 | substream->runtime->trigger_master = substream; |
1337 | return 0; | 1358 | return 0; |
@@ -1448,8 +1469,6 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) | |||
1448 | } | 1469 | } |
1449 | } | 1470 | } |
1450 | up_read(&snd_pcm_link_rwsem); | 1471 | up_read(&snd_pcm_link_rwsem); |
1451 | if (! num_drecs) | ||
1452 | goto _error; | ||
1453 | 1472 | ||
1454 | snd_pcm_stream_lock_irq(substream); | 1473 | snd_pcm_stream_lock_irq(substream); |
1455 | /* resume pause */ | 1474 | /* resume pause */ |
@@ -2006,6 +2025,10 @@ static void pcm_release_private(struct snd_pcm_substream *substream) | |||
2006 | 2025 | ||
2007 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) | 2026 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) |
2008 | { | 2027 | { |
2028 | substream->ref_count--; | ||
2029 | if (substream->ref_count > 0) | ||
2030 | return; | ||
2031 | |||
2009 | snd_pcm_drop(substream); | 2032 | snd_pcm_drop(substream); |
2010 | if (substream->hw_opened) { | 2033 | if (substream->hw_opened) { |
2011 | if (substream->ops->hw_free != NULL) | 2034 | if (substream->ops->hw_free != NULL) |
@@ -2020,6 +2043,8 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) | |||
2020 | snd_pcm_detach_substream(substream); | 2043 | snd_pcm_detach_substream(substream); |
2021 | } | 2044 | } |
2022 | 2045 | ||
2046 | EXPORT_SYMBOL(snd_pcm_release_substream); | ||
2047 | |||
2023 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | 2048 | int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, |
2024 | struct file *file, | 2049 | struct file *file, |
2025 | struct snd_pcm_substream **rsubstream) | 2050 | struct snd_pcm_substream **rsubstream) |
@@ -2030,6 +2055,11 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | |||
2030 | err = snd_pcm_attach_substream(pcm, stream, file, &substream); | 2055 | err = snd_pcm_attach_substream(pcm, stream, file, &substream); |
2031 | if (err < 0) | 2056 | if (err < 0) |
2032 | return err; | 2057 | return err; |
2058 | if (substream->ref_count > 1) { | ||
2059 | *rsubstream = substream; | ||
2060 | return 0; | ||
2061 | } | ||
2062 | |||
2033 | substream->no_mmap_ctrl = 0; | 2063 | substream->no_mmap_ctrl = 0; |
2034 | err = snd_pcm_hw_constraints_init(substream); | 2064 | err = snd_pcm_hw_constraints_init(substream); |
2035 | if (err < 0) { | 2065 | if (err < 0) { |
@@ -2056,6 +2086,8 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | |||
2056 | return err; | 2086 | return err; |
2057 | } | 2087 | } |
2058 | 2088 | ||
2089 | EXPORT_SYMBOL(snd_pcm_open_substream); | ||
2090 | |||
2059 | static int snd_pcm_open_file(struct file *file, | 2091 | static int snd_pcm_open_file(struct file *file, |
2060 | struct snd_pcm *pcm, | 2092 | struct snd_pcm *pcm, |
2061 | int stream, | 2093 | int stream, |
@@ -2073,17 +2105,20 @@ static int snd_pcm_open_file(struct file *file, | |||
2073 | if (err < 0) | 2105 | if (err < 0) |
2074 | return err; | 2106 | return err; |
2075 | 2107 | ||
2076 | pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); | 2108 | if (substream->ref_count > 1) |
2077 | if (pcm_file == NULL) { | 2109 | pcm_file = substream->file; |
2078 | snd_pcm_release_substream(substream); | 2110 | else { |
2079 | return -ENOMEM; | 2111 | pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); |
2112 | if (pcm_file == NULL) { | ||
2113 | snd_pcm_release_substream(substream); | ||
2114 | return -ENOMEM; | ||
2115 | } | ||
2116 | str = substream->pstr; | ||
2117 | substream->file = pcm_file; | ||
2118 | substream->pcm_release = pcm_release_private; | ||
2119 | pcm_file->substream = substream; | ||
2120 | snd_pcm_add_file(str, pcm_file); | ||
2080 | } | 2121 | } |
2081 | str = substream->pstr; | ||
2082 | substream->file = pcm_file; | ||
2083 | substream->pcm_release = pcm_release_private; | ||
2084 | pcm_file->substream = substream; | ||
2085 | snd_pcm_add_file(str, pcm_file); | ||
2086 | |||
2087 | file->private_data = pcm_file; | 2122 | file->private_data = pcm_file; |
2088 | *rpcm_file = pcm_file; | 2123 | *rpcm_file = pcm_file; |
2089 | return 0; | 2124 | return 0; |
@@ -2170,7 +2205,6 @@ static int snd_pcm_release(struct inode *inode, struct file *file) | |||
2170 | pcm_file = file->private_data; | 2205 | pcm_file = file->private_data; |
2171 | substream = pcm_file->substream; | 2206 | substream = pcm_file->substream; |
2172 | snd_assert(substream != NULL, return -ENXIO); | 2207 | snd_assert(substream != NULL, return -ENXIO); |
2173 | snd_assert(!atomic_read(&substream->runtime->mmap_count), ); | ||
2174 | pcm = substream->pcm; | 2208 | pcm = substream->pcm; |
2175 | fasync_helper(-1, file, 0, &substream->runtime->fasync); | 2209 | fasync_helper(-1, file, 0, &substream->runtime->fasync); |
2176 | mutex_lock(&pcm->open_mutex); | 2210 | mutex_lock(&pcm->open_mutex); |
@@ -2493,7 +2527,8 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream, | |||
2493 | return 0; | 2527 | return 0; |
2494 | } | 2528 | } |
2495 | 2529 | ||
2496 | static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, | 2530 | static int snd_pcm_common_ioctl1(struct file *file, |
2531 | struct snd_pcm_substream *substream, | ||
2497 | unsigned int cmd, void __user *arg) | 2532 | unsigned int cmd, void __user *arg) |
2498 | { | 2533 | { |
2499 | snd_assert(substream != NULL, return -ENXIO); | 2534 | snd_assert(substream != NULL, return -ENXIO); |
@@ -2518,7 +2553,7 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, | |||
2518 | case SNDRV_PCM_IOCTL_CHANNEL_INFO: | 2553 | case SNDRV_PCM_IOCTL_CHANNEL_INFO: |
2519 | return snd_pcm_channel_info_user(substream, arg); | 2554 | return snd_pcm_channel_info_user(substream, arg); |
2520 | case SNDRV_PCM_IOCTL_PREPARE: | 2555 | case SNDRV_PCM_IOCTL_PREPARE: |
2521 | return snd_pcm_prepare(substream); | 2556 | return snd_pcm_prepare(substream, file); |
2522 | case SNDRV_PCM_IOCTL_RESET: | 2557 | case SNDRV_PCM_IOCTL_RESET: |
2523 | return snd_pcm_reset(substream); | 2558 | return snd_pcm_reset(substream); |
2524 | case SNDRV_PCM_IOCTL_START: | 2559 | case SNDRV_PCM_IOCTL_START: |
@@ -2560,7 +2595,8 @@ static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream, | |||
2560 | return -ENOTTY; | 2595 | return -ENOTTY; |
2561 | } | 2596 | } |
2562 | 2597 | ||
2563 | static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, | 2598 | static int snd_pcm_playback_ioctl1(struct file *file, |
2599 | struct snd_pcm_substream *substream, | ||
2564 | unsigned int cmd, void __user *arg) | 2600 | unsigned int cmd, void __user *arg) |
2565 | { | 2601 | { |
2566 | snd_assert(substream != NULL, return -ENXIO); | 2602 | snd_assert(substream != NULL, return -ENXIO); |
@@ -2636,10 +2672,11 @@ static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream, | |||
2636 | return result < 0 ? result : 0; | 2672 | return result < 0 ? result : 0; |
2637 | } | 2673 | } |
2638 | } | 2674 | } |
2639 | return snd_pcm_common_ioctl1(substream, cmd, arg); | 2675 | return snd_pcm_common_ioctl1(file, substream, cmd, arg); |
2640 | } | 2676 | } |
2641 | 2677 | ||
2642 | static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, | 2678 | static int snd_pcm_capture_ioctl1(struct file *file, |
2679 | struct snd_pcm_substream *substream, | ||
2643 | unsigned int cmd, void __user *arg) | 2680 | unsigned int cmd, void __user *arg) |
2644 | { | 2681 | { |
2645 | snd_assert(substream != NULL, return -ENXIO); | 2682 | snd_assert(substream != NULL, return -ENXIO); |
@@ -2715,7 +2752,7 @@ static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream, | |||
2715 | return result < 0 ? result : 0; | 2752 | return result < 0 ? result : 0; |
2716 | } | 2753 | } |
2717 | } | 2754 | } |
2718 | return snd_pcm_common_ioctl1(substream, cmd, arg); | 2755 | return snd_pcm_common_ioctl1(file, substream, cmd, arg); |
2719 | } | 2756 | } |
2720 | 2757 | ||
2721 | static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, | 2758 | static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, |
@@ -2728,7 +2765,8 @@ static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, | |||
2728 | if (((cmd >> 8) & 0xff) != 'A') | 2765 | if (((cmd >> 8) & 0xff) != 'A') |
2729 | return -ENOTTY; | 2766 | return -ENOTTY; |
2730 | 2767 | ||
2731 | return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg); | 2768 | return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd, |
2769 | (void __user *)arg); | ||
2732 | } | 2770 | } |
2733 | 2771 | ||
2734 | static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, | 2772 | static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, |
@@ -2741,7 +2779,8 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, | |||
2741 | if (((cmd >> 8) & 0xff) != 'A') | 2779 | if (((cmd >> 8) & 0xff) != 'A') |
2742 | return -ENOTTY; | 2780 | return -ENOTTY; |
2743 | 2781 | ||
2744 | return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg); | 2782 | return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd, |
2783 | (void __user *)arg); | ||
2745 | } | 2784 | } |
2746 | 2785 | ||
2747 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | 2786 | int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, |
@@ -2753,12 +2792,12 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | |||
2753 | fs = snd_enter_user(); | 2792 | fs = snd_enter_user(); |
2754 | switch (substream->stream) { | 2793 | switch (substream->stream) { |
2755 | case SNDRV_PCM_STREAM_PLAYBACK: | 2794 | case SNDRV_PCM_STREAM_PLAYBACK: |
2756 | result = snd_pcm_playback_ioctl1(substream, | 2795 | result = snd_pcm_playback_ioctl1(NULL, substream, cmd, |
2757 | cmd, (void __user *)arg); | 2796 | (void __user *)arg); |
2758 | break; | 2797 | break; |
2759 | case SNDRV_PCM_STREAM_CAPTURE: | 2798 | case SNDRV_PCM_STREAM_CAPTURE: |
2760 | result = snd_pcm_capture_ioctl1(substream, | 2799 | result = snd_pcm_capture_ioctl1(NULL, substream, cmd, |
2761 | cmd, (void __user *)arg); | 2800 | (void __user *)arg); |
2762 | break; | 2801 | break; |
2763 | default: | 2802 | default: |
2764 | result = -EINVAL; | 2803 | result = -EINVAL; |
@@ -2768,6 +2807,8 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | |||
2768 | return result; | 2807 | return result; |
2769 | } | 2808 | } |
2770 | 2809 | ||
2810 | EXPORT_SYMBOL(snd_pcm_kernel_ioctl); | ||
2811 | |||
2771 | static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, | 2812 | static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, |
2772 | loff_t * offset) | 2813 | loff_t * offset) |
2773 | { | 2814 | { |
@@ -3134,7 +3175,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | |||
3134 | area->vm_ops = &snd_pcm_vm_ops_data; | 3175 | area->vm_ops = &snd_pcm_vm_ops_data; |
3135 | area->vm_private_data = substream; | 3176 | area->vm_private_data = substream; |
3136 | area->vm_flags |= VM_RESERVED; | 3177 | area->vm_flags |= VM_RESERVED; |
3137 | atomic_inc(&substream->runtime->mmap_count); | 3178 | atomic_inc(&substream->mmap_count); |
3138 | return 0; | 3179 | return 0; |
3139 | } | 3180 | } |
3140 | 3181 | ||
@@ -3166,9 +3207,11 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, | |||
3166 | (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, | 3207 | (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, |
3167 | size, area->vm_page_prot)) | 3208 | size, area->vm_page_prot)) |
3168 | return -EAGAIN; | 3209 | return -EAGAIN; |
3169 | atomic_inc(&substream->runtime->mmap_count); | 3210 | atomic_inc(&substream->mmap_count); |
3170 | return 0; | 3211 | return 0; |
3171 | } | 3212 | } |
3213 | |||
3214 | EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); | ||
3172 | #endif /* SNDRV_PCM_INFO_MMAP */ | 3215 | #endif /* SNDRV_PCM_INFO_MMAP */ |
3173 | 3216 | ||
3174 | /* | 3217 | /* |
@@ -3212,6 +3255,8 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, | |||
3212 | return snd_pcm_default_mmap(substream, area); | 3255 | return snd_pcm_default_mmap(substream, area); |
3213 | } | 3256 | } |
3214 | 3257 | ||
3258 | EXPORT_SYMBOL(snd_pcm_mmap_data); | ||
3259 | |||
3215 | static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) | 3260 | static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) |
3216 | { | 3261 | { |
3217 | struct snd_pcm_file * pcm_file; | 3262 | struct snd_pcm_file * pcm_file; |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 87b47c9564f7..8c15c66eb4aa 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -43,7 +43,7 @@ MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA."); | |||
43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
44 | 44 | ||
45 | #ifdef CONFIG_SND_OSSEMUL | 45 | #ifdef CONFIG_SND_OSSEMUL |
46 | static int midi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0}; | 46 | static int midi_map[SNDRV_CARDS]; |
47 | static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; | 47 | static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1}; |
48 | module_param_array(midi_map, int, NULL, 0444); | 48 | module_param_array(midi_map, int, NULL, 0444); |
49 | MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device."); | 49 | MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device."); |
@@ -1561,7 +1561,6 @@ static int snd_rawmidi_dev_register(struct snd_device *device) | |||
1561 | entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root); | 1561 | entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root); |
1562 | if (entry) { | 1562 | if (entry) { |
1563 | entry->private_data = rmidi; | 1563 | entry->private_data = rmidi; |
1564 | entry->c.text.read_size = 1024; | ||
1565 | entry->c.text.read = snd_rawmidi_proc_info_read; | 1564 | entry->c.text.read = snd_rawmidi_proc_info_read; |
1566 | if (snd_info_register(entry) < 0) { | 1565 | if (snd_info_register(entry) < 0) { |
1567 | snd_info_free_entry(entry); | 1566 | snd_info_free_entry(entry); |
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index b9919785180b..e7234135641c 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c | |||
@@ -291,7 +291,6 @@ register_proc(void) | |||
291 | 291 | ||
292 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 292 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
293 | entry->private_data = NULL; | 293 | entry->private_data = NULL; |
294 | entry->c.text.read_size = 1024; | ||
295 | entry->c.text.read = info_read; | 294 | entry->c.text.read = info_read; |
296 | if (snd_info_register(entry) < 0) { | 295 | if (snd_info_register(entry) < 0) { |
297 | snd_info_free_entry(entry); | 296 | snd_info_free_entry(entry); |
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c index 20f954bc7aa0..2f0d8773ac6b 100644 --- a/sound/core/seq/seq.c +++ b/sound/core/seq/seq.c | |||
@@ -129,25 +129,3 @@ static void __exit alsa_seq_exit(void) | |||
129 | 129 | ||
130 | module_init(alsa_seq_init) | 130 | module_init(alsa_seq_init) |
131 | module_exit(alsa_seq_exit) | 131 | module_exit(alsa_seq_exit) |
132 | |||
133 | /* seq_clientmgr.c */ | ||
134 | EXPORT_SYMBOL(snd_seq_create_kernel_client); | ||
135 | EXPORT_SYMBOL(snd_seq_delete_kernel_client); | ||
136 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); | ||
137 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); | ||
138 | EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); | ||
139 | EXPORT_SYMBOL(snd_seq_kernel_client_ctl); | ||
140 | EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); | ||
141 | EXPORT_SYMBOL(snd_seq_set_queue_tempo); | ||
142 | /* seq_memory.c */ | ||
143 | EXPORT_SYMBOL(snd_seq_expand_var_event); | ||
144 | EXPORT_SYMBOL(snd_seq_dump_var_event); | ||
145 | /* seq_ports.c */ | ||
146 | EXPORT_SYMBOL(snd_seq_event_port_attach); | ||
147 | EXPORT_SYMBOL(snd_seq_event_port_detach); | ||
148 | /* seq_lock.c */ | ||
149 | #if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG) | ||
150 | /*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/ | ||
151 | /*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/ | ||
152 | EXPORT_SYMBOL(snd_use_lock_sync_helper); | ||
153 | #endif | ||
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index bb15d9ee8842..532a660df51d 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -1714,6 +1714,8 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) | |||
1714 | return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); | 1714 | return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); |
1715 | } | 1715 | } |
1716 | 1716 | ||
1717 | EXPORT_SYMBOL(snd_seq_set_queue_tempo); | ||
1718 | |||
1717 | static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, | 1719 | static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, |
1718 | void __user *arg) | 1720 | void __user *arg) |
1719 | { | 1721 | { |
@@ -2264,6 +2266,8 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, | |||
2264 | return client->number; | 2266 | return client->number; |
2265 | } | 2267 | } |
2266 | 2268 | ||
2269 | EXPORT_SYMBOL(snd_seq_create_kernel_client); | ||
2270 | |||
2267 | /* exported to kernel modules */ | 2271 | /* exported to kernel modules */ |
2268 | int snd_seq_delete_kernel_client(int client) | 2272 | int snd_seq_delete_kernel_client(int client) |
2269 | { | 2273 | { |
@@ -2280,6 +2284,7 @@ int snd_seq_delete_kernel_client(int client) | |||
2280 | return 0; | 2284 | return 0; |
2281 | } | 2285 | } |
2282 | 2286 | ||
2287 | EXPORT_SYMBOL(snd_seq_delete_kernel_client); | ||
2283 | 2288 | ||
2284 | /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue | 2289 | /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue |
2285 | * and snd_seq_kernel_client_enqueue_blocking | 2290 | * and snd_seq_kernel_client_enqueue_blocking |
@@ -2328,6 +2333,8 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev, | |||
2328 | return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); | 2333 | return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); |
2329 | } | 2334 | } |
2330 | 2335 | ||
2336 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); | ||
2337 | |||
2331 | /* | 2338 | /* |
2332 | * exported, called by kernel clients to enqueue events (with blocking) | 2339 | * exported, called by kernel clients to enqueue events (with blocking) |
2333 | * | 2340 | * |
@@ -2340,6 +2347,7 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev | |||
2340 | return kernel_client_enqueue(client, ev, file, 1, atomic, hop); | 2347 | return kernel_client_enqueue(client, ev, file, 1, atomic, hop); |
2341 | } | 2348 | } |
2342 | 2349 | ||
2350 | EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); | ||
2343 | 2351 | ||
2344 | /* | 2352 | /* |
2345 | * exported, called by kernel clients to dispatch events directly to other | 2353 | * exported, called by kernel clients to dispatch events directly to other |
@@ -2376,6 +2384,7 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, | |||
2376 | return result; | 2384 | return result; |
2377 | } | 2385 | } |
2378 | 2386 | ||
2387 | EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); | ||
2379 | 2388 | ||
2380 | /* | 2389 | /* |
2381 | * exported, called by kernel clients to perform same functions as with | 2390 | * exported, called by kernel clients to perform same functions as with |
@@ -2396,6 +2405,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) | |||
2396 | return result; | 2405 | return result; |
2397 | } | 2406 | } |
2398 | 2407 | ||
2408 | EXPORT_SYMBOL(snd_seq_kernel_client_ctl); | ||
2399 | 2409 | ||
2400 | /* exported (for OSS emulator) */ | 2410 | /* exported (for OSS emulator) */ |
2401 | int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait) | 2411 | int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait) |
@@ -2413,6 +2423,8 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table | |||
2413 | return 0; | 2423 | return 0; |
2414 | } | 2424 | } |
2415 | 2425 | ||
2426 | EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); | ||
2427 | |||
2416 | /*---------------------------------------------------------------------------*/ | 2428 | /*---------------------------------------------------------------------------*/ |
2417 | 2429 | ||
2418 | #ifdef CONFIG_PROC_FS | 2430 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index d9a3e5a18d6a..d812dc886360 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c | |||
@@ -80,7 +80,7 @@ static LIST_HEAD(opslist); | |||
80 | static int num_ops; | 80 | static int num_ops; |
81 | static DEFINE_MUTEX(ops_mutex); | 81 | static DEFINE_MUTEX(ops_mutex); |
82 | #ifdef CONFIG_PROC_FS | 82 | #ifdef CONFIG_PROC_FS |
83 | static struct snd_info_entry *info_entry = NULL; | 83 | static struct snd_info_entry *info_entry; |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | /* | 86 | /* |
@@ -555,7 +555,6 @@ static int __init alsa_seq_device_init(void) | |||
555 | if (info_entry == NULL) | 555 | if (info_entry == NULL) |
556 | return -ENOMEM; | 556 | return -ENOMEM; |
557 | info_entry->content = SNDRV_INFO_CONTENT_TEXT; | 557 | info_entry->content = SNDRV_INFO_CONTENT_TEXT; |
558 | info_entry->c.text.read_size = 2048; | ||
559 | info_entry->c.text.read = snd_seq_device_info; | 558 | info_entry->c.text.read = snd_seq_device_info; |
560 | if (snd_info_register(info_entry) < 0) { | 559 | if (snd_info_register(info_entry) < 0) { |
561 | snd_info_free_entry(info_entry); | 560 | snd_info_free_entry(info_entry); |
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c index 2a283a59ea4d..e55488d1237c 100644 --- a/sound/core/seq/seq_dummy.c +++ b/sound/core/seq/seq_dummy.c | |||
@@ -66,7 +66,7 @@ MODULE_LICENSE("GPL"); | |||
66 | MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY)); | 66 | MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY)); |
67 | 67 | ||
68 | static int ports = 1; | 68 | static int ports = 1; |
69 | static int duplex = 0; | 69 | static int duplex; |
70 | 70 | ||
71 | module_param(ports, int, 0444); | 71 | module_param(ports, int, 0444); |
72 | MODULE_PARM_DESC(ports, "number of ports to be created"); | 72 | MODULE_PARM_DESC(ports, "number of ports to be created"); |
@@ -171,7 +171,9 @@ create_port(int idx, int type) | |||
171 | pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; | 171 | pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; |
172 | if (duplex) | 172 | if (duplex) |
173 | pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; | 173 | pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; |
174 | pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; | 174 | pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
175 | | SNDRV_SEQ_PORT_TYPE_SOFTWARE | ||
176 | | SNDRV_SEQ_PORT_TYPE_PORT; | ||
175 | memset(&pcb, 0, sizeof(pcb)); | 177 | memset(&pcb, 0, sizeof(pcb)); |
176 | pcb.owner = THIS_MODULE; | 178 | pcb.owner = THIS_MODULE; |
177 | pcb.unuse = dummy_unuse; | 179 | pcb.unuse = dummy_unuse; |
diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c index acce21afdaa4..142e9e6882c9 100644 --- a/sound/core/seq/seq_info.c +++ b/sound/core/seq/seq_info.c | |||
@@ -34,8 +34,8 @@ static struct snd_info_entry *timer_entry; | |||
34 | 34 | ||
35 | 35 | ||
36 | static struct snd_info_entry * __init | 36 | static struct snd_info_entry * __init |
37 | create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *, | 37 | create_info_entry(char *name, void (*read)(struct snd_info_entry *, |
38 | struct snd_info_buffer *)) | 38 | struct snd_info_buffer *)) |
39 | { | 39 | { |
40 | struct snd_info_entry *entry; | 40 | struct snd_info_entry *entry; |
41 | 41 | ||
@@ -43,7 +43,6 @@ create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *, | |||
43 | if (entry == NULL) | 43 | if (entry == NULL) |
44 | return NULL; | 44 | return NULL; |
45 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 45 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
46 | entry->c.text.read_size = size; | ||
47 | entry->c.text.read = read; | 46 | entry->c.text.read = read; |
48 | if (snd_info_register(entry) < 0) { | 47 | if (snd_info_register(entry) < 0) { |
49 | snd_info_free_entry(entry); | 48 | snd_info_free_entry(entry); |
@@ -55,11 +54,11 @@ create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *, | |||
55 | /* create all our /proc entries */ | 54 | /* create all our /proc entries */ |
56 | int __init snd_seq_info_init(void) | 55 | int __init snd_seq_info_init(void) |
57 | { | 56 | { |
58 | queues_entry = create_info_entry("queues", 512 + (256 * SNDRV_SEQ_MAX_QUEUES), | 57 | queues_entry = create_info_entry("queues", |
59 | snd_seq_info_queues_read); | 58 | snd_seq_info_queues_read); |
60 | clients_entry = create_info_entry("clients", 512 + (256 * SNDRV_SEQ_MAX_CLIENTS), | 59 | clients_entry = create_info_entry("clients", |
61 | snd_seq_info_clients_read); | 60 | snd_seq_info_clients_read); |
62 | timer_entry = create_info_entry("timer", 1024, snd_seq_info_timer_read); | 61 | timer_entry = create_info_entry("timer", snd_seq_info_timer_read); |
63 | return 0; | 62 | return 0; |
64 | } | 63 | } |
65 | 64 | ||
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c index a837a94b2d2a..1a34941d4217 100644 --- a/sound/core/seq/seq_lock.c +++ b/sound/core/seq/seq_lock.c | |||
@@ -44,4 +44,6 @@ void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line) | |||
44 | } | 44 | } |
45 | } | 45 | } |
46 | 46 | ||
47 | EXPORT_SYMBOL(snd_use_lock_sync_helper); | ||
48 | |||
47 | #endif | 49 | #endif |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 40b4f679c80e..4bffe509f719 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -118,6 +118,8 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, | |||
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
120 | 120 | ||
121 | EXPORT_SYMBOL(snd_seq_dump_var_event); | ||
122 | |||
121 | 123 | ||
122 | /* | 124 | /* |
123 | * exported: | 125 | * exported: |
@@ -167,6 +169,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char | |||
167 | return err < 0 ? err : newlen; | 169 | return err < 0 ? err : newlen; |
168 | } | 170 | } |
169 | 171 | ||
172 | EXPORT_SYMBOL(snd_seq_expand_var_event); | ||
170 | 173 | ||
171 | /* | 174 | /* |
172 | * release this cell, free extended data if available | 175 | * release this cell, free extended data if available |
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c index 9caa1372bece..1daa5b069c79 100644 --- a/sound/core/seq/seq_midi.c +++ b/sound/core/seq/seq_midi.c | |||
@@ -278,6 +278,7 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) | |||
278 | struct seq_midisynth *msynth, *ms; | 278 | struct seq_midisynth *msynth, *ms; |
279 | struct snd_seq_port_info *port; | 279 | struct snd_seq_port_info *port; |
280 | struct snd_rawmidi_info *info; | 280 | struct snd_rawmidi_info *info; |
281 | struct snd_rawmidi *rmidi = dev->private_data; | ||
281 | int newclient = 0; | 282 | int newclient = 0; |
282 | unsigned int p, ports; | 283 | unsigned int p, ports; |
283 | struct snd_seq_port_callback pcallbacks; | 284 | struct snd_seq_port_callback pcallbacks; |
@@ -320,8 +321,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) | |||
320 | } | 321 | } |
321 | client->seq_client = | 322 | client->seq_client = |
322 | snd_seq_create_kernel_client( | 323 | snd_seq_create_kernel_client( |
323 | card, 0, "%s", info->name[0] ? | 324 | card, 0, "%s", card->shortname[0] ? |
324 | (const char *)info->name : "External MIDI"); | 325 | (const char *)card->shortname : "External MIDI"); |
325 | if (client->seq_client < 0) { | 326 | if (client->seq_client < 0) { |
326 | kfree(client); | 327 | kfree(client); |
327 | mutex_unlock(®ister_mutex); | 328 | mutex_unlock(®ister_mutex); |
@@ -376,7 +377,9 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) | |||
376 | if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && | 377 | if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && |
377 | info->flags & SNDRV_RAWMIDI_INFO_DUPLEX) | 378 | info->flags & SNDRV_RAWMIDI_INFO_DUPLEX) |
378 | port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; | 379 | port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; |
379 | port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; | 380 | port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
381 | | SNDRV_SEQ_PORT_TYPE_HARDWARE | ||
382 | | SNDRV_SEQ_PORT_TYPE_PORT; | ||
380 | port->midi_channels = 16; | 383 | port->midi_channels = 16; |
381 | memset(&pcallbacks, 0, sizeof(pcallbacks)); | 384 | memset(&pcallbacks, 0, sizeof(pcallbacks)); |
382 | pcallbacks.owner = THIS_MODULE; | 385 | pcallbacks.owner = THIS_MODULE; |
@@ -387,6 +390,8 @@ snd_seq_midisynth_register_port(struct snd_seq_device *dev) | |||
387 | pcallbacks.unuse = midisynth_unuse; | 390 | pcallbacks.unuse = midisynth_unuse; |
388 | pcallbacks.event_input = event_process_midi; | 391 | pcallbacks.event_input = event_process_midi; |
389 | port->kernel = &pcallbacks; | 392 | port->kernel = &pcallbacks; |
393 | if (rmidi->ops && rmidi->ops->get_port_info) | ||
394 | rmidi->ops->get_port_info(rmidi, p, port); | ||
390 | if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0) | 395 | if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0) |
391 | goto __nomem; | 396 | goto __nomem; |
392 | ms->seq_client = client->seq_client; | 397 | ms->seq_client = client->seq_client; |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 41e078c938cd..334579a9f268 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -221,7 +221,6 @@ static void clear_subscriber_list(struct snd_seq_client *client, | |||
221 | { | 221 | { |
222 | struct list_head *p, *n; | 222 | struct list_head *p, *n; |
223 | 223 | ||
224 | down_write(&grp->list_mutex); | ||
225 | list_for_each_safe(p, n, &grp->list_head) { | 224 | list_for_each_safe(p, n, &grp->list_head) { |
226 | struct snd_seq_subscribers *subs; | 225 | struct snd_seq_subscribers *subs; |
227 | struct snd_seq_client *c; | 226 | struct snd_seq_client *c; |
@@ -259,7 +258,6 @@ static void clear_subscriber_list(struct snd_seq_client *client, | |||
259 | snd_seq_client_unlock(c); | 258 | snd_seq_client_unlock(c); |
260 | } | 259 | } |
261 | } | 260 | } |
262 | up_write(&grp->list_mutex); | ||
263 | } | 261 | } |
264 | 262 | ||
265 | /* delete port data */ | 263 | /* delete port data */ |
@@ -677,6 +675,7 @@ int snd_seq_event_port_attach(int client, | |||
677 | return ret; | 675 | return ret; |
678 | } | 676 | } |
679 | 677 | ||
678 | EXPORT_SYMBOL(snd_seq_event_port_attach); | ||
680 | 679 | ||
681 | /* | 680 | /* |
682 | * Detach the driver from a port. | 681 | * Detach the driver from a port. |
@@ -696,3 +695,5 @@ int snd_seq_event_port_detach(int client, int port) | |||
696 | 695 | ||
697 | return err; | 696 | return err; |
698 | } | 697 | } |
698 | |||
699 | EXPORT_SYMBOL(snd_seq_event_port_detach); | ||
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index f4edec603b8f..0cfa06c6b81f 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c | |||
@@ -390,7 +390,9 @@ static int snd_virmidi_dev_attach_seq(struct snd_virmidi_dev *rdev) | |||
390 | pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; | 390 | pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; |
391 | pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; | 391 | pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; |
392 | pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; | 392 | pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; |
393 | pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; | 393 | pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
394 | | SNDRV_SEQ_PORT_TYPE_SOFTWARE | ||
395 | | SNDRV_SEQ_PORT_TYPE_PORT; | ||
394 | pinfo->midi_channels = 16; | 396 | pinfo->midi_channels = 16; |
395 | memset(&pcallbacks, 0, sizeof(pcallbacks)); | 397 | memset(&pcallbacks, 0, sizeof(pcallbacks)); |
396 | pcallbacks.owner = THIS_MODULE; | 398 | pcallbacks.owner = THIS_MODULE; |
diff --git a/sound/core/sound.c b/sound/core/sound.c index 108e430b5036..cd862728346c 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
@@ -39,6 +39,8 @@ | |||
39 | 39 | ||
40 | static int major = CONFIG_SND_MAJOR; | 40 | static int major = CONFIG_SND_MAJOR; |
41 | int snd_major; | 41 | int snd_major; |
42 | EXPORT_SYMBOL(snd_major); | ||
43 | |||
42 | static int cards_limit = 1; | 44 | static int cards_limit = 1; |
43 | static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO; | 45 | static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO; |
44 | 46 | ||
@@ -60,6 +62,7 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR); | |||
60 | * modules are loaded manually, this limit number increases, too. | 62 | * modules are loaded manually, this limit number increases, too. |
61 | */ | 63 | */ |
62 | int snd_ecards_limit; | 64 | int snd_ecards_limit; |
65 | EXPORT_SYMBOL(snd_ecards_limit); | ||
63 | 66 | ||
64 | static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; | 67 | static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; |
65 | static DEFINE_MUTEX(sound_mutex); | 68 | static DEFINE_MUTEX(sound_mutex); |
@@ -78,20 +81,17 @@ extern struct class *sound_class; | |||
78 | */ | 81 | */ |
79 | void snd_request_card(int card) | 82 | void snd_request_card(int card) |
80 | { | 83 | { |
81 | int locked; | ||
82 | |||
83 | if (! current->fs->root) | 84 | if (! current->fs->root) |
84 | return; | 85 | return; |
85 | read_lock(&snd_card_rwlock); | 86 | if (snd_card_locked(card)) |
86 | locked = snd_cards_lock & (1 << card); | ||
87 | read_unlock(&snd_card_rwlock); | ||
88 | if (locked) | ||
89 | return; | 87 | return; |
90 | if (card < 0 || card >= cards_limit) | 88 | if (card < 0 || card >= cards_limit) |
91 | return; | 89 | return; |
92 | request_module("snd-card-%i", card); | 90 | request_module("snd-card-%i", card); |
93 | } | 91 | } |
94 | 92 | ||
93 | EXPORT_SYMBOL(snd_request_card); | ||
94 | |||
95 | static void snd_request_other(int minor) | 95 | static void snd_request_other(int minor) |
96 | { | 96 | { |
97 | char *str; | 97 | char *str; |
@@ -133,6 +133,8 @@ void *snd_lookup_minor_data(unsigned int minor, int type) | |||
133 | return private_data; | 133 | return private_data; |
134 | } | 134 | } |
135 | 135 | ||
136 | EXPORT_SYMBOL(snd_lookup_minor_data); | ||
137 | |||
136 | static int snd_open(struct inode *inode, struct file *file) | 138 | static int snd_open(struct inode *inode, struct file *file) |
137 | { | 139 | { |
138 | unsigned int minor = iminor(inode); | 140 | unsigned int minor = iminor(inode); |
@@ -281,6 +283,8 @@ int snd_register_device(int type, struct snd_card *card, int dev, | |||
281 | return 0; | 283 | return 0; |
282 | } | 284 | } |
283 | 285 | ||
286 | EXPORT_SYMBOL(snd_register_device); | ||
287 | |||
284 | /** | 288 | /** |
285 | * snd_unregister_device - unregister the device on the given card | 289 | * snd_unregister_device - unregister the device on the given card |
286 | * @type: the device type, SNDRV_DEVICE_TYPE_XXX | 290 | * @type: the device type, SNDRV_DEVICE_TYPE_XXX |
@@ -321,12 +325,14 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) | |||
321 | return 0; | 325 | return 0; |
322 | } | 326 | } |
323 | 327 | ||
328 | EXPORT_SYMBOL(snd_unregister_device); | ||
329 | |||
324 | #ifdef CONFIG_PROC_FS | 330 | #ifdef CONFIG_PROC_FS |
325 | /* | 331 | /* |
326 | * INFO PART | 332 | * INFO PART |
327 | */ | 333 | */ |
328 | 334 | ||
329 | static struct snd_info_entry *snd_minor_info_entry = NULL; | 335 | static struct snd_info_entry *snd_minor_info_entry; |
330 | 336 | ||
331 | static const char *snd_device_type_name(int type) | 337 | static const char *snd_device_type_name(int type) |
332 | { | 338 | { |
@@ -381,7 +387,6 @@ int __init snd_minor_info_init(void) | |||
381 | 387 | ||
382 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); | 388 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL); |
383 | if (entry) { | 389 | if (entry) { |
384 | entry->c.text.read_size = PAGE_SIZE; | ||
385 | entry->c.text.read = snd_minor_info_read; | 390 | entry->c.text.read = snd_minor_info_read; |
386 | if (snd_info_register(entry) < 0) { | 391 | if (snd_info_register(entry) < 0) { |
387 | snd_info_free_entry(entry); | 392 | snd_info_free_entry(entry); |
@@ -446,91 +451,3 @@ static void __exit alsa_sound_exit(void) | |||
446 | 451 | ||
447 | module_init(alsa_sound_init) | 452 | module_init(alsa_sound_init) |
448 | module_exit(alsa_sound_exit) | 453 | module_exit(alsa_sound_exit) |
449 | |||
450 | /* sound.c */ | ||
451 | EXPORT_SYMBOL(snd_major); | ||
452 | EXPORT_SYMBOL(snd_ecards_limit); | ||
453 | #if defined(CONFIG_KMOD) | ||
454 | EXPORT_SYMBOL(snd_request_card); | ||
455 | #endif | ||
456 | EXPORT_SYMBOL(snd_register_device); | ||
457 | EXPORT_SYMBOL(snd_unregister_device); | ||
458 | EXPORT_SYMBOL(snd_lookup_minor_data); | ||
459 | #if defined(CONFIG_SND_OSSEMUL) | ||
460 | EXPORT_SYMBOL(snd_register_oss_device); | ||
461 | EXPORT_SYMBOL(snd_unregister_oss_device); | ||
462 | EXPORT_SYMBOL(snd_lookup_oss_minor_data); | ||
463 | #endif | ||
464 | /* memory.c */ | ||
465 | EXPORT_SYMBOL(copy_to_user_fromio); | ||
466 | EXPORT_SYMBOL(copy_from_user_toio); | ||
467 | /* init.c */ | ||
468 | EXPORT_SYMBOL(snd_cards); | ||
469 | #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) | ||
470 | EXPORT_SYMBOL(snd_mixer_oss_notify_callback); | ||
471 | #endif | ||
472 | EXPORT_SYMBOL(snd_card_new); | ||
473 | EXPORT_SYMBOL(snd_card_disconnect); | ||
474 | EXPORT_SYMBOL(snd_card_free); | ||
475 | EXPORT_SYMBOL(snd_card_free_in_thread); | ||
476 | EXPORT_SYMBOL(snd_card_register); | ||
477 | EXPORT_SYMBOL(snd_component_add); | ||
478 | EXPORT_SYMBOL(snd_card_file_add); | ||
479 | EXPORT_SYMBOL(snd_card_file_remove); | ||
480 | #ifdef CONFIG_PM | ||
481 | EXPORT_SYMBOL(snd_power_wait); | ||
482 | #endif | ||
483 | /* device.c */ | ||
484 | EXPORT_SYMBOL(snd_device_new); | ||
485 | EXPORT_SYMBOL(snd_device_register); | ||
486 | EXPORT_SYMBOL(snd_device_free); | ||
487 | /* isadma.c */ | ||
488 | #ifdef CONFIG_ISA_DMA_API | ||
489 | EXPORT_SYMBOL(snd_dma_program); | ||
490 | EXPORT_SYMBOL(snd_dma_disable); | ||
491 | EXPORT_SYMBOL(snd_dma_pointer); | ||
492 | #endif | ||
493 | /* info.c */ | ||
494 | #ifdef CONFIG_PROC_FS | ||
495 | EXPORT_SYMBOL(snd_seq_root); | ||
496 | EXPORT_SYMBOL(snd_iprintf); | ||
497 | EXPORT_SYMBOL(snd_info_get_line); | ||
498 | EXPORT_SYMBOL(snd_info_get_str); | ||
499 | EXPORT_SYMBOL(snd_info_create_module_entry); | ||
500 | EXPORT_SYMBOL(snd_info_create_card_entry); | ||
501 | EXPORT_SYMBOL(snd_info_free_entry); | ||
502 | EXPORT_SYMBOL(snd_info_register); | ||
503 | EXPORT_SYMBOL(snd_info_unregister); | ||
504 | EXPORT_SYMBOL(snd_card_proc_new); | ||
505 | #endif | ||
506 | /* info_oss.c */ | ||
507 | #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) | ||
508 | EXPORT_SYMBOL(snd_oss_info_register); | ||
509 | #endif | ||
510 | /* control.c */ | ||
511 | EXPORT_SYMBOL(snd_ctl_new); | ||
512 | EXPORT_SYMBOL(snd_ctl_new1); | ||
513 | EXPORT_SYMBOL(snd_ctl_free_one); | ||
514 | EXPORT_SYMBOL(snd_ctl_add); | ||
515 | EXPORT_SYMBOL(snd_ctl_remove); | ||
516 | EXPORT_SYMBOL(snd_ctl_remove_id); | ||
517 | EXPORT_SYMBOL(snd_ctl_rename_id); | ||
518 | EXPORT_SYMBOL(snd_ctl_find_numid); | ||
519 | EXPORT_SYMBOL(snd_ctl_find_id); | ||
520 | EXPORT_SYMBOL(snd_ctl_notify); | ||
521 | EXPORT_SYMBOL(snd_ctl_register_ioctl); | ||
522 | EXPORT_SYMBOL(snd_ctl_unregister_ioctl); | ||
523 | #ifdef CONFIG_COMPAT | ||
524 | EXPORT_SYMBOL(snd_ctl_register_ioctl_compat); | ||
525 | EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat); | ||
526 | #endif | ||
527 | EXPORT_SYMBOL(snd_ctl_elem_read); | ||
528 | EXPORT_SYMBOL(snd_ctl_elem_write); | ||
529 | /* misc.c */ | ||
530 | EXPORT_SYMBOL(release_and_free_resource); | ||
531 | #ifdef CONFIG_SND_VERBOSE_PRINTK | ||
532 | EXPORT_SYMBOL(snd_verbose_printk); | ||
533 | #endif | ||
534 | #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK) | ||
535 | EXPORT_SYMBOL(snd_verbose_printd); | ||
536 | #endif | ||
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 9055c6de9587..74f0fe5a1ba0 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c | |||
@@ -58,6 +58,8 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) | |||
58 | return private_data; | 58 | return private_data; |
59 | } | 59 | } |
60 | 60 | ||
61 | EXPORT_SYMBOL(snd_lookup_oss_minor_data); | ||
62 | |||
61 | static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) | 63 | static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) |
62 | { | 64 | { |
63 | int minor; | 65 | int minor; |
@@ -158,6 +160,8 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, | |||
158 | return -EBUSY; | 160 | return -EBUSY; |
159 | } | 161 | } |
160 | 162 | ||
163 | EXPORT_SYMBOL(snd_register_oss_device); | ||
164 | |||
161 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev) | 165 | int snd_unregister_oss_device(int type, struct snd_card *card, int dev) |
162 | { | 166 | { |
163 | int minor = snd_oss_kernel_minor(type, card, dev); | 167 | int minor = snd_oss_kernel_minor(type, card, dev); |
@@ -197,13 +201,15 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) | |||
197 | return 0; | 201 | return 0; |
198 | } | 202 | } |
199 | 203 | ||
204 | EXPORT_SYMBOL(snd_unregister_oss_device); | ||
205 | |||
200 | /* | 206 | /* |
201 | * INFO PART | 207 | * INFO PART |
202 | */ | 208 | */ |
203 | 209 | ||
204 | #ifdef CONFIG_PROC_FS | 210 | #ifdef CONFIG_PROC_FS |
205 | 211 | ||
206 | static struct snd_info_entry *snd_minor_info_oss_entry = NULL; | 212 | static struct snd_info_entry *snd_minor_info_oss_entry; |
207 | 213 | ||
208 | static const char *snd_oss_device_type_name(int type) | 214 | static const char *snd_oss_device_type_name(int type) |
209 | { | 215 | { |
@@ -252,7 +258,6 @@ int __init snd_minor_info_oss_init(void) | |||
252 | 258 | ||
253 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); | 259 | entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root); |
254 | if (entry) { | 260 | if (entry) { |
255 | entry->c.text.read_size = PAGE_SIZE; | ||
256 | entry->c.text.read = snd_minor_info_oss_read; | 261 | entry->c.text.read = snd_minor_info_oss_read; |
257 | if (snd_info_register(entry) < 0) { | 262 | if (snd_info_register(entry) < 0) { |
258 | snd_info_free_entry(entry); | 263 | snd_info_free_entry(entry); |
diff --git a/sound/core/timer.c b/sound/core/timer.c index cdeeb639b675..78199f58b93a 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -1061,7 +1061,6 @@ static int snd_timer_register_system(void) | |||
1061 | static void snd_timer_proc_read(struct snd_info_entry *entry, | 1061 | static void snd_timer_proc_read(struct snd_info_entry *entry, |
1062 | struct snd_info_buffer *buffer) | 1062 | struct snd_info_buffer *buffer) |
1063 | { | 1063 | { |
1064 | unsigned long flags; | ||
1065 | struct snd_timer *timer; | 1064 | struct snd_timer *timer; |
1066 | struct snd_timer_instance *ti; | 1065 | struct snd_timer_instance *ti; |
1067 | struct list_head *p, *q; | 1066 | struct list_head *p, *q; |
@@ -1095,7 +1094,6 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, | |||
1095 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) | 1094 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) |
1096 | snd_iprintf(buffer, " SLAVE"); | 1095 | snd_iprintf(buffer, " SLAVE"); |
1097 | snd_iprintf(buffer, "\n"); | 1096 | snd_iprintf(buffer, "\n"); |
1098 | spin_lock_irqsave(&timer->lock, flags); | ||
1099 | list_for_each(q, &timer->open_list_head) { | 1097 | list_for_each(q, &timer->open_list_head) { |
1100 | ti = list_entry(q, struct snd_timer_instance, open_list); | 1098 | ti = list_entry(q, struct snd_timer_instance, open_list); |
1101 | snd_iprintf(buffer, " Client %s : %s\n", | 1099 | snd_iprintf(buffer, " Client %s : %s\n", |
@@ -1104,12 +1102,11 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, | |||
1104 | SNDRV_TIMER_IFLG_RUNNING) | 1102 | SNDRV_TIMER_IFLG_RUNNING) |
1105 | ? "running" : "stopped"); | 1103 | ? "running" : "stopped"); |
1106 | } | 1104 | } |
1107 | spin_unlock_irqrestore(&timer->lock, flags); | ||
1108 | } | 1105 | } |
1109 | mutex_unlock(®ister_mutex); | 1106 | mutex_unlock(®ister_mutex); |
1110 | } | 1107 | } |
1111 | 1108 | ||
1112 | static struct snd_info_entry *snd_timer_proc_entry = NULL; | 1109 | static struct snd_info_entry *snd_timer_proc_entry; |
1113 | 1110 | ||
1114 | static void __init snd_timer_proc_init(void) | 1111 | static void __init snd_timer_proc_init(void) |
1115 | { | 1112 | { |
@@ -1117,7 +1114,6 @@ static void __init snd_timer_proc_init(void) | |||
1117 | 1114 | ||
1118 | entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL); | 1115 | entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL); |
1119 | if (entry != NULL) { | 1116 | if (entry != NULL) { |
1120 | entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128; | ||
1121 | entry->c.text.read = snd_timer_proc_read; | 1117 | entry->c.text.read = snd_timer_proc_read; |
1122 | if (snd_info_register(entry) < 0) { | 1118 | if (snd_info_register(entry) < 0) { |
1123 | snd_info_free_entry(entry); | 1119 | snd_info_free_entry(entry); |
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index ae0df549fac7..ffeafaf2ecca 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -677,6 +677,10 @@ static int __init alsa_card_dummy_init(void) | |||
677 | i, NULL, 0); | 677 | i, NULL, 0); |
678 | if (IS_ERR(device)) | 678 | if (IS_ERR(device)) |
679 | continue; | 679 | continue; |
680 | if (!platform_get_drvdata(device)) { | ||
681 | platform_device_unregister(device); | ||
682 | continue; | ||
683 | } | ||
680 | devices[i] = device; | 684 | devices[i] = device; |
681 | cards++; | 685 | cards++; |
682 | } | 686 | } |
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 77b06009735d..d3cbbb047582 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
@@ -253,6 +253,10 @@ static int __init alsa_card_mpu401_init(void) | |||
253 | i, NULL, 0); | 253 | i, NULL, 0); |
254 | if (IS_ERR(device)) | 254 | if (IS_ERR(device)) |
255 | continue; | 255 | continue; |
256 | if (!platform_get_drvdata(device)) { | ||
257 | platform_device_unregister(device); | ||
258 | continue; | ||
259 | } | ||
256 | platform_devices[i] = device; | 260 | platform_devices[i] = device; |
257 | snd_mpu401_devices++; | 261 | snd_mpu401_devices++; |
258 | } | 262 | } |
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index b49a45cbf67a..4bf07ca9b17d 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c | |||
@@ -58,22 +58,26 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu); | |||
58 | #define MPU401_ACK 0xfe | 58 | #define MPU401_ACK 0xfe |
59 | 59 | ||
60 | /* Build in lowlevel io */ | 60 | /* Build in lowlevel io */ |
61 | static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr) | 61 | static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, |
62 | unsigned long addr) | ||
62 | { | 63 | { |
63 | outb(data, addr); | 64 | outb(data, addr); |
64 | } | 65 | } |
65 | 66 | ||
66 | static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, unsigned long addr) | 67 | static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, |
68 | unsigned long addr) | ||
67 | { | 69 | { |
68 | return inb(addr); | 70 | return inb(addr); |
69 | } | 71 | } |
70 | 72 | ||
71 | static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr) | 73 | static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, |
74 | unsigned long addr) | ||
72 | { | 75 | { |
73 | writeb(data, (void __iomem *)addr); | 76 | writeb(data, (void __iomem *)addr); |
74 | } | 77 | } |
75 | 78 | ||
76 | static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, unsigned long addr) | 79 | static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, |
80 | unsigned long addr) | ||
77 | { | 81 | { |
78 | return readb((void __iomem *)addr); | 82 | return readb((void __iomem *)addr); |
79 | } | 83 | } |
@@ -86,20 +90,13 @@ static void snd_mpu401_uart_clear_rx(struct snd_mpu401 *mpu) | |||
86 | mpu->read(mpu, MPU401D(mpu)); | 90 | mpu->read(mpu, MPU401D(mpu)); |
87 | #ifdef CONFIG_SND_DEBUG | 91 | #ifdef CONFIG_SND_DEBUG |
88 | if (timeout <= 0) | 92 | if (timeout <= 0) |
89 | snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu))); | 93 | snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n", |
94 | mpu->read(mpu, MPU401C(mpu))); | ||
90 | #endif | 95 | #endif |
91 | } | 96 | } |
92 | 97 | ||
93 | static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) | 98 | static void uart_interrupt_tx(struct snd_mpu401 *mpu) |
94 | { | 99 | { |
95 | spin_lock(&mpu->input_lock); | ||
96 | if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) { | ||
97 | snd_mpu401_uart_input_read(mpu); | ||
98 | } else { | ||
99 | snd_mpu401_uart_clear_rx(mpu); | ||
100 | } | ||
101 | spin_unlock(&mpu->input_lock); | ||
102 | /* ok. for better Tx performance try do some output when input is done */ | ||
103 | if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && | 100 | if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) && |
104 | test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { | 101 | test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) { |
105 | spin_lock(&mpu->output_lock); | 102 | spin_lock(&mpu->output_lock); |
@@ -108,6 +105,22 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) | |||
108 | } | 105 | } |
109 | } | 106 | } |
110 | 107 | ||
108 | static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) | ||
109 | { | ||
110 | if (mpu->info_flags & MPU401_INFO_INPUT) { | ||
111 | spin_lock(&mpu->input_lock); | ||
112 | if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) | ||
113 | snd_mpu401_uart_input_read(mpu); | ||
114 | else | ||
115 | snd_mpu401_uart_clear_rx(mpu); | ||
116 | spin_unlock(&mpu->input_lock); | ||
117 | } | ||
118 | if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) | ||
119 | /* ok. for better Tx performance try do some output | ||
120 | when input is done */ | ||
121 | uart_interrupt_tx(mpu); | ||
122 | } | ||
123 | |||
111 | /** | 124 | /** |
112 | * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler | 125 | * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler |
113 | * @irq: the irq number | 126 | * @irq: the irq number |
@@ -116,7 +129,8 @@ static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu) | |||
116 | * | 129 | * |
117 | * Processes the interrupt for MPU401-UART i/o. | 130 | * Processes the interrupt for MPU401-UART i/o. |
118 | */ | 131 | */ |
119 | irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 132 | irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, |
133 | struct pt_regs *regs) | ||
120 | { | 134 | { |
121 | struct snd_mpu401 *mpu = dev_id; | 135 | struct snd_mpu401 *mpu = dev_id; |
122 | 136 | ||
@@ -126,6 +140,29 @@ irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *reg | |||
126 | return IRQ_HANDLED; | 140 | return IRQ_HANDLED; |
127 | } | 141 | } |
128 | 142 | ||
143 | EXPORT_SYMBOL(snd_mpu401_uart_interrupt); | ||
144 | |||
145 | /** | ||
146 | * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler | ||
147 | * @irq: the irq number | ||
148 | * @dev_id: mpu401 instance | ||
149 | * @regs: the reigster | ||
150 | * | ||
151 | * Processes the interrupt for MPU401-UART output. | ||
152 | */ | ||
153 | irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id, | ||
154 | struct pt_regs *regs) | ||
155 | { | ||
156 | struct snd_mpu401 *mpu = dev_id; | ||
157 | |||
158 | if (mpu == NULL) | ||
159 | return IRQ_NONE; | ||
160 | uart_interrupt_tx(mpu); | ||
161 | return IRQ_HANDLED; | ||
162 | } | ||
163 | |||
164 | EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx); | ||
165 | |||
129 | /* | 166 | /* |
130 | * timer callback | 167 | * timer callback |
131 | * reprogram the timer and call the interrupt job | 168 | * reprogram the timer and call the interrupt job |
@@ -159,7 +196,8 @@ static void snd_mpu401_uart_add_timer (struct snd_mpu401 *mpu, int input) | |||
159 | mpu->timer.expires = 1 + jiffies; | 196 | mpu->timer.expires = 1 + jiffies; |
160 | add_timer(&mpu->timer); | 197 | add_timer(&mpu->timer); |
161 | } | 198 | } |
162 | mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER; | 199 | mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : |
200 | MPU401_MODE_OUTPUT_TIMER; | ||
163 | spin_unlock_irqrestore (&mpu->timer_lock, flags); | 201 | spin_unlock_irqrestore (&mpu->timer_lock, flags); |
164 | } | 202 | } |
165 | 203 | ||
@@ -172,7 +210,8 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) | |||
172 | 210 | ||
173 | spin_lock_irqsave (&mpu->timer_lock, flags); | 211 | spin_lock_irqsave (&mpu->timer_lock, flags); |
174 | if (mpu->timer_invoked) { | 212 | if (mpu->timer_invoked) { |
175 | mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER; | 213 | mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : |
214 | ~MPU401_MODE_OUTPUT_TIMER; | ||
176 | if (! mpu->timer_invoked) | 215 | if (! mpu->timer_invoked) |
177 | del_timer(&mpu->timer); | 216 | del_timer(&mpu->timer); |
178 | } | 217 | } |
@@ -180,11 +219,12 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input) | |||
180 | } | 219 | } |
181 | 220 | ||
182 | /* | 221 | /* |
183 | 222 | * send a UART command | |
223 | * return zero if successful, non-zero for some errors | ||
184 | */ | 224 | */ |
185 | 225 | ||
186 | static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, | 226 | static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, |
187 | int ack) | 227 | int ack) |
188 | { | 228 | { |
189 | unsigned long flags; | 229 | unsigned long flags; |
190 | int timeout, ok; | 230 | int timeout, ok; |
@@ -196,11 +236,13 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, | |||
196 | } | 236 | } |
197 | /* ok. standard MPU-401 initialization */ | 237 | /* ok. standard MPU-401 initialization */ |
198 | if (mpu->hardware != MPU401_HW_SB) { | 238 | if (mpu->hardware != MPU401_HW_SB) { |
199 | for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--) | 239 | for (timeout = 1000; timeout > 0 && |
240 | !snd_mpu401_output_ready(mpu); timeout--) | ||
200 | udelay(10); | 241 | udelay(10); |
201 | #ifdef CONFIG_SND_DEBUG | 242 | #ifdef CONFIG_SND_DEBUG |
202 | if (!timeout) | 243 | if (!timeout) |
203 | snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu))); | 244 | snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n", |
245 | mpu->read(mpu, MPU401C(mpu))); | ||
204 | #endif | 246 | #endif |
205 | } | 247 | } |
206 | mpu->write(mpu, cmd, MPU401C(mpu)); | 248 | mpu->write(mpu, cmd, MPU401C(mpu)); |
@@ -215,12 +257,14 @@ static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, | |||
215 | } | 257 | } |
216 | if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) | 258 | if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK) |
217 | ok = 1; | 259 | ok = 1; |
218 | } else { | 260 | } else |
219 | ok = 1; | 261 | ok = 1; |
220 | } | ||
221 | spin_unlock_irqrestore(&mpu->input_lock, flags); | 262 | spin_unlock_irqrestore(&mpu->input_lock, flags); |
222 | if (!ok) { | 263 | if (!ok) { |
223 | snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu))); | 264 | snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx " |
265 | "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port, | ||
266 | mpu->read(mpu, MPU401C(mpu)), | ||
267 | mpu->read(mpu, MPU401D(mpu))); | ||
224 | return 1; | 268 | return 1; |
225 | } | 269 | } |
226 | return 0; | 270 | return 0; |
@@ -314,7 +358,8 @@ static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream) | |||
314 | /* | 358 | /* |
315 | * trigger input callback | 359 | * trigger input callback |
316 | */ | 360 | */ |
317 | static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) | 361 | static void |
362 | snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up) | ||
318 | { | 363 | { |
319 | unsigned long flags; | 364 | unsigned long flags; |
320 | struct snd_mpu401 *mpu; | 365 | struct snd_mpu401 *mpu; |
@@ -322,7 +367,8 @@ static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substrea | |||
322 | 367 | ||
323 | mpu = substream->rmidi->private_data; | 368 | mpu = substream->rmidi->private_data; |
324 | if (up) { | 369 | if (up) { |
325 | if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) { | 370 | if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, |
371 | &mpu->mode)) { | ||
326 | /* first time - flush FIFO */ | 372 | /* first time - flush FIFO */ |
327 | while (max-- > 0) | 373 | while (max-- > 0) |
328 | mpu->read(mpu, MPU401D(mpu)); | 374 | mpu->read(mpu, MPU401D(mpu)); |
@@ -352,13 +398,11 @@ static void snd_mpu401_uart_input_read(struct snd_mpu401 * mpu) | |||
352 | unsigned char byte; | 398 | unsigned char byte; |
353 | 399 | ||
354 | while (max-- > 0) { | 400 | while (max-- > 0) { |
355 | if (snd_mpu401_input_avail(mpu)) { | 401 | if (! snd_mpu401_input_avail(mpu)) |
356 | byte = mpu->read(mpu, MPU401D(mpu)); | ||
357 | if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) | ||
358 | snd_rawmidi_receive(mpu->substream_input, &byte, 1); | ||
359 | } else { | ||
360 | break; /* input not available */ | 402 | break; /* input not available */ |
361 | } | 403 | byte = mpu->read(mpu, MPU401D(mpu)); |
404 | if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) | ||
405 | snd_rawmidi_receive(mpu->substream_input, &byte, 1); | ||
362 | } | 406 | } |
363 | } | 407 | } |
364 | 408 | ||
@@ -380,16 +424,16 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) | |||
380 | int max = 256, timeout; | 424 | int max = 256, timeout; |
381 | 425 | ||
382 | do { | 426 | do { |
383 | if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) { | 427 | if (snd_rawmidi_transmit_peek(mpu->substream_output, |
428 | &byte, 1) == 1) { | ||
384 | for (timeout = 100; timeout > 0; timeout--) { | 429 | for (timeout = 100; timeout > 0; timeout--) { |
385 | if (snd_mpu401_output_ready(mpu)) { | 430 | if (snd_mpu401_output_ready(mpu)) |
386 | mpu->write(mpu, byte, MPU401D(mpu)); | ||
387 | snd_rawmidi_transmit_ack(mpu->substream_output, 1); | ||
388 | break; | 431 | break; |
389 | } | ||
390 | } | 432 | } |
391 | if (timeout == 0) | 433 | if (timeout == 0) |
392 | break; /* Tx FIFO full - try again later */ | 434 | break; /* Tx FIFO full - try again later */ |
435 | mpu->write(mpu, byte, MPU401D(mpu)); | ||
436 | snd_rawmidi_transmit_ack(mpu->substream_output, 1); | ||
393 | } else { | 437 | } else { |
394 | snd_mpu401_uart_remove_timer (mpu, 0); | 438 | snd_mpu401_uart_remove_timer (mpu, 0); |
395 | break; /* no other data - leave the tx loop */ | 439 | break; /* no other data - leave the tx loop */ |
@@ -400,7 +444,8 @@ static void snd_mpu401_uart_output_write(struct snd_mpu401 * mpu) | |||
400 | /* | 444 | /* |
401 | * output trigger callback | 445 | * output trigger callback |
402 | */ | 446 | */ |
403 | static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) | 447 | static void |
448 | snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up) | ||
404 | { | 449 | { |
405 | unsigned long flags; | 450 | unsigned long flags; |
406 | struct snd_mpu401 *mpu; | 451 | struct snd_mpu401 *mpu; |
@@ -413,14 +458,16 @@ static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substre | |||
413 | * since the output timer might have been removed in | 458 | * since the output timer might have been removed in |
414 | * snd_mpu401_uart_output_write(). | 459 | * snd_mpu401_uart_output_write(). |
415 | */ | 460 | */ |
416 | snd_mpu401_uart_add_timer(mpu, 0); | 461 | if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) |
462 | snd_mpu401_uart_add_timer(mpu, 0); | ||
417 | 463 | ||
418 | /* output pending data */ | 464 | /* output pending data */ |
419 | spin_lock_irqsave(&mpu->output_lock, flags); | 465 | spin_lock_irqsave(&mpu->output_lock, flags); |
420 | snd_mpu401_uart_output_write(mpu); | 466 | snd_mpu401_uart_output_write(mpu); |
421 | spin_unlock_irqrestore(&mpu->output_lock, flags); | 467 | spin_unlock_irqrestore(&mpu->output_lock, flags); |
422 | } else { | 468 | } else { |
423 | snd_mpu401_uart_remove_timer(mpu, 0); | 469 | if (! (mpu->info_flags & MPU401_INFO_TX_IRQ)) |
470 | snd_mpu401_uart_remove_timer(mpu, 0); | ||
424 | clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); | 471 | clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode); |
425 | } | 472 | } |
426 | } | 473 | } |
@@ -458,7 +505,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) | |||
458 | * @device: the device index, zero-based | 505 | * @device: the device index, zero-based |
459 | * @hardware: the hardware type, MPU401_HW_XXXX | 506 | * @hardware: the hardware type, MPU401_HW_XXXX |
460 | * @port: the base address of MPU401 port | 507 | * @port: the base address of MPU401 port |
461 | * @integrated: non-zero if the port was already reserved by the chip | 508 | * @info_flags: bitflags MPU401_INFO_XXX |
462 | * @irq: the irq number, -1 if no interrupt for mpu | 509 | * @irq: the irq number, -1 if no interrupt for mpu |
463 | * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved. | 510 | * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved. |
464 | * @rrawmidi: the pointer to store the new rawmidi instance | 511 | * @rrawmidi: the pointer to store the new rawmidi instance |
@@ -473,17 +520,24 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi) | |||
473 | */ | 520 | */ |
474 | int snd_mpu401_uart_new(struct snd_card *card, int device, | 521 | int snd_mpu401_uart_new(struct snd_card *card, int device, |
475 | unsigned short hardware, | 522 | unsigned short hardware, |
476 | unsigned long port, int integrated, | 523 | unsigned long port, |
524 | unsigned int info_flags, | ||
477 | int irq, int irq_flags, | 525 | int irq, int irq_flags, |
478 | struct snd_rawmidi ** rrawmidi) | 526 | struct snd_rawmidi ** rrawmidi) |
479 | { | 527 | { |
480 | struct snd_mpu401 *mpu; | 528 | struct snd_mpu401 *mpu; |
481 | struct snd_rawmidi *rmidi; | 529 | struct snd_rawmidi *rmidi; |
530 | int in_enable, out_enable; | ||
482 | int err; | 531 | int err; |
483 | 532 | ||
484 | if (rrawmidi) | 533 | if (rrawmidi) |
485 | *rrawmidi = NULL; | 534 | *rrawmidi = NULL; |
486 | if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0) | 535 | if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT))) |
536 | info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT; | ||
537 | in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0; | ||
538 | out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0; | ||
539 | if ((err = snd_rawmidi_new(card, "MPU-401U", device, | ||
540 | out_enable, in_enable, &rmidi)) < 0) | ||
487 | return err; | 541 | return err; |
488 | mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); | 542 | mpu = kzalloc(sizeof(*mpu), GFP_KERNEL); |
489 | if (mpu == NULL) { | 543 | if (mpu == NULL) { |
@@ -497,23 +551,23 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, | |||
497 | spin_lock_init(&mpu->output_lock); | 551 | spin_lock_init(&mpu->output_lock); |
498 | spin_lock_init(&mpu->timer_lock); | 552 | spin_lock_init(&mpu->timer_lock); |
499 | mpu->hardware = hardware; | 553 | mpu->hardware = hardware; |
500 | if (!integrated) { | 554 | if (! (info_flags & MPU401_INFO_INTEGRATED)) { |
501 | int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; | 555 | int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; |
502 | if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) { | 556 | mpu->res = request_region(port, res_size, "MPU401 UART"); |
503 | snd_printk(KERN_ERR "mpu401_uart: unable to grab port 0x%lx size %d\n", port, res_size); | 557 | if (mpu->res == NULL) { |
558 | snd_printk(KERN_ERR "mpu401_uart: " | ||
559 | "unable to grab port 0x%lx size %d\n", | ||
560 | port, res_size); | ||
504 | snd_device_free(card, rmidi); | 561 | snd_device_free(card, rmidi); |
505 | return -EBUSY; | 562 | return -EBUSY; |
506 | } | 563 | } |
507 | } | 564 | } |
508 | switch (hardware) { | 565 | if (info_flags & MPU401_INFO_MMIO) { |
509 | case MPU401_HW_AUREAL: | ||
510 | mpu->write = mpu401_write_mmio; | 566 | mpu->write = mpu401_write_mmio; |
511 | mpu->read = mpu401_read_mmio; | 567 | mpu->read = mpu401_read_mmio; |
512 | break; | 568 | } else { |
513 | default: | ||
514 | mpu->write = mpu401_write_port; | 569 | mpu->write = mpu401_write_port; |
515 | mpu->read = mpu401_read_port; | 570 | mpu->read = mpu401_read_port; |
516 | break; | ||
517 | } | 571 | } |
518 | mpu->port = port; | 572 | mpu->port = port; |
519 | if (hardware == MPU401_HW_PC98II) | 573 | if (hardware == MPU401_HW_PC98II) |
@@ -521,30 +575,40 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, | |||
521 | else | 575 | else |
522 | mpu->cport = port + 1; | 576 | mpu->cport = port + 1; |
523 | if (irq >= 0 && irq_flags) { | 577 | if (irq >= 0 && irq_flags) { |
524 | if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) { | 578 | if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, |
525 | snd_printk(KERN_ERR "mpu401_uart: unable to grab IRQ %d\n", irq); | 579 | "MPU401 UART", (void *) mpu)) { |
580 | snd_printk(KERN_ERR "mpu401_uart: " | ||
581 | "unable to grab IRQ %d\n", irq); | ||
526 | snd_device_free(card, rmidi); | 582 | snd_device_free(card, rmidi); |
527 | return -EBUSY; | 583 | return -EBUSY; |
528 | } | 584 | } |
529 | } | 585 | } |
586 | mpu->info_flags = info_flags; | ||
530 | mpu->irq = irq; | 587 | mpu->irq = irq; |
531 | mpu->irq_flags = irq_flags; | 588 | mpu->irq_flags = irq_flags; |
532 | if (card->shortname[0]) | 589 | if (card->shortname[0]) |
533 | snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", card->shortname); | 590 | snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", |
591 | card->shortname); | ||
534 | else | 592 | else |
535 | sprintf(rmidi->name, "MPU-401 MIDI %d-%d", card->number, device); | 593 | sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device); |
536 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output); | 594 | if (out_enable) { |
537 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input); | 595 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, |
538 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | | 596 | &snd_mpu401_uart_output); |
539 | SNDRV_RAWMIDI_INFO_INPUT | | 597 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT; |
540 | SNDRV_RAWMIDI_INFO_DUPLEX; | 598 | } |
599 | if (in_enable) { | ||
600 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | ||
601 | &snd_mpu401_uart_input); | ||
602 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
603 | if (out_enable) | ||
604 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX; | ||
605 | } | ||
541 | mpu->rmidi = rmidi; | 606 | mpu->rmidi = rmidi; |
542 | if (rrawmidi) | 607 | if (rrawmidi) |
543 | *rrawmidi = rmidi; | 608 | *rrawmidi = rmidi; |
544 | return 0; | 609 | return 0; |
545 | } | 610 | } |
546 | 611 | ||
547 | EXPORT_SYMBOL(snd_mpu401_uart_interrupt); | ||
548 | EXPORT_SYMBOL(snd_mpu401_uart_new); | 612 | EXPORT_SYMBOL(snd_mpu401_uart_new); |
549 | 613 | ||
550 | /* | 614 | /* |
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c index b7a0b42813e1..474eed06e70f 100644 --- a/sound/drivers/mtpav.c +++ b/sound/drivers/mtpav.c | |||
@@ -770,11 +770,15 @@ static int __init alsa_card_mtpav_init(void) | |||
770 | return err; | 770 | return err; |
771 | 771 | ||
772 | device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); | 772 | device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0); |
773 | if (IS_ERR(device)) { | 773 | if (!IS_ERR(device)) { |
774 | platform_driver_unregister(&snd_mtpav_driver); | 774 | if (platform_get_drvdata(device)) |
775 | return PTR_ERR(device); | 775 | return 0; |
776 | } | 776 | platform_device_unregister(device); |
777 | return 0; | 777 | err = -ENODEV; |
778 | } else | ||
779 | err = PTR_ERR(device); | ||
780 | platform_driver_unregister(&snd_mtpav_driver); | ||
781 | return err; | ||
778 | } | 782 | } |
779 | 783 | ||
780 | static void __exit alsa_card_mtpav_exit(void) | 784 | static void __exit alsa_card_mtpav_exit(void) |
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c index 4f8556976774..87fe376f38f0 100644 --- a/sound/drivers/opl3/opl3_lib.c +++ b/sound/drivers/opl3/opl3_lib.c | |||
@@ -316,6 +316,8 @@ void snd_opl3_interrupt(struct snd_hwdep * hw) | |||
316 | } | 316 | } |
317 | } | 317 | } |
318 | 318 | ||
319 | EXPORT_SYMBOL(snd_opl3_interrupt); | ||
320 | |||
319 | /* | 321 | /* |
320 | 322 | ||
321 | */ | 323 | */ |
@@ -369,6 +371,8 @@ int snd_opl3_new(struct snd_card *card, | |||
369 | return 0; | 371 | return 0; |
370 | } | 372 | } |
371 | 373 | ||
374 | EXPORT_SYMBOL(snd_opl3_new); | ||
375 | |||
372 | int snd_opl3_init(struct snd_opl3 *opl3) | 376 | int snd_opl3_init(struct snd_opl3 *opl3) |
373 | { | 377 | { |
374 | if (! opl3->command) { | 378 | if (! opl3->command) { |
@@ -393,6 +397,8 @@ int snd_opl3_init(struct snd_opl3 *opl3) | |||
393 | return 0; | 397 | return 0; |
394 | } | 398 | } |
395 | 399 | ||
400 | EXPORT_SYMBOL(snd_opl3_init); | ||
401 | |||
396 | int snd_opl3_create(struct snd_card *card, | 402 | int snd_opl3_create(struct snd_card *card, |
397 | unsigned long l_port, | 403 | unsigned long l_port, |
398 | unsigned long r_port, | 404 | unsigned long r_port, |
@@ -451,6 +457,8 @@ int snd_opl3_create(struct snd_card *card, | |||
451 | return 0; | 457 | return 0; |
452 | } | 458 | } |
453 | 459 | ||
460 | EXPORT_SYMBOL(snd_opl3_create); | ||
461 | |||
454 | int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) | 462 | int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) |
455 | { | 463 | { |
456 | int err; | 464 | int err; |
@@ -468,6 +476,8 @@ int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev) | |||
468 | return 0; | 476 | return 0; |
469 | } | 477 | } |
470 | 478 | ||
479 | EXPORT_SYMBOL(snd_opl3_timer_new); | ||
480 | |||
471 | int snd_opl3_hwdep_new(struct snd_opl3 * opl3, | 481 | int snd_opl3_hwdep_new(struct snd_opl3 * opl3, |
472 | int device, int seq_device, | 482 | int device, int seq_device, |
473 | struct snd_hwdep ** rhwdep) | 483 | struct snd_hwdep ** rhwdep) |
@@ -526,17 +536,8 @@ int snd_opl3_hwdep_new(struct snd_opl3 * opl3, | |||
526 | return 0; | 536 | return 0; |
527 | } | 537 | } |
528 | 538 | ||
529 | EXPORT_SYMBOL(snd_opl3_interrupt); | ||
530 | EXPORT_SYMBOL(snd_opl3_new); | ||
531 | EXPORT_SYMBOL(snd_opl3_init); | ||
532 | EXPORT_SYMBOL(snd_opl3_create); | ||
533 | EXPORT_SYMBOL(snd_opl3_timer_new); | ||
534 | EXPORT_SYMBOL(snd_opl3_hwdep_new); | 539 | EXPORT_SYMBOL(snd_opl3_hwdep_new); |
535 | 540 | ||
536 | /* opl3_synth.c */ | ||
537 | EXPORT_SYMBOL(snd_opl3_regmap); | ||
538 | EXPORT_SYMBOL(snd_opl3_reset); | ||
539 | |||
540 | /* | 541 | /* |
541 | * INIT part | 542 | * INIT part |
542 | */ | 543 | */ |
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c index fccf019a6d85..5fd3a4c95626 100644 --- a/sound/drivers/opl3/opl3_oss.c +++ b/sound/drivers/opl3/opl3_oss.c | |||
@@ -100,7 +100,8 @@ static int snd_opl3_oss_create_port(struct snd_opl3 * opl3) | |||
100 | SNDRV_SEQ_PORT_CAP_WRITE, | 100 | SNDRV_SEQ_PORT_CAP_WRITE, |
101 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | | 101 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | |
102 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | | 102 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | |
103 | SNDRV_SEQ_PORT_TYPE_SYNTH, | 103 | SNDRV_SEQ_PORT_TYPE_HARDWARE | |
104 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
104 | voices, voices, | 105 | voices, voices, |
105 | name); | 106 | name); |
106 | if (opl3->oss_chset->port < 0) { | 107 | if (opl3->oss_chset->port < 0) { |
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c index 57becf34f43e..96762c9d4855 100644 --- a/sound/drivers/opl3/opl3_seq.c +++ b/sound/drivers/opl3/opl3_seq.c | |||
@@ -203,7 +203,9 @@ static int snd_opl3_synth_create_port(struct snd_opl3 * opl3) | |||
203 | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, | 203 | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, |
204 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | | 204 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | |
205 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | | 205 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | |
206 | SNDRV_SEQ_PORT_TYPE_SYNTH, | 206 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | |
207 | SNDRV_SEQ_PORT_TYPE_HARDWARE | | ||
208 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
207 | 16, voices, | 209 | 16, voices, |
208 | name); | 210 | name); |
209 | if (opl3->chset->port < 0) { | 211 | if (opl3->chset->port < 0) { |
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c index 6db503f025b3..a4b3543a7118 100644 --- a/sound/drivers/opl3/opl3_synth.c +++ b/sound/drivers/opl3/opl3_synth.c | |||
@@ -58,6 +58,8 @@ char snd_opl3_regmap[MAX_OPL2_VOICES][4] = | |||
58 | { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ | 58 | { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */ |
59 | }; | 59 | }; |
60 | 60 | ||
61 | EXPORT_SYMBOL(snd_opl3_regmap); | ||
62 | |||
61 | /* | 63 | /* |
62 | * prototypes | 64 | * prototypes |
63 | */ | 65 | */ |
@@ -228,6 +230,7 @@ void snd_opl3_reset(struct snd_opl3 * opl3) | |||
228 | opl3->rhythm = 0; | 230 | opl3->rhythm = 0; |
229 | } | 231 | } |
230 | 232 | ||
233 | EXPORT_SYMBOL(snd_opl3_reset); | ||
231 | 234 | ||
232 | static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note) | 235 | static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note) |
233 | { | 236 | { |
@@ -445,3 +448,4 @@ static int snd_opl3_set_connection(struct snd_opl3 * opl3, int connection) | |||
445 | 448 | ||
446 | return 0; | 449 | return 0; |
447 | } | 450 | } |
451 | |||
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c index 4bc860ae02de..01997f24c895 100644 --- a/sound/drivers/opl4/opl4_lib.c +++ b/sound/drivers/opl4/opl4_lib.c | |||
@@ -43,6 +43,8 @@ void snd_opl4_write(struct snd_opl4 *opl4, u8 reg, u8 value) | |||
43 | outb(value, opl4->pcm_port + 1); | 43 | outb(value, opl4->pcm_port + 1); |
44 | } | 44 | } |
45 | 45 | ||
46 | EXPORT_SYMBOL(snd_opl4_write); | ||
47 | |||
46 | u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) | 48 | u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) |
47 | { | 49 | { |
48 | snd_opl4_wait(opl4); | 50 | snd_opl4_wait(opl4); |
@@ -52,6 +54,8 @@ u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg) | |||
52 | return inb(opl4->pcm_port + 1); | 54 | return inb(opl4->pcm_port + 1); |
53 | } | 55 | } |
54 | 56 | ||
57 | EXPORT_SYMBOL(snd_opl4_read); | ||
58 | |||
55 | void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) | 59 | void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size) |
56 | { | 60 | { |
57 | unsigned long flags; | 61 | unsigned long flags; |
@@ -76,6 +80,8 @@ void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size | |||
76 | spin_unlock_irqrestore(&opl4->reg_lock, flags); | 80 | spin_unlock_irqrestore(&opl4->reg_lock, flags); |
77 | } | 81 | } |
78 | 82 | ||
83 | EXPORT_SYMBOL(snd_opl4_read_memory); | ||
84 | |||
79 | void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) | 85 | void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size) |
80 | { | 86 | { |
81 | unsigned long flags; | 87 | unsigned long flags; |
@@ -100,6 +106,8 @@ void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, i | |||
100 | spin_unlock_irqrestore(&opl4->reg_lock, flags); | 106 | spin_unlock_irqrestore(&opl4->reg_lock, flags); |
101 | } | 107 | } |
102 | 108 | ||
109 | EXPORT_SYMBOL(snd_opl4_write_memory); | ||
110 | |||
103 | static void snd_opl4_enable_opl4(struct snd_opl4 *opl4) | 111 | static void snd_opl4_enable_opl4(struct snd_opl4 *opl4) |
104 | { | 112 | { |
105 | outb(OPL3_REG_MODE, opl4->fm_port + 2); | 113 | outb(OPL3_REG_MODE, opl4->fm_port + 2); |
@@ -256,10 +264,6 @@ int snd_opl4_create(struct snd_card *card, | |||
256 | return 0; | 264 | return 0; |
257 | } | 265 | } |
258 | 266 | ||
259 | EXPORT_SYMBOL(snd_opl4_write); | ||
260 | EXPORT_SYMBOL(snd_opl4_read); | ||
261 | EXPORT_SYMBOL(snd_opl4_write_memory); | ||
262 | EXPORT_SYMBOL(snd_opl4_read_memory); | ||
263 | EXPORT_SYMBOL(snd_opl4_create); | 267 | EXPORT_SYMBOL(snd_opl4_create); |
264 | 268 | ||
265 | static int __init alsa_opl4_init(void) | 269 | static int __init alsa_opl4_init(void) |
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c index dc0dcdc6c313..43d8a2bdd280 100644 --- a/sound/drivers/opl4/opl4_seq.c +++ b/sound/drivers/opl4/opl4_seq.c | |||
@@ -164,7 +164,9 @@ static int snd_opl4_seq_new_device(struct snd_seq_device *dev) | |||
164 | SNDRV_SEQ_PORT_CAP_WRITE | | 164 | SNDRV_SEQ_PORT_CAP_WRITE | |
165 | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, | 165 | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, |
166 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | | 166 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | |
167 | SNDRV_SEQ_PORT_TYPE_MIDI_GM, | 167 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | |
168 | SNDRV_SEQ_PORT_TYPE_HARDWARE | | ||
169 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
168 | 16, 24, | 170 | 16, 24, |
169 | "OPL4 Wavetable Port"); | 171 | "OPL4 Wavetable Port"); |
170 | if (opl4->chset->port < 0) { | 172 | if (opl4->chset->port < 0) { |
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index c01b4c5118b9..2330fec505da 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -998,6 +998,10 @@ static int __init alsa_card_serial_init(void) | |||
998 | i, NULL, 0); | 998 | i, NULL, 0); |
999 | if (IS_ERR(device)) | 999 | if (IS_ERR(device)) |
1000 | continue; | 1000 | continue; |
1001 | if (!platform_get_drvdata(device)) { | ||
1002 | platform_device_unregister(device); | ||
1003 | continue; | ||
1004 | } | ||
1001 | devices[i] = device; | 1005 | devices[i] = device; |
1002 | cards++; | 1006 | cards++; |
1003 | } | 1007 | } |
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 26eb2499d442..59171f8200df 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c | |||
@@ -171,6 +171,10 @@ static int __init alsa_card_virmidi_init(void) | |||
171 | i, NULL, 0); | 171 | i, NULL, 0); |
172 | if (IS_ERR(device)) | 172 | if (IS_ERR(device)) |
173 | continue; | 173 | continue; |
174 | if (!platform_get_drvdata(device)) { | ||
175 | platform_device_unregister(device); | ||
176 | continue; | ||
177 | } | ||
174 | devices[i] = device; | 178 | devices[i] = device; |
175 | cards++; | 179 | cards++; |
176 | } | 180 | } |
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c index fa4a2b5c2d8d..a60168268ddd 100644 --- a/sound/drivers/vx/vx_core.c +++ b/sound/drivers/vx/vx_core.c | |||
@@ -70,6 +70,8 @@ int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int t | |||
70 | return -EIO; | 70 | return -EIO; |
71 | } | 71 | } |
72 | 72 | ||
73 | EXPORT_SYMBOL(snd_vx_check_reg_bit); | ||
74 | |||
73 | /* | 75 | /* |
74 | * vx_send_irq_dsp - set command irq bit | 76 | * vx_send_irq_dsp - set command irq bit |
75 | * @num: the requested IRQ type, IRQ_XXX | 77 | * @num: the requested IRQ type, IRQ_XXX |
@@ -465,6 +467,8 @@ int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *boot) | |||
465 | return 0; | 467 | return 0; |
466 | } | 468 | } |
467 | 469 | ||
470 | EXPORT_SYMBOL(snd_vx_load_boot_image); | ||
471 | |||
468 | /* | 472 | /* |
469 | * vx_test_irq_src - query the source of interrupts | 473 | * vx_test_irq_src - query the source of interrupts |
470 | * | 474 | * |
@@ -545,6 +549,7 @@ irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs) | |||
545 | return IRQ_HANDLED; | 549 | return IRQ_HANDLED; |
546 | } | 550 | } |
547 | 551 | ||
552 | EXPORT_SYMBOL(snd_vx_irq_handler); | ||
548 | 553 | ||
549 | /* | 554 | /* |
550 | */ | 555 | */ |
@@ -635,7 +640,7 @@ static void vx_proc_init(struct vx_core *chip) | |||
635 | struct snd_info_entry *entry; | 640 | struct snd_info_entry *entry; |
636 | 641 | ||
637 | if (! snd_card_proc_new(chip->card, "vx-status", &entry)) | 642 | if (! snd_card_proc_new(chip->card, "vx-status", &entry)) |
638 | snd_info_set_text_ops(entry, chip, 1024, vx_proc_read); | 643 | snd_info_set_text_ops(entry, chip, vx_proc_read); |
639 | } | 644 | } |
640 | 645 | ||
641 | 646 | ||
@@ -657,6 +662,8 @@ int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *boot) | |||
657 | return 0; | 662 | return 0; |
658 | } | 663 | } |
659 | 664 | ||
665 | EXPORT_SYMBOL(snd_vx_dsp_boot); | ||
666 | |||
660 | /** | 667 | /** |
661 | * snd_vx_dsp_load - load the DSP image | 668 | * snd_vx_dsp_load - load the DSP image |
662 | */ | 669 | */ |
@@ -705,6 +712,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp) | |||
705 | return 0; | 712 | return 0; |
706 | } | 713 | } |
707 | 714 | ||
715 | EXPORT_SYMBOL(snd_vx_dsp_load); | ||
716 | |||
708 | #ifdef CONFIG_PM | 717 | #ifdef CONFIG_PM |
709 | /* | 718 | /* |
710 | * suspend | 719 | * suspend |
@@ -721,6 +730,8 @@ int snd_vx_suspend(struct vx_core *chip, pm_message_t state) | |||
721 | return 0; | 730 | return 0; |
722 | } | 731 | } |
723 | 732 | ||
733 | EXPORT_SYMBOL(snd_vx_suspend); | ||
734 | |||
724 | /* | 735 | /* |
725 | * resume | 736 | * resume |
726 | */ | 737 | */ |
@@ -747,6 +758,7 @@ int snd_vx_resume(struct vx_core *chip) | |||
747 | return 0; | 758 | return 0; |
748 | } | 759 | } |
749 | 760 | ||
761 | EXPORT_SYMBOL(snd_vx_resume); | ||
750 | #endif | 762 | #endif |
751 | 763 | ||
752 | /** | 764 | /** |
@@ -790,6 +802,8 @@ struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw, | |||
790 | return chip; | 802 | return chip; |
791 | } | 803 | } |
792 | 804 | ||
805 | EXPORT_SYMBOL(snd_vx_create); | ||
806 | |||
793 | /* | 807 | /* |
794 | * module entries | 808 | * module entries |
795 | */ | 809 | */ |
@@ -804,19 +818,3 @@ static void __exit alsa_vx_core_exit(void) | |||
804 | 818 | ||
805 | module_init(alsa_vx_core_init) | 819 | module_init(alsa_vx_core_init) |
806 | module_exit(alsa_vx_core_exit) | 820 | module_exit(alsa_vx_core_exit) |
807 | |||
808 | /* | ||
809 | * exports | ||
810 | */ | ||
811 | EXPORT_SYMBOL(snd_vx_check_reg_bit); | ||
812 | EXPORT_SYMBOL(snd_vx_create); | ||
813 | EXPORT_SYMBOL(snd_vx_setup_firmware); | ||
814 | EXPORT_SYMBOL(snd_vx_free_firmware); | ||
815 | EXPORT_SYMBOL(snd_vx_irq_handler); | ||
816 | EXPORT_SYMBOL(snd_vx_dsp_boot); | ||
817 | EXPORT_SYMBOL(snd_vx_dsp_load); | ||
818 | EXPORT_SYMBOL(snd_vx_load_boot_image); | ||
819 | #ifdef CONFIG_PM | ||
820 | EXPORT_SYMBOL(snd_vx_suspend); | ||
821 | EXPORT_SYMBOL(snd_vx_resume); | ||
822 | #endif | ||
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c index d837783fb538..e1920af4501d 100644 --- a/sound/drivers/vx/vx_hwdep.c +++ b/sound/drivers/vx/vx_hwdep.c | |||
@@ -250,3 +250,6 @@ void snd_vx_free_firmware(struct vx_core *chip) | |||
250 | } | 250 | } |
251 | 251 | ||
252 | #endif /* SND_VX_FW_LOADER */ | 252 | #endif /* SND_VX_FW_LOADER */ |
253 | |||
254 | EXPORT_SYMBOL(snd_vx_setup_firmware); | ||
255 | EXPORT_SYMBOL(snd_vx_free_firmware); | ||
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c index edfe76fb0074..b60fb1892828 100644 --- a/sound/i2c/i2c.c +++ b/sound/i2c/i2c.c | |||
@@ -106,6 +106,8 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name, | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | EXPORT_SYMBOL(snd_i2c_bus_create); | ||
110 | |||
109 | int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, | 111 | int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, |
110 | unsigned char addr, struct snd_i2c_device **rdevice) | 112 | unsigned char addr, struct snd_i2c_device **rdevice) |
111 | { | 113 | { |
@@ -124,6 +126,8 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name, | |||
124 | return 0; | 126 | return 0; |
125 | } | 127 | } |
126 | 128 | ||
129 | EXPORT_SYMBOL(snd_i2c_device_create); | ||
130 | |||
127 | int snd_i2c_device_free(struct snd_i2c_device *device) | 131 | int snd_i2c_device_free(struct snd_i2c_device *device) |
128 | { | 132 | { |
129 | if (device->bus) | 133 | if (device->bus) |
@@ -134,22 +138,29 @@ int snd_i2c_device_free(struct snd_i2c_device *device) | |||
134 | return 0; | 138 | return 0; |
135 | } | 139 | } |
136 | 140 | ||
141 | EXPORT_SYMBOL(snd_i2c_device_free); | ||
142 | |||
137 | int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) | 143 | int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) |
138 | { | 144 | { |
139 | return device->bus->ops->sendbytes(device, bytes, count); | 145 | return device->bus->ops->sendbytes(device, bytes, count); |
140 | } | 146 | } |
141 | 147 | ||
148 | EXPORT_SYMBOL(snd_i2c_sendbytes); | ||
142 | 149 | ||
143 | int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) | 150 | int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count) |
144 | { | 151 | { |
145 | return device->bus->ops->readbytes(device, bytes, count); | 152 | return device->bus->ops->readbytes(device, bytes, count); |
146 | } | 153 | } |
147 | 154 | ||
155 | EXPORT_SYMBOL(snd_i2c_readbytes); | ||
156 | |||
148 | int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) | 157 | int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) |
149 | { | 158 | { |
150 | return bus->ops->probeaddr(bus, addr); | 159 | return bus->ops->probeaddr(bus, addr); |
151 | } | 160 | } |
152 | 161 | ||
162 | EXPORT_SYMBOL(snd_i2c_probeaddr); | ||
163 | |||
153 | /* | 164 | /* |
154 | * bit-operations | 165 | * bit-operations |
155 | */ | 166 | */ |
@@ -320,12 +331,6 @@ static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr) | |||
320 | return err; | 331 | return err; |
321 | } | 332 | } |
322 | 333 | ||
323 | EXPORT_SYMBOL(snd_i2c_bus_create); | ||
324 | EXPORT_SYMBOL(snd_i2c_device_create); | ||
325 | EXPORT_SYMBOL(snd_i2c_device_free); | ||
326 | EXPORT_SYMBOL(snd_i2c_sendbytes); | ||
327 | EXPORT_SYMBOL(snd_i2c_readbytes); | ||
328 | EXPORT_SYMBOL(snd_i2c_probeaddr); | ||
329 | 334 | ||
330 | static int __init alsa_i2c_init(void) | 335 | static int __init alsa_i2c_init(void) |
331 | { | 336 | { |
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c index 746500e06950..b074fdddea55 100644 --- a/sound/i2c/l3/uda1341.c +++ b/sound/i2c/l3/uda1341.c | |||
@@ -517,9 +517,9 @@ static void __devinit snd_uda1341_proc_init(struct snd_card *card, struct l3_cli | |||
517 | struct snd_info_entry *entry; | 517 | struct snd_info_entry *entry; |
518 | 518 | ||
519 | if (! snd_card_proc_new(card, "uda1341", &entry)) | 519 | if (! snd_card_proc_new(card, "uda1341", &entry)) |
520 | snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_read); | 520 | snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read); |
521 | if (! snd_card_proc_new(card, "uda1341-regs", &entry)) | 521 | if (! snd_card_proc_new(card, "uda1341-regs", &entry)) |
522 | snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_regs_read); | 522 | snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read); |
523 | } | 523 | } |
524 | 524 | ||
525 | /* }}} */ | 525 | /* }}} */ |
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c index c19ba2910b72..42db37552efb 100644 --- a/sound/isa/gus/gus_irq.c +++ b/sound/isa/gus/gus_irq.c | |||
@@ -136,7 +136,7 @@ void snd_gus_irq_profile_init(struct snd_gus_card *gus) | |||
136 | struct snd_info_entry *entry; | 136 | struct snd_info_entry *entry; |
137 | 137 | ||
138 | if (! snd_card_proc_new(gus->card, "gusirq", &entry)) | 138 | if (! snd_card_proc_new(gus->card, "gusirq", &entry)) |
139 | snd_info_set_text_ops(entry, gus, 1024, snd_gus_irq_info_read); | 139 | snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read); |
140 | } | 140 | } |
141 | 141 | ||
142 | #endif | 142 | #endif |
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c index 3c0d27aa08b3..f50c276caee8 100644 --- a/sound/isa/gus/gus_mem.c +++ b/sound/isa/gus/gus_mem.c | |||
@@ -264,10 +264,8 @@ int snd_gf1_mem_init(struct snd_gus_card * gus) | |||
264 | if (snd_gf1_mem_xalloc(alloc, &block) == NULL) | 264 | if (snd_gf1_mem_xalloc(alloc, &block) == NULL) |
265 | return -ENOMEM; | 265 | return -ENOMEM; |
266 | #ifdef CONFIG_SND_DEBUG | 266 | #ifdef CONFIG_SND_DEBUG |
267 | if (! snd_card_proc_new(gus->card, "gusmem", &entry)) { | 267 | if (! snd_card_proc_new(gus->card, "gusmem", &entry)) |
268 | snd_info_set_text_ops(entry, gus, 1024, snd_gf1_mem_info_read); | 268 | snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read); |
269 | entry->c.text.read_size = 256 * 1024; | ||
270 | } | ||
271 | #endif | 269 | #endif |
272 | return 0; | 270 | return 0; |
273 | } | 271 | } |
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c index 2767cc187ae3..3e4d4d6edd8b 100644 --- a/sound/isa/gus/gus_synth.c +++ b/sound/isa/gus/gus_synth.c | |||
@@ -194,7 +194,9 @@ static int snd_gus_synth_create_port(struct snd_gus_card * gus, int idx) | |||
194 | &callbacks, | 194 | &callbacks, |
195 | SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, | 195 | SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, |
196 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | | 196 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | |
197 | SNDRV_SEQ_PORT_TYPE_SYNTH, | 197 | SNDRV_SEQ_PORT_TYPE_SYNTH | |
198 | SNDRV_SEQ_PORT_TYPE_HARDWARE | | ||
199 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
198 | 16, 0, | 200 | 16, 0, |
199 | name); | 201 | name); |
200 | if (p->chset->port < 0) { | 202 | if (p->chset->port < 0) { |
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index 4298d339e786..866300f2acbb 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
@@ -70,9 +70,9 @@ static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ | |||
70 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ | 70 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ |
71 | static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; | 71 | static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29}; |
72 | /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ | 72 | /* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */ |
73 | static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 73 | static int midi[SNDRV_CARDS]; |
74 | static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; | 74 | static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; |
75 | static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 75 | static int effect[SNDRV_CARDS]; |
76 | 76 | ||
77 | #ifdef SNDRV_STB | 77 | #ifdef SNDRV_STB |
78 | #define PFX "interwave-stb: " | 78 | #define PFX "interwave-stb: " |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 6d889052c32c..647a996791e9 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -59,7 +59,7 @@ static long midi_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;/* 0x330,0x300 */ | |||
59 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */ | 59 | static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 0,1,3,5,9,11,12,15 */ |
60 | static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ | 60 | static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ |
61 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ | 61 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */ |
62 | static int opl3sa3_ymode[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* 0,1,2,3 */ /*SL Added*/ | 62 | static int opl3sa3_ymode[SNDRV_CARDS]; /* 0,1,2,3 */ /*SL Added*/ |
63 | 63 | ||
64 | module_param_array(index, int, NULL, 0444); | 64 | module_param_array(index, int, NULL, 0444); |
65 | MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard."); | 65 | MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard."); |
@@ -221,7 +221,7 @@ static void snd_opl3sa2_write(struct snd_opl3sa2 *chip, unsigned char reg, unsig | |||
221 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 221 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
222 | } | 222 | } |
223 | 223 | ||
224 | static int __init snd_opl3sa2_detect(struct snd_opl3sa2 *chip) | 224 | static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip) |
225 | { | 225 | { |
226 | struct snd_card *card; | 226 | struct snd_card *card; |
227 | unsigned long port; | 227 | unsigned long port; |
@@ -489,7 +489,7 @@ static void snd_opl3sa2_master_free(struct snd_kcontrol *kcontrol) | |||
489 | chip->master_volume = NULL; | 489 | chip->master_volume = NULL; |
490 | } | 490 | } |
491 | 491 | ||
492 | static int __init snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) | 492 | static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip) |
493 | { | 493 | { |
494 | struct snd_card *card = chip->card; | 494 | struct snd_card *card = chip->card; |
495 | struct snd_ctl_elem_id id1, id2; | 495 | struct snd_ctl_elem_id id1, id2; |
@@ -583,8 +583,8 @@ static int snd_opl3sa2_resume(struct snd_card *card) | |||
583 | #endif /* CONFIG_PM */ | 583 | #endif /* CONFIG_PM */ |
584 | 584 | ||
585 | #ifdef CONFIG_PNP | 585 | #ifdef CONFIG_PNP |
586 | static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, | 586 | static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip, |
587 | struct pnp_dev *pdev) | 587 | struct pnp_dev *pdev) |
588 | { | 588 | { |
589 | struct pnp_resource_table * cfg; | 589 | struct pnp_resource_table * cfg; |
590 | int err; | 590 | int err; |
@@ -862,7 +862,7 @@ static struct pnp_card_driver opl3sa2_pnpc_driver = { | |||
862 | }; | 862 | }; |
863 | #endif /* CONFIG_PNP */ | 863 | #endif /* CONFIG_PNP */ |
864 | 864 | ||
865 | static int __init snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) | 865 | static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev) |
866 | { | 866 | { |
867 | struct snd_card *card; | 867 | struct snd_card *card; |
868 | int err; | 868 | int err; |
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index e6bfcf74c1c1..283817f2de75 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
@@ -967,7 +967,7 @@ static void __init snd_miro_proc_init(struct snd_miro * miro) | |||
967 | struct snd_info_entry *entry; | 967 | struct snd_info_entry *entry; |
968 | 968 | ||
969 | if (! snd_card_proc_new(miro->card, "miro", &entry)) | 969 | if (! snd_card_proc_new(miro->card, "miro", &entry)) |
970 | snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read); | 970 | snd_info_set_text_ops(entry, miro, snd_miro_proc_read); |
971 | } | 971 | } |
972 | 972 | ||
973 | /* | 973 | /* |
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index c0b8d61b75e7..658179e86142 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c | |||
@@ -131,7 +131,7 @@ snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode) | |||
131 | 131 | ||
132 | /* | 132 | /* |
133 | */ | 133 | */ |
134 | static void __init | 134 | static void __devinit |
135 | snd_emu8000_read_wait(struct snd_emu8000 *emu) | 135 | snd_emu8000_read_wait(struct snd_emu8000 *emu) |
136 | { | 136 | { |
137 | while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) { | 137 | while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) { |
@@ -143,7 +143,7 @@ snd_emu8000_read_wait(struct snd_emu8000 *emu) | |||
143 | 143 | ||
144 | /* | 144 | /* |
145 | */ | 145 | */ |
146 | static void __init | 146 | static void __devinit |
147 | snd_emu8000_write_wait(struct snd_emu8000 *emu) | 147 | snd_emu8000_write_wait(struct snd_emu8000 *emu) |
148 | { | 148 | { |
149 | while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { | 149 | while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) { |
@@ -156,7 +156,7 @@ snd_emu8000_write_wait(struct snd_emu8000 *emu) | |||
156 | /* | 156 | /* |
157 | * detect a card at the given port | 157 | * detect a card at the given port |
158 | */ | 158 | */ |
159 | static int __init | 159 | static int __devinit |
160 | snd_emu8000_detect(struct snd_emu8000 *emu) | 160 | snd_emu8000_detect(struct snd_emu8000 *emu) |
161 | { | 161 | { |
162 | /* Initialise */ | 162 | /* Initialise */ |
@@ -182,7 +182,7 @@ snd_emu8000_detect(struct snd_emu8000 *emu) | |||
182 | /* | 182 | /* |
183 | * intiailize audio channels | 183 | * intiailize audio channels |
184 | */ | 184 | */ |
185 | static void __init | 185 | static void __devinit |
186 | init_audio(struct snd_emu8000 *emu) | 186 | init_audio(struct snd_emu8000 *emu) |
187 | { | 187 | { |
188 | int ch; | 188 | int ch; |
@@ -223,7 +223,7 @@ init_audio(struct snd_emu8000 *emu) | |||
223 | /* | 223 | /* |
224 | * initialize DMA address | 224 | * initialize DMA address |
225 | */ | 225 | */ |
226 | static void __init | 226 | static void __devinit |
227 | init_dma(struct snd_emu8000 *emu) | 227 | init_dma(struct snd_emu8000 *emu) |
228 | { | 228 | { |
229 | EMU8000_SMALR_WRITE(emu, 0); | 229 | EMU8000_SMALR_WRITE(emu, 0); |
@@ -327,7 +327,7 @@ static unsigned short init4[128] /*__devinitdata*/ = { | |||
327 | * Taken from the oss driver, not obvious from the doc how this | 327 | * Taken from the oss driver, not obvious from the doc how this |
328 | * is meant to work | 328 | * is meant to work |
329 | */ | 329 | */ |
330 | static void __init | 330 | static void __devinit |
331 | send_array(struct snd_emu8000 *emu, unsigned short *data, int size) | 331 | send_array(struct snd_emu8000 *emu, unsigned short *data, int size) |
332 | { | 332 | { |
333 | int i; | 333 | int i; |
@@ -349,7 +349,7 @@ send_array(struct snd_emu8000 *emu, unsigned short *data, int size) | |||
349 | * Send initialization arrays to start up, this just follows the | 349 | * Send initialization arrays to start up, this just follows the |
350 | * initialisation sequence in the adip. | 350 | * initialisation sequence in the adip. |
351 | */ | 351 | */ |
352 | static void __init | 352 | static void __devinit |
353 | init_arrays(struct snd_emu8000 *emu) | 353 | init_arrays(struct snd_emu8000 *emu) |
354 | { | 354 | { |
355 | send_array(emu, init1, ARRAY_SIZE(init1)/4); | 355 | send_array(emu, init1, ARRAY_SIZE(init1)/4); |
@@ -375,7 +375,7 @@ init_arrays(struct snd_emu8000 *emu) | |||
375 | * seems that the only way to do this is to use the one channel and keep | 375 | * seems that the only way to do this is to use the one channel and keep |
376 | * reallocating between read and write. | 376 | * reallocating between read and write. |
377 | */ | 377 | */ |
378 | static void __init | 378 | static void __devinit |
379 | size_dram(struct snd_emu8000 *emu) | 379 | size_dram(struct snd_emu8000 *emu) |
380 | { | 380 | { |
381 | int i, size; | 381 | int i, size; |
@@ -500,7 +500,7 @@ snd_emu8000_init_fm(struct snd_emu8000 *emu) | |||
500 | /* | 500 | /* |
501 | * The main initialization routine. | 501 | * The main initialization routine. |
502 | */ | 502 | */ |
503 | static void __init | 503 | static void __devinit |
504 | snd_emu8000_init_hw(struct snd_emu8000 *emu) | 504 | snd_emu8000_init_hw(struct snd_emu8000 *emu) |
505 | { | 505 | { |
506 | int i; | 506 | int i; |
@@ -1019,7 +1019,7 @@ static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = { | |||
1019 | /* | 1019 | /* |
1020 | * create and attach mixer elements for WaveTable treble/bass controls | 1020 | * create and attach mixer elements for WaveTable treble/bass controls |
1021 | */ | 1021 | */ |
1022 | static int __init | 1022 | static int __devinit |
1023 | snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) | 1023 | snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu) |
1024 | { | 1024 | { |
1025 | int i, err = 0; | 1025 | int i, err = 0; |
@@ -1069,7 +1069,7 @@ static int snd_emu8000_dev_free(struct snd_device *device) | |||
1069 | /* | 1069 | /* |
1070 | * initialize and register emu8000 synth device. | 1070 | * initialize and register emu8000 synth device. |
1071 | */ | 1071 | */ |
1072 | int __init | 1072 | int __devinit |
1073 | snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, | 1073 | snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports, |
1074 | struct snd_seq_device **awe_ret) | 1074 | struct snd_seq_device **awe_ret) |
1075 | { | 1075 | { |
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c index 80b1cf84a1ae..1be16c9700f0 100644 --- a/sound/isa/sb/emu8000_patch.c +++ b/sound/isa/sb/emu8000_patch.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
25 | 25 | ||
26 | static int emu8000_reset_addr = 0; | 26 | static int emu8000_reset_addr; |
27 | module_param(emu8000_reset_addr, int, 0444); | 27 | module_param(emu8000_reset_addr, int, 0444); |
28 | MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)"); | 28 | MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)"); |
29 | 29 | ||
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c index 6333f900eaee..7f7f05fa518a 100644 --- a/sound/isa/sb/sb16.c +++ b/sound/isa/sb/sb16.c | |||
@@ -85,7 +85,7 @@ static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */ | |||
85 | static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */ | 85 | static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 5,6,7 */ |
86 | static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; | 86 | static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; |
87 | #ifdef CONFIG_SND_SB16_CSP | 87 | #ifdef CONFIG_SND_SB16_CSP |
88 | static int csp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 88 | static int csp[SNDRV_CARDS]; |
89 | #endif | 89 | #endif |
90 | #ifdef SNDRV_SBAWE_EMU8000 | 90 | #ifdef SNDRV_SBAWE_EMU8000 |
91 | static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; | 91 | static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; |
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 9703c68e4e08..fcd638090a9e 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c | |||
@@ -1101,7 +1101,7 @@ static int init_proc_entry(struct snd_sb_csp * p, int device) | |||
1101 | struct snd_info_entry *entry; | 1101 | struct snd_info_entry *entry; |
1102 | sprintf(name, "cspD%d", device); | 1102 | sprintf(name, "cspD%d", device); |
1103 | if (! snd_card_proc_new(p->chip->card, name, &entry)) | 1103 | if (! snd_card_proc_new(p->chip->card, name, &entry)) |
1104 | snd_info_set_text_ops(entry, p, 1024, info_read); | 1104 | snd_info_set_text_ops(entry, p, info_read); |
1105 | return 0; | 1105 | return 0; |
1106 | } | 1106 | } |
1107 | 1107 | ||
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c index c549aceea294..0b67edd7ac6e 100644 --- a/sound/isa/sb/sb8_midi.c +++ b/sound/isa/sb/sb8_midi.c | |||
@@ -32,20 +32,22 @@ | |||
32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
33 | #include <sound/sb.h> | 33 | #include <sound/sb.h> |
34 | 34 | ||
35 | /* | ||
36 | |||
37 | */ | ||
38 | 35 | ||
39 | irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip) | 36 | irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip) |
40 | { | 37 | { |
41 | struct snd_rawmidi *rmidi; | 38 | struct snd_rawmidi *rmidi; |
42 | int max = 64; | 39 | int max = 64; |
43 | char byte; | 40 | char byte; |
44 | 41 | ||
45 | if (chip == NULL || (rmidi = chip->rmidi) == NULL) { | 42 | if (!chip) |
43 | return IRQ_NONE; | ||
44 | |||
45 | rmidi = chip->rmidi; | ||
46 | if (!rmidi) { | ||
46 | inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */ | 47 | inb(SBP(chip, DATA_AVAIL)); /* ack interrupt */ |
47 | return IRQ_NONE; | 48 | return IRQ_NONE; |
48 | } | 49 | } |
50 | |||
49 | spin_lock(&chip->midi_input_lock); | 51 | spin_lock(&chip->midi_input_lock); |
50 | while (max-- > 0) { | 52 | while (max-- > 0) { |
51 | if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { | 53 | if (inb(SBP(chip, DATA_AVAIL)) & 0x80) { |
@@ -59,10 +61,6 @@ irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip) | |||
59 | return IRQ_HANDLED; | 61 | return IRQ_HANDLED; |
60 | } | 62 | } |
61 | 63 | ||
62 | /* | ||
63 | |||
64 | */ | ||
65 | |||
66 | static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream) | 64 | static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream) |
67 | { | 65 | { |
68 | unsigned long flags; | 66 | unsigned long flags; |
@@ -252,10 +250,6 @@ static void snd_sb8dsp_midi_output_trigger(struct snd_rawmidi_substream *substre | |||
252 | snd_sb8dsp_midi_output_write(substream); | 250 | snd_sb8dsp_midi_output_write(substream); |
253 | } | 251 | } |
254 | 252 | ||
255 | /* | ||
256 | |||
257 | */ | ||
258 | |||
259 | static struct snd_rawmidi_ops snd_sb8dsp_midi_output = | 253 | static struct snd_rawmidi_ops snd_sb8dsp_midi_output = |
260 | { | 254 | { |
261 | .open = snd_sb8dsp_midi_output_open, | 255 | .open = snd_sb8dsp_midi_output_open, |
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index d2a856f0fde2..27271c9446dc 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -897,10 +897,9 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum, unsigned l | |||
897 | struct snd_rawmidi *rawmidi; | 897 | struct snd_rawmidi *rawmidi; |
898 | int err; | 898 | int err; |
899 | 899 | ||
900 | #define MPU401_SHARE_HARDWARE 1 | ||
901 | if ((err = snd_mpu401_uart_new(card, devnum, | 900 | if ((err = snd_mpu401_uart_new(card, devnum, |
902 | MPU401_HW_MPU401, | 901 | MPU401_HW_MPU401, |
903 | port, MPU401_SHARE_HARDWARE, | 902 | port, MPU401_INFO_INTEGRATED, |
904 | irq, SA_INTERRUPT, | 903 | irq, SA_INTERRUPT, |
905 | &rawmidi)) == 0) { | 904 | &rawmidi)) == 0) { |
906 | struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data; | 905 | struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data; |
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c index 7ae86f82c3fa..9eb27082c659 100644 --- a/sound/isa/wavefront/wavefront.c +++ b/sound/isa/wavefront/wavefront.c | |||
@@ -50,7 +50,7 @@ static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */ | |||
50 | static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ | 50 | static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */ |
51 | static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ | 51 | static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ |
52 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ | 52 | static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */ |
53 | static int use_cs4232_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 53 | static int use_cs4232_midi[SNDRV_CARDS]; |
54 | 54 | ||
55 | module_param_array(index, int, NULL, 0444); | 55 | module_param_array(index, int, NULL, 0444); |
56 | MODULE_PARM_DESC(index, "Index value for WaveFront soundcard."); | 56 | MODULE_PARM_DESC(index, "Index value for WaveFront soundcard."); |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index a2081803a827..d37346b12dc0 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -216,14 +216,19 @@ config SND_CS46XX_NEW_DSP | |||
216 | This works better than the old code, so say Y. | 216 | This works better than the old code, so say Y. |
217 | 217 | ||
218 | config SND_CS5535AUDIO | 218 | config SND_CS5535AUDIO |
219 | tristate "CS5535 Audio" | 219 | tristate "CS5535/CS5536 Audio" |
220 | depends on SND && X86 && !X86_64 | 220 | depends on SND && X86 && !X86_64 |
221 | select SND_PCM | 221 | select SND_PCM |
222 | select SND_AC97_CODEC | 222 | select SND_AC97_CODEC |
223 | help | 223 | help |
224 | Say Y here to include support for audio on CS5535 chips. It is | 224 | Say Y here to include support for audio on CS5535 chips. It is |
225 | referred to as NS CS5535 IO or AMD CS5535 IO companion in | 225 | referred to as NS CS5535 IO or AMD CS5535 IO companion in |
226 | various literature. | 226 | various literature. This driver also supports the CS5536 audio |
227 | device. However, for both chips, on certain boards, you may | ||
228 | need to use ac97_quirk=hp_only if your board has physically | ||
229 | mapped headphone out to master output. If that works for you, | ||
230 | send lspci -vvv output to the mailing list so that your board | ||
231 | can be identified in the quirks list. | ||
227 | 232 | ||
228 | To compile this driver as a module, choose M here: the module | 233 | To compile this driver as a module, choose M here: the module |
229 | will be called snd-cs5535audio. | 234 | will be called snd-cs5535audio. |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index d05200741ac3..0abf2808d59f 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -253,6 +253,8 @@ void snd_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short va | |||
253 | ac97->bus->ops->write(ac97, reg, value); | 253 | ac97->bus->ops->write(ac97, reg, value); |
254 | } | 254 | } |
255 | 255 | ||
256 | EXPORT_SYMBOL(snd_ac97_write); | ||
257 | |||
256 | /** | 258 | /** |
257 | * snd_ac97_read - read a value from the given register | 259 | * snd_ac97_read - read a value from the given register |
258 | * | 260 | * |
@@ -281,6 +283,8 @@ static inline unsigned short snd_ac97_read_cache(struct snd_ac97 *ac97, unsigned | |||
281 | return ac97->regs[reg]; | 283 | return ac97->regs[reg]; |
282 | } | 284 | } |
283 | 285 | ||
286 | EXPORT_SYMBOL(snd_ac97_read); | ||
287 | |||
284 | /** | 288 | /** |
285 | * snd_ac97_write_cache - write a value on the given register and update the cache | 289 | * snd_ac97_write_cache - write a value on the given register and update the cache |
286 | * @ac97: the ac97 instance | 290 | * @ac97: the ac97 instance |
@@ -302,6 +306,8 @@ void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned sh | |||
302 | mutex_unlock(&ac97->reg_mutex); | 306 | mutex_unlock(&ac97->reg_mutex); |
303 | } | 307 | } |
304 | 308 | ||
309 | EXPORT_SYMBOL(snd_ac97_write_cache); | ||
310 | |||
305 | /** | 311 | /** |
306 | * snd_ac97_update - update the value on the given register | 312 | * snd_ac97_update - update the value on the given register |
307 | * @ac97: the ac97 instance | 313 | * @ac97: the ac97 instance |
@@ -331,6 +337,8 @@ int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short va | |||
331 | return change; | 337 | return change; |
332 | } | 338 | } |
333 | 339 | ||
340 | EXPORT_SYMBOL(snd_ac97_update); | ||
341 | |||
334 | /** | 342 | /** |
335 | * snd_ac97_update_bits - update the bits on the given register | 343 | * snd_ac97_update_bits - update the bits on the given register |
336 | * @ac97: the ac97 instance | 344 | * @ac97: the ac97 instance |
@@ -356,6 +364,8 @@ int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned sho | |||
356 | return change; | 364 | return change; |
357 | } | 365 | } |
358 | 366 | ||
367 | EXPORT_SYMBOL(snd_ac97_update_bits); | ||
368 | |||
359 | /* no lock version - see snd_ac97_updat_bits() */ | 369 | /* no lock version - see snd_ac97_updat_bits() */ |
360 | int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, | 370 | int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg, |
361 | unsigned short mask, unsigned short value) | 371 | unsigned short mask, unsigned short value) |
@@ -563,7 +573,7 @@ AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) | |||
563 | }; | 573 | }; |
564 | 574 | ||
565 | static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = | 575 | static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = |
566 | AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0); | 576 | AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0); |
567 | 577 | ||
568 | 578 | ||
569 | static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; | 579 | static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; |
@@ -605,7 +615,7 @@ AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0), | |||
605 | AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), | 615 | AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), |
606 | AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), | 616 | AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), |
607 | AC97_ENUM("Mono Output Select", std_enum[2]), | 617 | AC97_ENUM("Mono Output Select", std_enum[2]), |
608 | AC97_ENUM("Mic Select", std_enum[3]), | 618 | AC97_ENUM("Mic Select Capture Switch", std_enum[3]), |
609 | AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) | 619 | AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) |
610 | }; | 620 | }; |
611 | 621 | ||
@@ -1226,7 +1236,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1226 | ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080; | 1236 | ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080; |
1227 | 1237 | ||
1228 | /* build center controls */ | 1238 | /* build center controls */ |
1229 | if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) { | 1239 | if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) |
1240 | && !(ac97->flags & AC97_AD_MULTI)) { | ||
1230 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0) | 1241 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0) |
1231 | return err; | 1242 | return err; |
1232 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0) | 1243 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0) |
@@ -1238,7 +1249,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1238 | } | 1249 | } |
1239 | 1250 | ||
1240 | /* build LFE controls */ | 1251 | /* build LFE controls */ |
1241 | if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) { | 1252 | if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) |
1253 | && !(ac97->flags & AC97_AD_MULTI)) { | ||
1242 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0) | 1254 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0) |
1243 | return err; | 1255 | return err; |
1244 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0) | 1256 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0) |
@@ -1250,7 +1262,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1250 | } | 1262 | } |
1251 | 1263 | ||
1252 | /* build surround controls */ | 1264 | /* build surround controls */ |
1253 | if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) { | 1265 | if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) |
1266 | && !(ac97->flags & AC97_AD_MULTI)) { | ||
1254 | /* Surround Master (0x38) is with stereo mutes */ | 1267 | /* Surround Master (0x38) is with stereo mutes */ |
1255 | if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) | 1268 | if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) |
1256 | return err; | 1269 | return err; |
@@ -1335,9 +1348,11 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1335 | } | 1348 | } |
1336 | 1349 | ||
1337 | /* build Aux controls */ | 1350 | /* build Aux controls */ |
1338 | if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { | 1351 | if (!(ac97->flags & AC97_HAS_NO_AUX)) { |
1339 | if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) | 1352 | if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { |
1340 | return err; | 1353 | if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) |
1354 | return err; | ||
1355 | } | ||
1341 | } | 1356 | } |
1342 | 1357 | ||
1343 | /* build PCM controls */ | 1358 | /* build PCM controls */ |
@@ -1682,6 +1697,7 @@ const char *snd_ac97_get_short_name(struct snd_ac97 *ac97) | |||
1682 | return "unknown codec"; | 1697 | return "unknown codec"; |
1683 | } | 1698 | } |
1684 | 1699 | ||
1700 | EXPORT_SYMBOL(snd_ac97_get_short_name); | ||
1685 | 1701 | ||
1686 | /* wait for a while until registers are accessible after RESET | 1702 | /* wait for a while until registers are accessible after RESET |
1687 | * return 0 if ok, negative not ready | 1703 | * return 0 if ok, negative not ready |
@@ -1774,6 +1790,8 @@ int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops, | |||
1774 | return 0; | 1790 | return 0; |
1775 | } | 1791 | } |
1776 | 1792 | ||
1793 | EXPORT_SYMBOL(snd_ac97_bus); | ||
1794 | |||
1777 | /* stop no dev release warning */ | 1795 | /* stop no dev release warning */ |
1778 | static void ac97_device_release(struct device * dev) | 1796 | static void ac97_device_release(struct device * dev) |
1779 | { | 1797 | { |
@@ -2117,6 +2135,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
2117 | return 0; | 2135 | return 0; |
2118 | } | 2136 | } |
2119 | 2137 | ||
2138 | EXPORT_SYMBOL(snd_ac97_mixer); | ||
2120 | 2139 | ||
2121 | /* | 2140 | /* |
2122 | * Power down the chip. | 2141 | * Power down the chip. |
@@ -2166,6 +2185,8 @@ void snd_ac97_suspend(struct snd_ac97 *ac97) | |||
2166 | snd_ac97_powerdown(ac97); | 2185 | snd_ac97_powerdown(ac97); |
2167 | } | 2186 | } |
2168 | 2187 | ||
2188 | EXPORT_SYMBOL(snd_ac97_suspend); | ||
2189 | |||
2169 | /* | 2190 | /* |
2170 | * restore ac97 status | 2191 | * restore ac97 status |
2171 | */ | 2192 | */ |
@@ -2267,6 +2288,8 @@ __reset_ready: | |||
2267 | snd_ac97_restore_iec958(ac97); | 2288 | snd_ac97_restore_iec958(ac97); |
2268 | } | 2289 | } |
2269 | } | 2290 | } |
2291 | |||
2292 | EXPORT_SYMBOL(snd_ac97_resume); | ||
2270 | #endif | 2293 | #endif |
2271 | 2294 | ||
2272 | 2295 | ||
@@ -2590,29 +2613,7 @@ int snd_ac97_tune_hardware(struct snd_ac97 *ac97, struct ac97_quirk *quirk, cons | |||
2590 | return 0; | 2613 | return 0; |
2591 | } | 2614 | } |
2592 | 2615 | ||
2593 | |||
2594 | /* | ||
2595 | * Exported symbols | ||
2596 | */ | ||
2597 | |||
2598 | EXPORT_SYMBOL(snd_ac97_write); | ||
2599 | EXPORT_SYMBOL(snd_ac97_read); | ||
2600 | EXPORT_SYMBOL(snd_ac97_write_cache); | ||
2601 | EXPORT_SYMBOL(snd_ac97_update); | ||
2602 | EXPORT_SYMBOL(snd_ac97_update_bits); | ||
2603 | EXPORT_SYMBOL(snd_ac97_get_short_name); | ||
2604 | EXPORT_SYMBOL(snd_ac97_bus); | ||
2605 | EXPORT_SYMBOL(snd_ac97_mixer); | ||
2606 | EXPORT_SYMBOL(snd_ac97_pcm_assign); | ||
2607 | EXPORT_SYMBOL(snd_ac97_pcm_open); | ||
2608 | EXPORT_SYMBOL(snd_ac97_pcm_close); | ||
2609 | EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules); | ||
2610 | EXPORT_SYMBOL(snd_ac97_tune_hardware); | 2616 | EXPORT_SYMBOL(snd_ac97_tune_hardware); |
2611 | EXPORT_SYMBOL(snd_ac97_set_rate); | ||
2612 | #ifdef CONFIG_PM | ||
2613 | EXPORT_SYMBOL(snd_ac97_resume); | ||
2614 | EXPORT_SYMBOL(snd_ac97_suspend); | ||
2615 | #endif | ||
2616 | 2617 | ||
2617 | /* | 2618 | /* |
2618 | * INIT part | 2619 | * INIT part |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 4d9cf37300f7..7f197c780816 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -464,6 +464,10 @@ int patch_wolfson05(struct snd_ac97 * ac97) | |||
464 | { | 464 | { |
465 | /* WM9705, WM9710 */ | 465 | /* WM9705, WM9710 */ |
466 | ac97->build_ops = &patch_wolfson_wm9705_ops; | 466 | ac97->build_ops = &patch_wolfson_wm9705_ops; |
467 | #ifdef CONFIG_TOUCHSCREEN_WM9705 | ||
468 | /* WM9705 touchscreen uses AUX and VIDEO for touch */ | ||
469 | ac97->flags |=3D AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; | ||
470 | #endif | ||
467 | return 0; | 471 | return 0; |
468 | } | 472 | } |
469 | 473 | ||
@@ -1367,6 +1371,13 @@ static void ad18xx_resume(struct snd_ac97 *ac97) | |||
1367 | 1371 | ||
1368 | snd_ac97_restore_iec958(ac97); | 1372 | snd_ac97_restore_iec958(ac97); |
1369 | } | 1373 | } |
1374 | |||
1375 | static void ad1888_resume(struct snd_ac97 *ac97) | ||
1376 | { | ||
1377 | ad18xx_resume(ac97); | ||
1378 | snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080); | ||
1379 | } | ||
1380 | |||
1370 | #endif | 1381 | #endif |
1371 | 1382 | ||
1372 | int patch_ad1819(struct snd_ac97 * ac97) | 1383 | int patch_ad1819(struct snd_ac97 * ac97) |
@@ -1627,6 +1638,7 @@ static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = { | |||
1627 | * (SS vendor << 16 | device) | 1638 | * (SS vendor << 16 | device) |
1628 | */ | 1639 | */ |
1629 | static unsigned int ad1981_jacks_blacklist[] = { | 1640 | static unsigned int ad1981_jacks_blacklist[] = { |
1641 | 0x10140537, /* Thinkpad T41p */ | ||
1630 | 0x10140554, /* Thinkpad T42p/R50p */ | 1642 | 0x10140554, /* Thinkpad T42p/R50p */ |
1631 | 0 /* end */ | 1643 | 0 /* end */ |
1632 | }; | 1644 | }; |
@@ -1839,7 +1851,7 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = { | |||
1839 | .build_post_spdif = patch_ad198x_post_spdif, | 1851 | .build_post_spdif = patch_ad198x_post_spdif, |
1840 | .build_specific = patch_ad1888_specific, | 1852 | .build_specific = patch_ad1888_specific, |
1841 | #ifdef CONFIG_PM | 1853 | #ifdef CONFIG_PM |
1842 | .resume = ad18xx_resume, | 1854 | .resume = ad1888_resume, |
1843 | #endif | 1855 | #endif |
1844 | .update_jacks = ad1888_update_jacks, | 1856 | .update_jacks = ad1888_update_jacks, |
1845 | }; | 1857 | }; |
@@ -2048,7 +2060,10 @@ int patch_alc650(struct snd_ac97 * ac97) | |||
2048 | /* Enable SPDIF-IN only on Rev.E and above */ | 2060 | /* Enable SPDIF-IN only on Rev.E and above */ |
2049 | val = snd_ac97_read(ac97, AC97_ALC650_CLOCK); | 2061 | val = snd_ac97_read(ac97, AC97_ALC650_CLOCK); |
2050 | /* SPDIF IN with pin 47 */ | 2062 | /* SPDIF IN with pin 47 */ |
2051 | if (ac97->spec.dev_flags) | 2063 | if (ac97->spec.dev_flags && |
2064 | /* ASUS A6KM requires EAPD */ | ||
2065 | ! (ac97->subsystem_vendor == 0x1043 && | ||
2066 | ac97->subsystem_device == 0x1103)) | ||
2052 | val |= 0x03; /* enable */ | 2067 | val |= 0x03; /* enable */ |
2053 | else | 2068 | else |
2054 | val &= ~0x03; /* disable */ | 2069 | val &= ~0x03; /* disable */ |
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c index 512a3583b0ce..f684aa2c0067 100644 --- a/sound/pci/ac97/ac97_pcm.c +++ b/sound/pci/ac97/ac97_pcm.c | |||
@@ -317,6 +317,8 @@ int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) | |||
317 | return 0; | 317 | return 0; |
318 | } | 318 | } |
319 | 319 | ||
320 | EXPORT_SYMBOL(snd_ac97_set_rate); | ||
321 | |||
320 | static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots) | 322 | static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots) |
321 | { | 323 | { |
322 | if (!ac97_is_audio(ac97)) | 324 | if (!ac97_is_audio(ac97)) |
@@ -550,6 +552,8 @@ int snd_ac97_pcm_assign(struct snd_ac97_bus *bus, | |||
550 | return 0; | 552 | return 0; |
551 | } | 553 | } |
552 | 554 | ||
555 | EXPORT_SYMBOL(snd_ac97_pcm_assign); | ||
556 | |||
553 | /** | 557 | /** |
554 | * snd_ac97_pcm_open - opens the given AC97 pcm | 558 | * snd_ac97_pcm_open - opens the given AC97 pcm |
555 | * @pcm: the ac97 pcm instance | 559 | * @pcm: the ac97 pcm instance |
@@ -633,6 +637,8 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, | |||
633 | return err; | 637 | return err; |
634 | } | 638 | } |
635 | 639 | ||
640 | EXPORT_SYMBOL(snd_ac97_pcm_open); | ||
641 | |||
636 | /** | 642 | /** |
637 | * snd_ac97_pcm_close - closes the given AC97 pcm | 643 | * snd_ac97_pcm_close - closes the given AC97 pcm |
638 | * @pcm: the ac97 pcm instance | 644 | * @pcm: the ac97 pcm instance |
@@ -658,6 +664,8 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) | |||
658 | return 0; | 664 | return 0; |
659 | } | 665 | } |
660 | 666 | ||
667 | EXPORT_SYMBOL(snd_ac97_pcm_close); | ||
668 | |||
661 | static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params, | 669 | static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params, |
662 | struct snd_pcm_hw_rule *rule) | 670 | struct snd_pcm_hw_rule *rule) |
663 | { | 671 | { |
@@ -709,3 +717,5 @@ int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime) | |||
709 | SNDRV_PCM_HW_PARAM_RATE, -1); | 717 | SNDRV_PCM_HW_PARAM_RATE, -1); |
710 | return err; | 718 | return err; |
711 | } | 719 | } |
720 | |||
721 | EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules); | ||
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c index 4d523df79cc7..2118df50b9d6 100644 --- a/sound/pci/ac97/ac97_proc.c +++ b/sound/pci/ac97/ac97_proc.c | |||
@@ -433,7 +433,7 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97) | |||
433 | prefix = ac97_is_audio(ac97) ? "ac97" : "mc97"; | 433 | prefix = ac97_is_audio(ac97) ? "ac97" : "mc97"; |
434 | sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num); | 434 | sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num); |
435 | if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { | 435 | if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { |
436 | snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_read); | 436 | snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read); |
437 | if (snd_info_register(entry) < 0) { | 437 | if (snd_info_register(entry) < 0) { |
438 | snd_info_free_entry(entry); | 438 | snd_info_free_entry(entry); |
439 | entry = NULL; | 439 | entry = NULL; |
@@ -442,10 +442,9 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97) | |||
442 | ac97->proc = entry; | 442 | ac97->proc = entry; |
443 | sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num); | 443 | sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num); |
444 | if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { | 444 | if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) { |
445 | snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_regs_read); | 445 | snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read); |
446 | #ifdef CONFIG_SND_DEBUG | 446 | #ifdef CONFIG_SND_DEBUG |
447 | entry->mode |= S_IWUSR; | 447 | entry->mode |= S_IWUSR; |
448 | entry->c.text.write_size = 1024; | ||
449 | entry->c.text.write = snd_ac97_proc_regs_write; | 448 | entry->c.text.write = snd_ac97_proc_regs_write; |
450 | #endif | 449 | #endif |
451 | if (snd_info_register(entry) < 0) { | 450 | if (snd_info_register(entry) < 0) { |
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c index 0fb7b3407312..94c26ec05882 100644 --- a/sound/pci/ac97/ak4531_codec.c +++ b/sound/pci/ac97/ak4531_codec.c | |||
@@ -453,7 +453,7 @@ static void snd_ak4531_proc_init(struct snd_card *card, struct snd_ak4531 *ak453 | |||
453 | struct snd_info_entry *entry; | 453 | struct snd_info_entry *entry; |
454 | 454 | ||
455 | if (! snd_card_proc_new(card, "ak4531", &entry)) | 455 | if (! snd_card_proc_new(card, "ak4531", &entry)) |
456 | snd_info_set_text_ops(entry, ak4531, 1024, snd_ak4531_proc_read); | 456 | snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read); |
457 | } | 457 | } |
458 | #endif | 458 | #endif |
459 | 459 | ||
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c index eece1c7e55a0..d42bf4570367 100644 --- a/sound/pci/ad1889.c +++ b/sound/pci/ad1889.c | |||
@@ -753,7 +753,7 @@ snd_ad1889_proc_init(struct snd_ad1889 *chip) | |||
753 | struct snd_info_entry *entry; | 753 | struct snd_info_entry *entry; |
754 | 754 | ||
755 | if (!snd_card_proc_new(chip->card, chip->card->driver, &entry)) | 755 | if (!snd_card_proc_new(chip->card, chip->card->driver, &entry)) |
756 | snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read); | 756 | snd_info_set_text_ops(entry, chip, snd_ad1889_proc_read); |
757 | } | 757 | } |
758 | 758 | ||
759 | static struct ac97_quirk ac97_quirks[] = { | 759 | static struct ac97_quirk ac97_quirks[] = { |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index e2dbc2118902..5dfdbf6657f2 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -49,7 +49,7 @@ MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}"); | |||
49 | static int index = SNDRV_DEFAULT_IDX1; /* Index */ | 49 | static int index = SNDRV_DEFAULT_IDX1; /* Index */ |
50 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ | 50 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ |
51 | static int pcm_channels = 32; | 51 | static int pcm_channels = 32; |
52 | static int spdif = 0; | 52 | static int spdif; |
53 | 53 | ||
54 | module_param(index, int, 0444); | 54 | module_param(index, int, 0444); |
55 | MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio."); | 55 | MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio."); |
@@ -2173,7 +2173,7 @@ static void __devinit snd_ali_proc_init(struct snd_ali *codec) | |||
2173 | { | 2173 | { |
2174 | struct snd_info_entry *entry; | 2174 | struct snd_info_entry *entry; |
2175 | if(!snd_card_proc_new(codec->card, "ali5451", &entry)) | 2175 | if(!snd_card_proc_new(codec->card, "ali5451", &entry)) |
2176 | snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read); | 2176 | snd_info_set_text_ops(entry, codec, snd_ali_proc_read); |
2177 | } | 2177 | } |
2178 | 2178 | ||
2179 | static int __devinit snd_ali_resources(struct snd_ali *codec) | 2179 | static int __devinit snd_ali_resources(struct snd_ali *codec) |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 60423b1c678b..a9f08066459a 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
@@ -746,8 +746,8 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci, | |||
746 | card->shortname, chip->alt_port, chip->irq); | 746 | card->shortname, chip->alt_port, chip->irq); |
747 | 747 | ||
748 | if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, | 748 | if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000, |
749 | gcr+0x30, 1, pci->irq, 0, | 749 | gcr+0x30, MPU401_INFO_INTEGRATED, |
750 | &chip->rmidi)) < 0) { | 750 | pci->irq, 0, &chip->rmidi)) < 0) { |
751 | printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30); | 751 | printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30); |
752 | goto out_err; | 752 | goto out_err; |
753 | } | 753 | } |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index d0f759d86d3d..f18a8c0e4688 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -1504,7 +1504,7 @@ static void __devinit snd_atiixp_proc_init(struct atiixp *chip) | |||
1504 | struct snd_info_entry *entry; | 1504 | struct snd_info_entry *entry; |
1505 | 1505 | ||
1506 | if (! snd_card_proc_new(chip->card, "atiixp", &entry)) | 1506 | if (! snd_card_proc_new(chip->card, "atiixp", &entry)) |
1507 | snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read); | 1507 | snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); |
1508 | } | 1508 | } |
1509 | #else /* !CONFIG_PROC_FS */ | 1509 | #else /* !CONFIG_PROC_FS */ |
1510 | #define snd_atiixp_proc_init(chip) | 1510 | #define snd_atiixp_proc_init(chip) |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 12a34c39caa7..40739057076b 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -1177,7 +1177,7 @@ static void __devinit snd_atiixp_proc_init(struct atiixp_modem *chip) | |||
1177 | struct snd_info_entry *entry; | 1177 | struct snd_info_entry *entry; |
1178 | 1178 | ||
1179 | if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) | 1179 | if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry)) |
1180 | snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read); | 1180 | snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read); |
1181 | } | 1181 | } |
1182 | #else | 1182 | #else |
1183 | #define snd_atiixp_proc_init(chip) | 1183 | #define snd_atiixp_proc_init(chip) |
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c index 126870ec063a..8a3b118989bf 100644 --- a/sound/pci/au88x0/au88x0.c +++ b/sound/pci/au88x0/au88x0.c | |||
@@ -261,6 +261,13 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
261 | return err; | 261 | return err; |
262 | } | 262 | } |
263 | snd_vortex_workaround(pci, pcifix[dev]); | 263 | snd_vortex_workaround(pci, pcifix[dev]); |
264 | |||
265 | // Card details needed in snd_vortex_midi | ||
266 | strcpy(card->driver, CARD_NAME_SHORT); | ||
267 | sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT); | ||
268 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
269 | card->shortname, chip->io, chip->irq); | ||
270 | |||
264 | // (4) Alloc components. | 271 | // (4) Alloc components. |
265 | // ADB pcm. | 272 | // ADB pcm. |
266 | if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) { | 273 | if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) { |
@@ -323,11 +330,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
323 | #endif | 330 | #endif |
324 | 331 | ||
325 | // (5) | 332 | // (5) |
326 | strcpy(card->driver, CARD_NAME_SHORT); | ||
327 | strcpy(card->shortname, CARD_NAME_SHORT); | ||
328 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
329 | card->shortname, chip->io, chip->irq); | ||
330 | |||
331 | if ((err = pci_read_config_word(pci, PCI_DEVICE_ID, | 333 | if ((err = pci_read_config_word(pci, PCI_DEVICE_ID, |
332 | &(chip->device))) < 0) { | 334 | &(chip->device))) < 0) { |
333 | snd_card_free(card); | 335 | snd_card_free(card); |
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c index 873f486b07b8..c75d368ea087 100644 --- a/sound/pci/au88x0/au88x0_mpu401.c +++ b/sound/pci/au88x0/au88x0_mpu401.c | |||
@@ -47,7 +47,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) | |||
47 | struct snd_rawmidi *rmidi; | 47 | struct snd_rawmidi *rmidi; |
48 | int temp, mode; | 48 | int temp, mode; |
49 | struct snd_mpu401 *mpu; | 49 | struct snd_mpu401 *mpu; |
50 | int port; | 50 | unsigned long port; |
51 | 51 | ||
52 | #ifdef VORTEX_MPU401_LEGACY | 52 | #ifdef VORTEX_MPU401_LEGACY |
53 | /* EnableHardCodedMPU401Port() */ | 53 | /* EnableHardCodedMPU401Port() */ |
@@ -70,9 +70,6 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) | |||
70 | temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4; | 70 | temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4; |
71 | hwwrite(vortex->mmio, VORTEX_CTRL2, temp); | 71 | hwwrite(vortex->mmio, VORTEX_CTRL2, temp); |
72 | hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET); | 72 | hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET); |
73 | /* Set some kind of mode */ | ||
74 | if (mode) | ||
75 | hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_ENTER_UART); | ||
76 | 73 | ||
77 | /* Check if anything is OK. */ | 74 | /* Check if anything is OK. */ |
78 | temp = hwread(vortex->mmio, VORTEX_MIDI_DATA); | 75 | temp = hwread(vortex->mmio, VORTEX_MIDI_DATA); |
@@ -98,7 +95,8 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) | |||
98 | port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); | 95 | port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA); |
99 | if ((temp = | 96 | if ((temp = |
100 | snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, | 97 | snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port, |
101 | 1, 0, 0, &rmidi)) != 0) { | 98 | MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO, |
99 | 0, 0, &rmidi)) != 0) { | ||
102 | hwwrite(vortex->mmio, VORTEX_CTRL, | 100 | hwwrite(vortex->mmio, VORTEX_CTRL, |
103 | (hwread(vortex->mmio, VORTEX_CTRL) & | 101 | (hwread(vortex->mmio, VORTEX_CTRL) & |
104 | ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); | 102 | ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN); |
@@ -107,6 +105,9 @@ static int __devinit snd_vortex_midi(vortex_t * vortex) | |||
107 | mpu = rmidi->private_data; | 105 | mpu = rmidi->private_data; |
108 | mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD); | 106 | mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD); |
109 | #endif | 107 | #endif |
108 | /* Overwrite MIDI name */ | ||
109 | snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number); | ||
110 | |||
110 | vortex->rmidi = rmidi; | 111 | vortex->rmidi = rmidi; |
111 | return 0; | 112 | return 0; |
112 | } | 113 | } |
diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c index 4534e1882ada..b4151e208b71 100644 --- a/sound/pci/au88x0/au88x0_xtalk.c +++ b/sound/pci/au88x0/au88x0_xtalk.c | |||
@@ -66,31 +66,20 @@ static xtalk_gains_t const asXtalkGainsAllChan = { | |||
66 | 0 | 66 | 0 |
67 | //0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff | 67 | //0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff |
68 | }; | 68 | }; |
69 | static xtalk_gains_t const asXtalkGainsZeros = { | 69 | static xtalk_gains_t const asXtalkGainsZeros; |
70 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
71 | }; | ||
72 | 70 | ||
73 | static xtalk_dline_t const alXtalkDlineZeros = { | 71 | static xtalk_dline_t const alXtalkDlineZeros; |
74 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
75 | 0, 0, 0, | ||
76 | 0, 0, 0, 0, 0, 0, 0 | ||
77 | }; | ||
78 | static xtalk_dline_t const alXtalkDlineTest = { | 72 | static xtalk_dline_t const alXtalkDlineTest = { |
79 | 0xFC18, 0x03E8FFFF, 0x186A0, 0x7960FFFE, 1, 0xFFFFFFFF, | 73 | 0xFC18, 0x03E8FFFF, 0x186A0, 0x7960FFFE, 1, 0xFFFFFFFF, |
80 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 74 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
81 | 0, 0, 0, 0 | 75 | 0, 0, 0, 0 |
82 | }; | 76 | }; |
83 | 77 | ||
84 | static xtalk_instate_t const asXtalkInStateZeros = { 0, 0, 0, 0 }; | 78 | static xtalk_instate_t const asXtalkInStateZeros; |
85 | static xtalk_instate_t const asXtalkInStateTest = | 79 | static xtalk_instate_t const asXtalkInStateTest = |
86 | { 0xFF80, 0x0080, 0xFFFF, 0x0001 }; | 80 | { 0xFF80, 0x0080, 0xFFFF, 0x0001 }; |
87 | static xtalk_state_t const asXtalkOutStateZeros = { | 81 | static xtalk_state_t const asXtalkOutStateZeros; |
88 | {0, 0, 0, 0}, | 82 | |
89 | {0, 0, 0, 0}, | ||
90 | {0, 0, 0, 0}, | ||
91 | {0, 0, 0, 0}, | ||
92 | {0, 0, 0, 0} | ||
93 | }; | ||
94 | static short const sDiamondKLeftEq = 0x401d; | 83 | static short const sDiamondKLeftEq = 0x401d; |
95 | static short const sDiamondKRightEq = 0x401d; | 84 | static short const sDiamondKRightEq = 0x401d; |
96 | static short const sDiamondKLeftXt = 0xF90E; | 85 | static short const sDiamondKLeftXt = 0xF90E; |
@@ -162,13 +151,7 @@ static xtalk_coefs_t const asXtalkNarrowCoefsRightXt = { | |||
162 | {0, 0, 0, 0, 0} | 151 | {0, 0, 0, 0, 0} |
163 | }; | 152 | }; |
164 | 153 | ||
165 | static xtalk_coefs_t const asXtalkCoefsZeros = { | 154 | static xtalk_coefs_t const asXtalkCoefsZeros; |
166 | {0, 0, 0, 0, 0}, | ||
167 | {0, 0, 0, 0, 0}, | ||
168 | {0, 0, 0, 0, 0}, | ||
169 | {0, 0, 0, 0, 0}, | ||
170 | {0, 0, 0, 0, 0} | ||
171 | }; | ||
172 | static xtalk_coefs_t const asXtalkCoefsPipe = { | 155 | static xtalk_coefs_t const asXtalkCoefsPipe = { |
173 | {0, 0, 0x0FA0, 0, 0}, | 156 | {0, 0, 0x0FA0, 0, 0}, |
174 | {0, 0, 0x0FA0, 0, 0}, | 157 | {0, 0, 0x0FA0, 0, 0}, |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 52a364524262..6e62dafb66cd 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -33,14 +33,21 @@ | |||
33 | * in the first place >:-P}), | 33 | * in the first place >:-P}), |
34 | * I was forced to base this driver on reverse engineering | 34 | * I was forced to base this driver on reverse engineering |
35 | * (3 weeks' worth of evenings filled with driver work). | 35 | * (3 weeks' worth of evenings filled with driver work). |
36 | * (and no, I did NOT go the easy way: to pick up a PCI128 for 9 Euros) | 36 | * (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros) |
37 | * | 37 | * |
38 | * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name | 38 | * The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name |
39 | * for compatibility reasons) has the following features: | 39 | * for compatibility reasons) has the following features: |
40 | * | 40 | * |
41 | * - builtin AC97 conformant codec (SNR over 80dB) | 41 | * - builtin AC97 conformant codec (SNR over 80dB) |
42 | * (really AC97 compliant?? I really doubt it when looking | 42 | * Note that "conformant" != "compliant"!! this chip's mixer register layout |
43 | * at the mixer register layout) | 43 | * *differs* from the standard AC97 layout: |
44 | * they chose to not implement the headphone register (which is not a | ||
45 | * problem since it's merely optional), yet when doing this, they committed | ||
46 | * the grave sin of letting other registers follow immediately instead of | ||
47 | * keeping a headphone dummy register, thereby shifting the mixer register | ||
48 | * addresses illegally. So far unfortunately it looks like the very flexible | ||
49 | * ALSA AC97 support is still not enough to easily compensate for such a | ||
50 | * grave layout violation despite all tweaks and quirks mechanisms it offers. | ||
44 | * - builtin genuine OPL3 | 51 | * - builtin genuine OPL3 |
45 | * - full duplex 16bit playback/record at independent sampling rate | 52 | * - full duplex 16bit playback/record at independent sampling rate |
46 | * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr?? | 53 | * - MPU401 (+ legacy address support) FIXME: how to enable legacy addr?? |
@@ -90,10 +97,15 @@ | |||
90 | * | 97 | * |
91 | * TODO | 98 | * TODO |
92 | * - test MPU401 MIDI playback etc. | 99 | * - test MPU401 MIDI playback etc. |
93 | * - power management. See e.g. intel8x0 or cs4281. | 100 | * - add some power micro-management (disable various units of the card |
94 | * This would be nice since the chip runs a bit hot, and it's *required* | 101 | * as long as they're unused). However this requires I/O ports which I |
95 | * anyway for proper ACPI power management. | 102 | * haven't figured out yet and which thus might not even exist... |
103 | * The standard suspend/resume functionality could probably make use of | ||
104 | * some improvement, too... | ||
96 | * - figure out what all unknown port bits are responsible for | 105 | * - figure out what all unknown port bits are responsible for |
106 | * - figure out some cleverly evil scheme to possibly make ALSA AC97 code | ||
107 | * fully accept our quite incompatible ""AC97"" mixer and thus save some | ||
108 | * code (but I'm not too optimistic that doing this is possible at all) | ||
97 | */ | 109 | */ |
98 | 110 | ||
99 | #include <sound/driver.h> | 111 | #include <sound/driver.h> |
@@ -214,6 +226,16 @@ struct snd_azf3328 { | |||
214 | 226 | ||
215 | struct pci_dev *pci; | 227 | struct pci_dev *pci; |
216 | int irq; | 228 | int irq; |
229 | |||
230 | #ifdef CONFIG_PM | ||
231 | /* register value containers for power management | ||
232 | * Note: not always full I/O range preserved (just like Win driver!) */ | ||
233 | u16 saved_regs_codec [AZF_IO_SIZE_CODEC_PM / 2]; | ||
234 | u16 saved_regs_io2 [AZF_IO_SIZE_IO2_PM / 2]; | ||
235 | u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2]; | ||
236 | u16 saved_regs_synth[AZF_IO_SIZE_SYNTH_PM / 2]; | ||
237 | u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2]; | ||
238 | #endif | ||
217 | }; | 239 | }; |
218 | 240 | ||
219 | static const struct pci_device_id snd_azf3328_ids[] __devinitdata = { | 241 | static const struct pci_device_id snd_azf3328_ids[] __devinitdata = { |
@@ -317,10 +339,8 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg | |||
317 | else | 339 | else |
318 | dst_vol_left &= ~0x80; | 340 | dst_vol_left &= ~0x80; |
319 | 341 | ||
320 | do | 342 | do { |
321 | { | 343 | if (!left_done) { |
322 | if (!left_done) | ||
323 | { | ||
324 | if (curr_vol_left > dst_vol_left) | 344 | if (curr_vol_left > dst_vol_left) |
325 | curr_vol_left--; | 345 | curr_vol_left--; |
326 | else | 346 | else |
@@ -330,8 +350,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg | |||
330 | left_done = 1; | 350 | left_done = 1; |
331 | outb(curr_vol_left, portbase + 1); | 351 | outb(curr_vol_left, portbase + 1); |
332 | } | 352 | } |
333 | if (!right_done) | 353 | if (!right_done) { |
334 | { | ||
335 | if (curr_vol_right > dst_vol_right) | 354 | if (curr_vol_right > dst_vol_right) |
336 | curr_vol_right--; | 355 | curr_vol_right--; |
337 | else | 356 | else |
@@ -346,8 +365,7 @@ snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, int reg | |||
346 | } | 365 | } |
347 | if (delay) | 366 | if (delay) |
348 | mdelay(delay); | 367 | mdelay(delay); |
349 | } | 368 | } while ((!left_done) || (!right_done)); |
350 | while ((!left_done) || (!right_done)); | ||
351 | snd_azf3328_dbgcallleave(); | 369 | snd_azf3328_dbgcallleave(); |
352 | } | 370 | } |
353 | 371 | ||
@@ -514,15 +532,18 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, | |||
514 | struct snd_ctl_elem_info *uinfo) | 532 | struct snd_ctl_elem_info *uinfo) |
515 | { | 533 | { |
516 | static const char * const texts1[] = { | 534 | static const char * const texts1[] = { |
517 | "ModemOut1", "ModemOut2" | 535 | "Mic1", "Mic2" |
518 | }; | 536 | }; |
519 | static const char * const texts2[] = { | 537 | static const char * const texts2[] = { |
520 | "MonoSelectSource1", "MonoSelectSource2" | 538 | "Mix", "Mic" |
521 | }; | 539 | }; |
522 | static const char * const texts3[] = { | 540 | static const char * const texts3[] = { |
523 | "Mic", "CD", "Video", "Aux", | 541 | "Mic", "CD", "Video", "Aux", |
524 | "Line", "Mix", "Mix Mono", "Phone" | 542 | "Line", "Mix", "Mix Mono", "Phone" |
525 | }; | 543 | }; |
544 | static const char * const texts4[] = { | ||
545 | "pre 3D", "post 3D" | ||
546 | }; | ||
526 | struct azf3328_mixer_reg reg; | 547 | struct azf3328_mixer_reg reg; |
527 | 548 | ||
528 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); | 549 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); |
@@ -531,14 +552,19 @@ snd_azf3328_info_mixer_enum(struct snd_kcontrol *kcontrol, | |||
531 | uinfo->value.enumerated.items = reg.enum_c; | 552 | uinfo->value.enumerated.items = reg.enum_c; |
532 | if (uinfo->value.enumerated.item > reg.enum_c - 1U) | 553 | if (uinfo->value.enumerated.item > reg.enum_c - 1U) |
533 | uinfo->value.enumerated.item = reg.enum_c - 1U; | 554 | uinfo->value.enumerated.item = reg.enum_c - 1U; |
534 | if (reg.reg == IDX_MIXER_ADVCTL2) | 555 | if (reg.reg == IDX_MIXER_ADVCTL2) { |
535 | { | 556 | switch(reg.lchan_shift) { |
536 | if (reg.lchan_shift == 8) /* modem out sel */ | 557 | case 8: /* modem out sel */ |
537 | strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]); | 558 | strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]); |
538 | else /* mono sel source */ | 559 | break; |
560 | case 9: /* mono sel source */ | ||
539 | strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]); | 561 | strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]); |
540 | } | 562 | break; |
541 | else | 563 | case 15: /* PCM Out Path */ |
564 | strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]); | ||
565 | break; | ||
566 | } | ||
567 | } else | ||
542 | strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item] | 568 | strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item] |
543 | ); | 569 | ); |
544 | return 0; | 570 | return 0; |
@@ -554,12 +580,10 @@ snd_azf3328_get_mixer_enum(struct snd_kcontrol *kcontrol, | |||
554 | 580 | ||
555 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); | 581 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); |
556 | val = snd_azf3328_mixer_inw(chip, reg.reg); | 582 | val = snd_azf3328_mixer_inw(chip, reg.reg); |
557 | if (reg.reg == IDX_MIXER_REC_SELECT) | 583 | if (reg.reg == IDX_MIXER_REC_SELECT) { |
558 | { | ||
559 | ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); | 584 | ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1); |
560 | ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1); | 585 | ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1); |
561 | } | 586 | } else |
562 | else | ||
563 | ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); | 587 | ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1); |
564 | 588 | ||
565 | snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", | 589 | snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n", |
@@ -579,16 +603,13 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol, | |||
579 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); | 603 | snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); |
580 | oreg = snd_azf3328_mixer_inw(chip, reg.reg); | 604 | oreg = snd_azf3328_mixer_inw(chip, reg.reg); |
581 | val = oreg; | 605 | val = oreg; |
582 | if (reg.reg == IDX_MIXER_REC_SELECT) | 606 | if (reg.reg == IDX_MIXER_REC_SELECT) { |
583 | { | ||
584 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U || | 607 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U || |
585 | ucontrol->value.enumerated.item[1] > reg.enum_c - 1U) | 608 | ucontrol->value.enumerated.item[1] > reg.enum_c - 1U) |
586 | return -EINVAL; | 609 | return -EINVAL; |
587 | val = (ucontrol->value.enumerated.item[0] << 8) | | 610 | val = (ucontrol->value.enumerated.item[0] << 8) | |
588 | (ucontrol->value.enumerated.item[1] << 0); | 611 | (ucontrol->value.enumerated.item[1] << 0); |
589 | } | 612 | } else { |
590 | else | ||
591 | { | ||
592 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U) | 613 | if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U) |
593 | return -EINVAL; | 614 | return -EINVAL; |
594 | val &= ~((reg.enum_c - 1) << reg.lchan_shift); | 615 | val &= ~((reg.enum_c - 1) << reg.lchan_shift); |
@@ -629,13 +650,14 @@ static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] __devinitdata | |||
629 | AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1), | 650 | AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1), |
630 | AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1), | 651 | AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1), |
631 | AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1), | 652 | AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1), |
632 | AZF3328_MIXER_ENUM("Modem Out Select", IDX_MIXER_ADVCTL2, 2, 8), | 653 | AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8), |
633 | AZF3328_MIXER_ENUM("Mono Select Source", IDX_MIXER_ADVCTL2, 2, 9), | 654 | AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9), |
655 | AZF3328_MIXER_ENUM("PCM", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */ | ||
634 | AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), | 656 | AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0), |
635 | AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), | 657 | AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0), |
636 | AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), | 658 | AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0), |
637 | AZF3328_MIXER_VOL_SPECIAL("3D Control - Wide", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ | 659 | AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */ |
638 | AZF3328_MIXER_VOL_SPECIAL("3D Control - Space", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ | 660 | AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */ |
639 | #if MIXER_TESTING | 661 | #if MIXER_TESTING |
640 | AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0), | 662 | AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0), |
641 | AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0), | 663 | AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0), |
@@ -813,22 +835,18 @@ snd_azf3328_setdmaa(struct snd_azf3328 *chip, | |||
813 | unsigned int is_running; | 835 | unsigned int is_running; |
814 | 836 | ||
815 | snd_azf3328_dbgcallenter(); | 837 | snd_azf3328_dbgcallenter(); |
816 | if (do_recording) | 838 | if (do_recording) { |
817 | { | ||
818 | /* access capture registers, i.e. skip playback reg section */ | 839 | /* access capture registers, i.e. skip playback reg section */ |
819 | portbase = chip->codec_port + 0x20; | 840 | portbase = chip->codec_port + 0x20; |
820 | is_running = chip->is_recording; | 841 | is_running = chip->is_recording; |
821 | } | 842 | } else { |
822 | else | ||
823 | { | ||
824 | /* access the playback register section */ | 843 | /* access the playback register section */ |
825 | portbase = chip->codec_port + 0x00; | 844 | portbase = chip->codec_port + 0x00; |
826 | is_running = chip->is_playing; | 845 | is_running = chip->is_playing; |
827 | } | 846 | } |
828 | 847 | ||
829 | /* AZF3328 uses a two buffer pointer DMA playback approach */ | 848 | /* AZF3328 uses a two buffer pointer DMA playback approach */ |
830 | if (!is_running) | 849 | if (!is_running) { |
831 | { | ||
832 | unsigned long addr_area2; | 850 | unsigned long addr_area2; |
833 | unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ | 851 | unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */ |
834 | count_areas = size/2; | 852 | count_areas = size/2; |
@@ -961,6 +979,13 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
961 | chip->is_playing = 1; | 979 | chip->is_playing = 1; |
962 | snd_azf3328_dbgplay("STARTED PLAYBACK\n"); | 980 | snd_azf3328_dbgplay("STARTED PLAYBACK\n"); |
963 | break; | 981 | break; |
982 | case SNDRV_PCM_TRIGGER_RESUME: | ||
983 | snd_azf3328_dbgplay("RESUME PLAYBACK\n"); | ||
984 | /* resume playback if we were active */ | ||
985 | if (chip->is_playing) | ||
986 | snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, | ||
987 | snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME); | ||
988 | break; | ||
964 | case SNDRV_PCM_TRIGGER_STOP: | 989 | case SNDRV_PCM_TRIGGER_STOP: |
965 | snd_azf3328_dbgplay("STOP PLAYBACK\n"); | 990 | snd_azf3328_dbgplay("STOP PLAYBACK\n"); |
966 | 991 | ||
@@ -988,6 +1013,12 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
988 | chip->is_playing = 0; | 1013 | chip->is_playing = 0; |
989 | snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); | 1014 | snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); |
990 | break; | 1015 | break; |
1016 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1017 | snd_azf3328_dbgplay("SUSPEND PLAYBACK\n"); | ||
1018 | /* make sure playback is stopped */ | ||
1019 | snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, | ||
1020 | snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME); | ||
1021 | break; | ||
991 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 1022 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
992 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); | 1023 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); |
993 | break; | 1024 | break; |
@@ -995,6 +1026,7 @@ snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
995 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); | 1026 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); |
996 | break; | 1027 | break; |
997 | default: | 1028 | default: |
1029 | printk(KERN_ERR "FIXME: unknown trigger mode!\n"); | ||
998 | return -EINVAL; | 1030 | return -EINVAL; |
999 | } | 1031 | } |
1000 | 1032 | ||
@@ -1068,6 +1100,13 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1068 | chip->is_recording = 1; | 1100 | chip->is_recording = 1; |
1069 | snd_azf3328_dbgplay("STARTED CAPTURE\n"); | 1101 | snd_azf3328_dbgplay("STARTED CAPTURE\n"); |
1070 | break; | 1102 | break; |
1103 | case SNDRV_PCM_TRIGGER_RESUME: | ||
1104 | snd_azf3328_dbgplay("RESUME CAPTURE\n"); | ||
1105 | /* resume recording if we were active */ | ||
1106 | if (chip->is_recording) | ||
1107 | snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, | ||
1108 | snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME); | ||
1109 | break; | ||
1071 | case SNDRV_PCM_TRIGGER_STOP: | 1110 | case SNDRV_PCM_TRIGGER_STOP: |
1072 | snd_azf3328_dbgplay("STOP CAPTURE\n"); | 1111 | snd_azf3328_dbgplay("STOP CAPTURE\n"); |
1073 | 1112 | ||
@@ -1088,6 +1127,12 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1088 | chip->is_recording = 0; | 1127 | chip->is_recording = 0; |
1089 | snd_azf3328_dbgplay("STOPPED CAPTURE\n"); | 1128 | snd_azf3328_dbgplay("STOPPED CAPTURE\n"); |
1090 | break; | 1129 | break; |
1130 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
1131 | snd_azf3328_dbgplay("SUSPEND CAPTURE\n"); | ||
1132 | /* make sure recording is stopped */ | ||
1133 | snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, | ||
1134 | snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME); | ||
1135 | break; | ||
1091 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 1136 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
1092 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); | 1137 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); |
1093 | break; | 1138 | break; |
@@ -1095,6 +1140,7 @@ snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1095 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); | 1140 | snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); |
1096 | break; | 1141 | break; |
1097 | default: | 1142 | default: |
1143 | printk(KERN_ERR "FIXME: unknown trigger mode!\n"); | ||
1098 | return -EINVAL; | 1144 | return -EINVAL; |
1099 | } | 1145 | } |
1100 | 1146 | ||
@@ -1163,8 +1209,7 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1163 | snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), | 1209 | snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), |
1164 | status); | 1210 | status); |
1165 | 1211 | ||
1166 | if (status & IRQ_TIMER) | 1212 | if (status & IRQ_TIMER) { |
1167 | { | ||
1168 | /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ | 1213 | /* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */ |
1169 | if (chip->timer) | 1214 | if (chip->timer) |
1170 | snd_timer_interrupt(chip->timer, chip->timer->sticks); | 1215 | snd_timer_interrupt(chip->timer, chip->timer->sticks); |
@@ -1174,50 +1219,43 @@ snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
1174 | spin_unlock(&chip->reg_lock); | 1219 | spin_unlock(&chip->reg_lock); |
1175 | snd_azf3328_dbgplay("azt3328: timer IRQ\n"); | 1220 | snd_azf3328_dbgplay("azt3328: timer IRQ\n"); |
1176 | } | 1221 | } |
1177 | if (status & IRQ_PLAYBACK) | 1222 | if (status & IRQ_PLAYBACK) { |
1178 | { | ||
1179 | spin_lock(&chip->reg_lock); | 1223 | spin_lock(&chip->reg_lock); |
1180 | which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); | 1224 | which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); |
1181 | /* ack all IRQ types immediately */ | 1225 | /* ack all IRQ types immediately */ |
1182 | snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); | 1226 | snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); |
1183 | spin_unlock(&chip->reg_lock); | 1227 | spin_unlock(&chip->reg_lock); |
1184 | 1228 | ||
1185 | if (chip->pcm && chip->playback_substream) | 1229 | if (chip->pcm && chip->playback_substream) { |
1186 | { | ||
1187 | snd_pcm_period_elapsed(chip->playback_substream); | 1230 | snd_pcm_period_elapsed(chip->playback_substream); |
1188 | snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", | 1231 | snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", |
1189 | which, | 1232 | which, |
1190 | inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); | 1233 | inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); |
1191 | } | 1234 | } else |
1192 | else | ||
1193 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); | 1235 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); |
1194 | if (which & IRQ_PLAY_SOMETHING) | 1236 | if (which & IRQ_PLAY_SOMETHING) |
1195 | snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); | 1237 | snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); |
1196 | } | 1238 | } |
1197 | if (status & IRQ_RECORDING) | 1239 | if (status & IRQ_RECORDING) { |
1198 | { | ||
1199 | spin_lock(&chip->reg_lock); | 1240 | spin_lock(&chip->reg_lock); |
1200 | which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); | 1241 | which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); |
1201 | /* ack all IRQ types immediately */ | 1242 | /* ack all IRQ types immediately */ |
1202 | snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); | 1243 | snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); |
1203 | spin_unlock(&chip->reg_lock); | 1244 | spin_unlock(&chip->reg_lock); |
1204 | 1245 | ||
1205 | if (chip->pcm && chip->capture_substream) | 1246 | if (chip->pcm && chip->capture_substream) { |
1206 | { | ||
1207 | snd_pcm_period_elapsed(chip->capture_substream); | 1247 | snd_pcm_period_elapsed(chip->capture_substream); |
1208 | snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", | 1248 | snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", |
1209 | which, | 1249 | which, |
1210 | inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); | 1250 | inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); |
1211 | } | 1251 | } else |
1212 | else | ||
1213 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); | 1252 | snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); |
1214 | if (which & IRQ_REC_SOMETHING) | 1253 | if (which & IRQ_REC_SOMETHING) |
1215 | snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); | 1254 | snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); |
1216 | } | 1255 | } |
1217 | /* MPU401 has less critical IRQ requirements | 1256 | /* MPU401 has less critical IRQ requirements |
1218 | * than timer and playback/recording, right? */ | 1257 | * than timer and playback/recording, right? */ |
1219 | if (status & IRQ_MPU401) | 1258 | if (status & IRQ_MPU401) { |
1220 | { | ||
1221 | snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); | 1259 | snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); |
1222 | 1260 | ||
1223 | /* hmm, do we have to ack the IRQ here somehow? | 1261 | /* hmm, do we have to ack the IRQ here somehow? |
@@ -1511,8 +1549,7 @@ snd_azf3328_timer_start(struct snd_timer *timer) | |||
1511 | snd_azf3328_dbgcallenter(); | 1549 | snd_azf3328_dbgcallenter(); |
1512 | chip = snd_timer_chip(timer); | 1550 | chip = snd_timer_chip(timer); |
1513 | delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; | 1551 | delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK; |
1514 | if (delay < 49) | 1552 | if (delay < 49) { |
1515 | { | ||
1516 | /* uhoh, that's not good, since user-space won't know about | 1553 | /* uhoh, that's not good, since user-space won't know about |
1517 | * this timing tweak | 1554 | * this timing tweak |
1518 | * (we need to do it to avoid a lockup, though) */ | 1555 | * (we need to do it to avoid a lockup, though) */ |
@@ -1766,9 +1803,11 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
1766 | goto out_err; | 1803 | goto out_err; |
1767 | } | 1804 | } |
1768 | 1805 | ||
1806 | card->private_data = chip; | ||
1807 | |||
1769 | if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, | 1808 | if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401, |
1770 | chip->mpu_port, 1, pci->irq, 0, | 1809 | chip->mpu_port, MPU401_INFO_INTEGRATED, |
1771 | &chip->rmidi)) < 0) { | 1810 | pci->irq, 0, &chip->rmidi)) < 0) { |
1772 | snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); | 1811 | snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port); |
1773 | goto out_err; | 1812 | goto out_err; |
1774 | } | 1813 | } |
@@ -1791,6 +1830,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
1791 | } | 1830 | } |
1792 | } | 1831 | } |
1793 | 1832 | ||
1833 | opl3->private_data = chip; | ||
1834 | |||
1794 | sprintf(card->longname, "%s at 0x%lx, irq %i", | 1835 | sprintf(card->longname, "%s at 0x%lx, irq %i", |
1795 | card->shortname, chip->codec_port, chip->irq); | 1836 | card->shortname, chip->codec_port, chip->irq); |
1796 | 1837 | ||
@@ -1834,11 +1875,80 @@ snd_azf3328_remove(struct pci_dev *pci) | |||
1834 | snd_azf3328_dbgcallleave(); | 1875 | snd_azf3328_dbgcallleave(); |
1835 | } | 1876 | } |
1836 | 1877 | ||
1878 | #ifdef CONFIG_PM | ||
1879 | static int | ||
1880 | snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | ||
1881 | { | ||
1882 | struct snd_card *card = pci_get_drvdata(pci); | ||
1883 | struct snd_azf3328 *chip = card->private_data; | ||
1884 | int reg; | ||
1885 | |||
1886 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
1887 | |||
1888 | snd_pcm_suspend_all(chip->pcm); | ||
1889 | |||
1890 | for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++) | ||
1891 | chip->saved_regs_mixer[reg] = inw(chip->mixer_port + reg * 2); | ||
1892 | |||
1893 | /* make sure to disable master volume etc. to prevent looping sound */ | ||
1894 | snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); | ||
1895 | snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); | ||
1896 | |||
1897 | for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++) | ||
1898 | chip->saved_regs_codec[reg] = inw(chip->codec_port + reg * 2); | ||
1899 | for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++) | ||
1900 | chip->saved_regs_io2[reg] = inw(chip->io2_port + reg * 2); | ||
1901 | for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++) | ||
1902 | chip->saved_regs_mpu[reg] = inw(chip->mpu_port + reg * 2); | ||
1903 | for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++) | ||
1904 | chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2); | ||
1905 | |||
1906 | pci_set_power_state(pci, PCI_D3hot); | ||
1907 | pci_disable_device(pci); | ||
1908 | pci_save_state(pci); | ||
1909 | return 0; | ||
1910 | } | ||
1911 | |||
1912 | static int | ||
1913 | snd_azf3328_resume(struct pci_dev *pci) | ||
1914 | { | ||
1915 | struct snd_card *card = pci_get_drvdata(pci); | ||
1916 | struct snd_azf3328 *chip = card->private_data; | ||
1917 | int reg; | ||
1918 | |||
1919 | pci_restore_state(pci); | ||
1920 | pci_enable_device(pci); | ||
1921 | pci_set_power_state(pci, PCI_D0); | ||
1922 | pci_set_master(pci); | ||
1923 | |||
1924 | for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++) | ||
1925 | outw(chip->saved_regs_io2[reg], chip->io2_port + reg * 2); | ||
1926 | for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++) | ||
1927 | outw(chip->saved_regs_mpu[reg], chip->mpu_port + reg * 2); | ||
1928 | for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++) | ||
1929 | outw(chip->saved_regs_synth[reg], chip->synth_port + reg * 2); | ||
1930 | for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++) | ||
1931 | outw(chip->saved_regs_mixer[reg], chip->mixer_port + reg * 2); | ||
1932 | for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++) | ||
1933 | outw(chip->saved_regs_codec[reg], chip->codec_port + reg * 2); | ||
1934 | |||
1935 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
1936 | return 0; | ||
1937 | } | ||
1938 | #endif | ||
1939 | |||
1940 | |||
1941 | |||
1942 | |||
1837 | static struct pci_driver driver = { | 1943 | static struct pci_driver driver = { |
1838 | .name = "AZF3328", | 1944 | .name = "AZF3328", |
1839 | .id_table = snd_azf3328_ids, | 1945 | .id_table = snd_azf3328_ids, |
1840 | .probe = snd_azf3328_probe, | 1946 | .probe = snd_azf3328_probe, |
1841 | .remove = __devexit_p(snd_azf3328_remove), | 1947 | .remove = __devexit_p(snd_azf3328_remove), |
1948 | #ifdef CONFIG_PM | ||
1949 | .suspend = snd_azf3328_suspend, | ||
1950 | .resume = snd_azf3328_resume, | ||
1951 | #endif | ||
1842 | }; | 1952 | }; |
1843 | 1953 | ||
1844 | static int __init | 1954 | static int __init |
diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h index f489bdaf6d40..b4f3e3cd006b 100644 --- a/sound/pci/azt3328.h +++ b/sound/pci/azt3328.h | |||
@@ -5,6 +5,9 @@ | |||
5 | 5 | ||
6 | /*** main I/O area port indices ***/ | 6 | /*** main I/O area port indices ***/ |
7 | /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ | 7 | /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ |
8 | #define AZF_IO_SIZE_CODEC 0x80 | ||
9 | #define AZF_IO_SIZE_CODEC_PM 0x70 | ||
10 | |||
8 | /* the driver initialisation suggests a layout of 4 main areas: | 11 | /* the driver initialisation suggests a layout of 4 main areas: |
9 | * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). | 12 | * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). |
10 | * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, | 13 | * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, |
@@ -87,7 +90,7 @@ | |||
87 | #define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ | 90 | #define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ |
88 | #define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ | 91 | #define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ |
89 | 92 | ||
90 | /** hmm, what is this I/O area for? MPU401?? (after playback, recording, ???, timer) **/ | 93 | /** hmm, what is this I/O area for? MPU401?? or external DAC via I2S?? (after playback, recording, ???, timer) **/ |
91 | #define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ | 94 | #define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ |
92 | /* general */ | 95 | /* general */ |
93 | #define IDX_IO_42H 0x42 /* PU:0x0001 */ | 96 | #define IDX_IO_42H 0x42 /* PU:0x0001 */ |
@@ -107,7 +110,8 @@ | |||
107 | #define IRQ_UNKNOWN2 0x0080 /* probably unused */ | 110 | #define IRQ_UNKNOWN2 0x0080 /* probably unused */ |
108 | #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ | 111 | #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ |
109 | #define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */ | 112 | #define IDX_IO_SOME_VALUE 0x68 /* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */ |
110 | #define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback!!! maybe power management?? */ | 113 | #define IDX_IO_6AH 0x6A /* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */ |
114 | #define IO_6A_PAUSE_PLAYBACK 0x0200 /* bit 9; sure, this pauses playback, but what the heck is this really about?? */ | ||
111 | #define IDX_IO_6CH 0x6C | 115 | #define IDX_IO_6CH 0x6C |
112 | #define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */ | 116 | #define IDX_IO_6EH 0x6E /* writing 0xffff returns 0x83fe */ |
113 | /* further I/O indices not saved/restored, so probably not used */ | 117 | /* further I/O indices not saved/restored, so probably not used */ |
@@ -115,15 +119,25 @@ | |||
115 | 119 | ||
116 | /*** I/O 2 area port indices ***/ | 120 | /*** I/O 2 area port indices ***/ |
117 | /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ | 121 | /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ |
122 | #define AZF_IO_SIZE_IO2 0x08 | ||
123 | #define AZF_IO_SIZE_IO2_PM 0x06 | ||
124 | |||
118 | #define IDX_IO2_LEGACY_ADDR 0x04 | 125 | #define IDX_IO2_LEGACY_ADDR 0x04 |
119 | #define LEGACY_SOMETHING 0x01 /* OPL3?? */ | 126 | #define LEGACY_SOMETHING 0x01 /* OPL3?? */ |
120 | #define LEGACY_JOY 0x08 | 127 | #define LEGACY_JOY 0x08 |
121 | 128 | ||
129 | #define AZF_IO_SIZE_MPU 0x04 | ||
130 | #define AZF_IO_SIZE_MPU_PM 0x04 | ||
131 | |||
132 | #define AZF_IO_SIZE_SYNTH 0x08 | ||
133 | #define AZF_IO_SIZE_SYNTH_PM 0x06 | ||
122 | 134 | ||
123 | /*** mixer I/O area port indices ***/ | 135 | /*** mixer I/O area port indices ***/ |
124 | /* (only 0x22 of 0x40 bytes saved/restored by Windows driver) | 136 | /* (only 0x22 of 0x40 bytes saved/restored by Windows driver) |
125 | * generally spoken: AC97 register index = AZF3328 mixer reg index + 2 | 137 | * UNFORTUNATELY azf3328 is NOT truly AC97 compliant: see main file intro */ |
126 | * (in other words: AZF3328 NOT fully AC97 compliant) */ | 138 | #define AZF_IO_SIZE_MIXER 0x40 |
139 | #define AZF_IO_SIZE_MIXER_PM 0x22 | ||
140 | |||
127 | #define MIXER_VOLUME_RIGHT_MASK 0x001f | 141 | #define MIXER_VOLUME_RIGHT_MASK 0x001f |
128 | #define MIXER_VOLUME_LEFT_MASK 0x1f00 | 142 | #define MIXER_VOLUME_LEFT_MASK 0x1f00 |
129 | #define MIXER_MUTE_MASK 0x8000 | 143 | #define MIXER_MUTE_MASK 0x8000 |
@@ -156,14 +170,14 @@ | |||
156 | #define IDX_MIXER_ADVCTL1 0x1e | 170 | #define IDX_MIXER_ADVCTL1 0x1e |
157 | /* unlisted bits are unmodifiable */ | 171 | /* unlisted bits are unmodifiable */ |
158 | #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e | 172 | #define MIXER_ADVCTL1_3DWIDTH_MASK 0x000e |
159 | #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 | 173 | #define MIXER_ADVCTL1_HIFI3D_MASK 0x0300 /* yup, this is missing the high bit that official AC97 contains, plus it doesn't have linear bit value range behaviour but instead acts weirdly (possibly we're dealing with two *different* 3D settings here??) */ |
160 | #define IDX_MIXER_ADVCTL2 0x20 /* resembles AC97_GENERAL_PURPOSE reg! */ | 174 | #define IDX_MIXER_ADVCTL2 0x20 /* subset of AC97_GENERAL_PURPOSE reg! */ |
161 | /* unlisted bits are unmodifiable */ | 175 | /* unlisted bits are unmodifiable */ |
162 | #define MIXER_ADVCTL2_BIT7 0x0080 /* WaveOut 3D Bypass? mutes WaveOut at LineOut */ | 176 | #define MIXER_ADVCTL2_LPBK 0x0080 /* Loopback mode -- Win driver: "WaveOut3DBypass"? mutes WaveOut at LineOut */ |
163 | #define MIXER_ADVCTL2_BIT8 0x0100 /* is this Modem Out Select? */ | 177 | #define MIXER_ADVCTL2_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 -- Win driver: "ModemOutSelect"?? */ |
164 | #define MIXER_ADVCTL2_BIT9 0x0200 /* Mono Select Source? */ | 178 | #define MIXER_ADVCTL2_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic; Win driver: "MonoSelectSource"?? */ |
165 | #define MIXER_ADVCTL2_BIT13 0x2000 /* 3D enable? */ | 179 | #define MIXER_ADVCTL2_3D 0x2000 /* 3D Enhancement 1=on */ |
166 | #define MIXER_ADVCTL2_BIT15 0x8000 /* unknown */ | 180 | #define MIXER_ADVCTL2_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */ |
167 | 181 | ||
168 | #define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */ | 182 | #define IDX_MIXER_SOMETHING30H 0x30 /* used, but unknown??? */ |
169 | 183 | ||
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 9ee07d4aac1e..c33642d8d9a1 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c | |||
@@ -44,7 +44,7 @@ MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878}," | |||
44 | static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ | 44 | static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */ |
45 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 45 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
46 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 46 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
47 | static int digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */ | 47 | static int digital_rate[SNDRV_CARDS]; /* digital input rate */ |
48 | static int load_all; /* allow to load the non-whitelisted cards */ | 48 | static int load_all; /* allow to load the non-whitelisted cards */ |
49 | 49 | ||
50 | module_param_array(index, int, NULL, 0444); | 50 | module_param_array(index, int, NULL, 0444); |
@@ -781,10 +781,12 @@ static struct pci_device_id snd_bt87x_ids[] __devinitdata = { | |||
781 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), | 781 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), |
782 | /* Viewcast Osprey 200 */ | 782 | /* Viewcast Osprey 200 */ |
783 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), | 783 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), |
784 | /* AVerMedia Studio No. 103, 203, ...? */ | ||
785 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), | ||
786 | /* Leadtek Winfast tv 2000xp delux */ | 784 | /* Leadtek Winfast tv 2000xp delux */ |
787 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), | 785 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000), |
786 | /* Voodoo TV 200 */ | ||
787 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000), | ||
788 | /* AVerMedia Studio No. 103, 203, ...? */ | ||
789 | BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000), | ||
788 | { } | 790 | { } |
789 | }; | 791 | }; |
790 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); | 792 | MODULE_DEVICE_TABLE(pci, snd_bt87x_ids); |
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index c8131ea92ed6..9cb66c59f523 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -537,9 +537,9 @@ | |||
537 | #endif | 537 | #endif |
538 | 538 | ||
539 | #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux | 539 | #define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux |
540 | #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) | ||
540 | #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux | 541 | #define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux |
541 | #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux | 542 | #define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux |
542 | #define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used) | ||
543 | #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux | 543 | #define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux |
544 | 544 | ||
545 | #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ | 545 | #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */ |
@@ -604,6 +604,8 @@ struct snd_ca0106 { | |||
604 | u32 spdif_bits[4]; /* s/pdif out setup */ | 604 | u32 spdif_bits[4]; /* s/pdif out setup */ |
605 | int spdif_enable; | 605 | int spdif_enable; |
606 | int capture_source; | 606 | int capture_source; |
607 | int i2c_capture_source; | ||
608 | u8 i2c_capture_volume[4][2]; | ||
607 | int capture_mic_line_in; | 609 | int capture_mic_line_in; |
608 | 610 | ||
609 | struct snd_dma_buffer buffer; | 611 | struct snd_dma_buffer buffer; |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index fd8bfebfbd54..59bf9bd02534 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -186,8 +186,8 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
186 | /* New Audigy SE. Has a different DAC. */ | 186 | /* New Audigy SE. Has a different DAC. */ |
187 | /* SB0570: | 187 | /* SB0570: |
188 | * CTRL:CA0106-DAT | 188 | * CTRL:CA0106-DAT |
189 | * ADC: WM8768GEDS | 189 | * ADC: WM8775EDS |
190 | * DAC: WM8775EDS | 190 | * DAC: WM8768GEDS |
191 | */ | 191 | */ |
192 | { .serial = 0x100a1102, | 192 | { .serial = 0x100a1102, |
193 | .name = "Audigy SE [SB0570]", | 193 | .name = "Audigy SE [SB0570]", |
@@ -195,9 +195,14 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
195 | .i2c_adc = 1, | 195 | .i2c_adc = 1, |
196 | .spi_dac = 1 } , | 196 | .spi_dac = 1 } , |
197 | /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ | 197 | /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ |
198 | /* SB0438 | ||
199 | * CTRL:CA0106-DAT | ||
200 | * ADC: WM8775SEDS | ||
201 | * DAC: CS4382-KQZ | ||
202 | */ | ||
198 | { .serial = 0x10091462, | 203 | { .serial = 0x10091462, |
199 | .name = "MSI K8N Diamond MB [SB0438]", | 204 | .name = "MSI K8N Diamond MB [SB0438]", |
200 | .gpio_type = 1, | 205 | .gpio_type = 2, |
201 | .i2c_adc = 1 } , | 206 | .i2c_adc = 1 } , |
202 | /* Shuttle XPC SD31P which has an onboard Creative Labs | 207 | /* Shuttle XPC SD31P which has an onboard Creative Labs |
203 | * Sound Blaster Live! 24-bit EAX | 208 | * Sound Blaster Live! 24-bit EAX |
@@ -326,6 +331,7 @@ int snd_ca0106_spi_write(struct snd_ca0106 * emu, | |||
326 | return 0; | 331 | return 0; |
327 | } | 332 | } |
328 | 333 | ||
334 | /* The ADC does not support i2c read, so only write is implemented */ | ||
329 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, | 335 | int snd_ca0106_i2c_write(struct snd_ca0106 *emu, |
330 | u32 reg, | 336 | u32 reg, |
331 | u32 value) | 337 | u32 value) |
@@ -340,6 +346,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, | |||
340 | } | 346 | } |
341 | 347 | ||
342 | tmp = reg << 25 | value << 16; | 348 | tmp = reg << 25 | value << 16; |
349 | // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value); | ||
343 | /* Not sure what this I2C channel controls. */ | 350 | /* Not sure what this I2C channel controls. */ |
344 | /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ | 351 | /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */ |
345 | 352 | ||
@@ -348,8 +355,9 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, | |||
348 | 355 | ||
349 | for (retry = 0; retry < 10; retry++) { | 356 | for (retry = 0; retry < 10; retry++) { |
350 | /* Send the data to i2c */ | 357 | /* Send the data to i2c */ |
351 | tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); | 358 | //tmp = snd_ca0106_ptr_read(emu, I2C_A, 0); |
352 | tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); | 359 | //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK); |
360 | tmp = 0; | ||
353 | tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); | 361 | tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD); |
354 | snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); | 362 | snd_ca0106_ptr_write(emu, I2C_A, 0, tmp); |
355 | 363 | ||
@@ -1181,7 +1189,7 @@ static unsigned int spi_dac_init[] = { | |||
1181 | 0x02ff, | 1189 | 0x02ff, |
1182 | 0x0400, | 1190 | 0x0400, |
1183 | 0x0520, | 1191 | 0x0520, |
1184 | 0x0600, | 1192 | 0x0620, /* Set 24 bit. Was 0x0600 */ |
1185 | 0x08ff, | 1193 | 0x08ff, |
1186 | 0x0aff, | 1194 | 0x0aff, |
1187 | 0x0cff, | 1195 | 0x0cff, |
@@ -1200,6 +1208,22 @@ static unsigned int spi_dac_init[] = { | |||
1200 | 0x1400, | 1208 | 0x1400, |
1201 | }; | 1209 | }; |
1202 | 1210 | ||
1211 | static unsigned int i2c_adc_init[][2] = { | ||
1212 | { 0x17, 0x00 }, /* Reset */ | ||
1213 | { 0x07, 0x00 }, /* Timeout */ | ||
1214 | { 0x0b, 0x22 }, /* Interface control */ | ||
1215 | { 0x0c, 0x22 }, /* Master mode control */ | ||
1216 | { 0x0d, 0x08 }, /* Powerdown control */ | ||
1217 | { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */ | ||
1218 | { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */ | ||
1219 | { 0x10, 0x7b }, /* ALC Control 1 */ | ||
1220 | { 0x11, 0x00 }, /* ALC Control 2 */ | ||
1221 | { 0x12, 0x32 }, /* ALC Control 3 */ | ||
1222 | { 0x13, 0x00 }, /* Noise gate control */ | ||
1223 | { 0x14, 0xa6 }, /* Limiter control */ | ||
1224 | { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */ | ||
1225 | }; | ||
1226 | |||
1203 | static int __devinit snd_ca0106_create(struct snd_card *card, | 1227 | static int __devinit snd_ca0106_create(struct snd_card *card, |
1204 | struct pci_dev *pci, | 1228 | struct pci_dev *pci, |
1205 | struct snd_ca0106 **rchip) | 1229 | struct snd_ca0106 **rchip) |
@@ -1361,7 +1385,12 @@ static int __devinit snd_ca0106_create(struct snd_card *card, | |||
1361 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ | 1385 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ |
1362 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ | 1386 | chip->capture_source = 3; /* Set CAPTURE_SOURCE */ |
1363 | 1387 | ||
1364 | if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ | 1388 | if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */ |
1389 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ | ||
1390 | outl(0x0, chip->port+GPIO); | ||
1391 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ | ||
1392 | outl(0x005f5301, chip->port+GPIO); /* Analog */ | ||
1393 | } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ | ||
1365 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ | 1394 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ |
1366 | outl(0x0, chip->port+GPIO); | 1395 | outl(0x0, chip->port+GPIO); |
1367 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ | 1396 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ |
@@ -1379,7 +1408,19 @@ static int __devinit snd_ca0106_create(struct snd_card *card, | |||
1379 | outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ | 1408 | outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ |
1380 | 1409 | ||
1381 | if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ | 1410 | if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ |
1382 | snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ | 1411 | int size, n; |
1412 | |||
1413 | size = ARRAY_SIZE(i2c_adc_init); | ||
1414 | //snd_printk("I2C:array size=0x%x\n", size); | ||
1415 | for (n=0; n < size; n++) { | ||
1416 | snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); | ||
1417 | } | ||
1418 | for (n=0; n < 4; n++) { | ||
1419 | chip->i2c_capture_volume[n][0]= 0xcf; | ||
1420 | chip->i2c_capture_volume[n][1]= 0xcf; | ||
1421 | } | ||
1422 | chip->i2c_capture_source=2; /* Line in */ | ||
1423 | //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ | ||
1383 | } | 1424 | } |
1384 | if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ | 1425 | if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ |
1385 | int size, n; | 1426 | int size, n; |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 06fe055674fb..146eed70dce6 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -171,6 +171,76 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, | |||
171 | return change; | 171 | return change; |
172 | } | 172 | } |
173 | 173 | ||
174 | static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol, | ||
175 | struct snd_ctl_elem_info *uinfo) | ||
176 | { | ||
177 | static char *texts[6] = { | ||
178 | "Phone", "Mic", "Line in", "Aux" | ||
179 | }; | ||
180 | |||
181 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
182 | uinfo->count = 1; | ||
183 | uinfo->value.enumerated.items = 4; | ||
184 | if (uinfo->value.enumerated.item > 3) | ||
185 | uinfo->value.enumerated.item = 3; | ||
186 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol, | ||
191 | struct snd_ctl_elem_value *ucontrol) | ||
192 | { | ||
193 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
194 | |||
195 | ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, | ||
200 | struct snd_ctl_elem_value *ucontrol) | ||
201 | { | ||
202 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
203 | unsigned int source_id; | ||
204 | unsigned int ngain, ogain; | ||
205 | int change = 0; | ||
206 | u32 source; | ||
207 | /* If the capture source has changed, | ||
208 | * update the capture volume from the cached value | ||
209 | * for the particular source. | ||
210 | */ | ||
211 | source_id = ucontrol->value.enumerated.item[0] ; | ||
212 | change = (emu->i2c_capture_source != source_id); | ||
213 | if (change) { | ||
214 | snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ | ||
215 | ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ | ||
216 | ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ | ||
217 | if (ngain != ogain) | ||
218 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); | ||
219 | ngain = emu->i2c_capture_volume[source_id][1]; /* Left */ | ||
220 | ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */ | ||
221 | if (ngain != ogain) | ||
222 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); | ||
223 | source = 1 << source_id; | ||
224 | snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ | ||
225 | emu->i2c_capture_source = source_id; | ||
226 | } | ||
227 | return change; | ||
228 | } | ||
229 | |||
230 | static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol, | ||
231 | struct snd_ctl_elem_info *uinfo) | ||
232 | { | ||
233 | static char *texts[2] = { "Side out", "Line in" }; | ||
234 | |||
235 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
236 | uinfo->count = 1; | ||
237 | uinfo->value.enumerated.items = 2; | ||
238 | if (uinfo->value.enumerated.item > 1) | ||
239 | uinfo->value.enumerated.item = 1; | ||
240 | strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); | ||
241 | return 0; | ||
242 | } | ||
243 | |||
174 | static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, | 244 | static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol, |
175 | struct snd_ctl_elem_info *uinfo) | 245 | struct snd_ctl_elem_info *uinfo) |
176 | { | 246 | { |
@@ -207,16 +277,16 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, | |||
207 | if (change) { | 277 | if (change) { |
208 | emu->capture_mic_line_in = val; | 278 | emu->capture_mic_line_in = val; |
209 | if (val) { | 279 | if (val) { |
210 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ | 280 | //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ |
211 | tmp = inl(emu->port+GPIO) & ~0x400; | 281 | tmp = inl(emu->port+GPIO) & ~0x400; |
212 | tmp = tmp | 0x400; | 282 | tmp = tmp | 0x400; |
213 | outl(tmp, emu->port+GPIO); | 283 | outl(tmp, emu->port+GPIO); |
214 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); | 284 | //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); |
215 | } else { | 285 | } else { |
216 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */ | 286 | //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ |
217 | tmp = inl(emu->port+GPIO) & ~0x400; | 287 | tmp = inl(emu->port+GPIO) & ~0x400; |
218 | outl(tmp, emu->port+GPIO); | 288 | outl(tmp, emu->port+GPIO); |
219 | snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); | 289 | //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); |
220 | } | 290 | } |
221 | } | 291 | } |
222 | return change; | 292 | return change; |
@@ -225,12 +295,22 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, | |||
225 | static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = | 295 | static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata = |
226 | { | 296 | { |
227 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 297 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
228 | .name = "Mic/Line in Capture", | 298 | .name = "Shared Mic/Line in Capture Switch", |
229 | .info = snd_ca0106_capture_mic_line_in_info, | 299 | .info = snd_ca0106_capture_mic_line_in_info, |
230 | .get = snd_ca0106_capture_mic_line_in_get, | 300 | .get = snd_ca0106_capture_mic_line_in_get, |
231 | .put = snd_ca0106_capture_mic_line_in_put | 301 | .put = snd_ca0106_capture_mic_line_in_put |
232 | }; | 302 | }; |
233 | 303 | ||
304 | static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata = | ||
305 | { | ||
306 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
307 | .name = "Shared Line in/Side out Capture Switch", | ||
308 | .info = snd_ca0106_capture_line_in_side_out_info, | ||
309 | .get = snd_ca0106_capture_mic_line_in_get, | ||
310 | .put = snd_ca0106_capture_mic_line_in_put | ||
311 | }; | ||
312 | |||
313 | |||
234 | static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, | 314 | static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, |
235 | struct snd_ctl_elem_info *uinfo) | 315 | struct snd_ctl_elem_info *uinfo) |
236 | { | 316 | { |
@@ -329,15 +409,81 @@ static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol, | |||
329 | return 1; | 409 | return 1; |
330 | } | 410 | } |
331 | 411 | ||
412 | static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol, | ||
413 | struct snd_ctl_elem_info *uinfo) | ||
414 | { | ||
415 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
416 | uinfo->count = 2; | ||
417 | uinfo->value.integer.min = 0; | ||
418 | uinfo->value.integer.max = 255; | ||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol, | ||
423 | struct snd_ctl_elem_value *ucontrol) | ||
424 | { | ||
425 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
426 | int source_id; | ||
427 | |||
428 | source_id = kcontrol->private_value; | ||
429 | |||
430 | ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; | ||
431 | ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, | ||
436 | struct snd_ctl_elem_value *ucontrol) | ||
437 | { | ||
438 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
439 | unsigned int ogain; | ||
440 | unsigned int ngain; | ||
441 | int source_id; | ||
442 | int change = 0; | ||
443 | |||
444 | source_id = kcontrol->private_value; | ||
445 | ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ | ||
446 | ngain = ucontrol->value.integer.value[0]; | ||
447 | if (ngain > 0xff) | ||
448 | return 0; | ||
449 | if (ogain != ngain) { | ||
450 | if (emu->i2c_capture_source == source_id) | ||
451 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); | ||
452 | emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; | ||
453 | change = 1; | ||
454 | } | ||
455 | ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ | ||
456 | ngain = ucontrol->value.integer.value[1]; | ||
457 | if (ngain > 0xff) | ||
458 | return 0; | ||
459 | if (ogain != ngain) { | ||
460 | if (emu->i2c_capture_source == source_id) | ||
461 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); | ||
462 | emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; | ||
463 | change = 1; | ||
464 | } | ||
465 | |||
466 | return change; | ||
467 | } | ||
468 | |||
332 | #define CA_VOLUME(xname,chid,reg) \ | 469 | #define CA_VOLUME(xname,chid,reg) \ |
333 | { \ | 470 | { \ |
334 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 471 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
335 | .info = snd_ca0106_volume_info, \ | 472 | .info = snd_ca0106_volume_info, \ |
336 | .get = snd_ca0106_volume_get, \ | 473 | .get = snd_ca0106_volume_get, \ |
337 | .put = snd_ca0106_volume_put, \ | 474 | .put = snd_ca0106_volume_put, \ |
338 | .private_value = ((chid) << 8) | (reg) \ | 475 | .private_value = ((chid) << 8) | (reg) \ |
339 | } | 476 | } |
340 | 477 | ||
478 | #define I2C_VOLUME(xname,chid) \ | ||
479 | { \ | ||
480 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
481 | .info = snd_ca0106_i2c_volume_info, \ | ||
482 | .get = snd_ca0106_i2c_volume_get, \ | ||
483 | .put = snd_ca0106_i2c_volume_put, \ | ||
484 | .private_value = chid \ | ||
485 | } | ||
486 | |||
341 | 487 | ||
342 | static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { | 488 | static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { |
343 | CA_VOLUME("Analog Front Playback Volume", | 489 | CA_VOLUME("Analog Front Playback Volume", |
@@ -361,6 +507,11 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { | |||
361 | CA_VOLUME("CAPTURE feedback Playback Volume", | 507 | CA_VOLUME("CAPTURE feedback Playback Volume", |
362 | 1, CAPTURE_CONTROL), | 508 | 1, CAPTURE_CONTROL), |
363 | 509 | ||
510 | I2C_VOLUME("Phone Capture Volume", 0), | ||
511 | I2C_VOLUME("Mic Capture Volume", 1), | ||
512 | I2C_VOLUME("Line in Capture Volume", 2), | ||
513 | I2C_VOLUME("Aux Capture Volume", 3), | ||
514 | |||
364 | { | 515 | { |
365 | .access = SNDRV_CTL_ELEM_ACCESS_READ, | 516 | .access = SNDRV_CTL_ELEM_ACCESS_READ, |
366 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 517 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
@@ -378,12 +529,19 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { | |||
378 | }, | 529 | }, |
379 | { | 530 | { |
380 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 531 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
381 | .name = "Capture Source", | 532 | .name = "Digital Capture Source", |
382 | .info = snd_ca0106_capture_source_info, | 533 | .info = snd_ca0106_capture_source_info, |
383 | .get = snd_ca0106_capture_source_get, | 534 | .get = snd_ca0106_capture_source_get, |
384 | .put = snd_ca0106_capture_source_put | 535 | .put = snd_ca0106_capture_source_put |
385 | }, | 536 | }, |
386 | { | 537 | { |
538 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
539 | .name = "Capture Source", | ||
540 | .info = snd_ca0106_i2c_capture_source_info, | ||
541 | .get = snd_ca0106_i2c_capture_source_get, | ||
542 | .put = snd_ca0106_i2c_capture_source_put | ||
543 | }, | ||
544 | { | ||
387 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | 545 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, |
388 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 546 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), |
389 | .count = 4, | 547 | .count = 4, |
@@ -477,7 +635,10 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
477 | return err; | 635 | return err; |
478 | } | 636 | } |
479 | if (emu->details->i2c_adc == 1) { | 637 | if (emu->details->i2c_adc == 1) { |
480 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); | 638 | if (emu->details->gpio_type == 1) |
639 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); | ||
640 | else /* gpio_type == 2 */ | ||
641 | err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu)); | ||
481 | if (err < 0) | 642 | if (err < 0) |
482 | return err; | 643 | return err; |
483 | } | 644 | } |
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c index 63757273bfb7..75ca421eb3a1 100644 --- a/sound/pci/ca0106/ca0106_proc.c +++ b/sound/pci/ca0106/ca0106_proc.c | |||
@@ -431,33 +431,30 @@ int __devinit snd_ca0106_proc_init(struct snd_ca0106 * emu) | |||
431 | struct snd_info_entry *entry; | 431 | struct snd_info_entry *entry; |
432 | 432 | ||
433 | if(! snd_card_proc_new(emu->card, "iec958", &entry)) | 433 | if(! snd_card_proc_new(emu->card, "iec958", &entry)) |
434 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_iec958); | 434 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_iec958); |
435 | if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) { | 435 | if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) { |
436 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32); | 436 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32); |
437 | entry->c.text.write_size = 64; | ||
438 | entry->c.text.write = snd_ca0106_proc_reg_write32; | 437 | entry->c.text.write = snd_ca0106_proc_reg_write32; |
439 | entry->mode |= S_IWUSR; | 438 | entry->mode |= S_IWUSR; |
440 | } | 439 | } |
441 | if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) | 440 | if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry)) |
442 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16); | 441 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16); |
443 | if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry)) | 442 | if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry)) |
444 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read8); | 443 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read8); |
445 | if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) { | 444 | if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) { |
446 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1); | 445 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1); |
447 | entry->c.text.write_size = 64; | ||
448 | entry->c.text.write = snd_ca0106_proc_reg_write; | 446 | entry->c.text.write = snd_ca0106_proc_reg_write; |
449 | entry->mode |= S_IWUSR; | 447 | entry->mode |= S_IWUSR; |
450 | // entry->private_data = emu; | 448 | // entry->private_data = emu; |
451 | } | 449 | } |
452 | if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { | 450 | if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) { |
453 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write); | 451 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_i2c_write); |
454 | entry->c.text.write_size = 64; | ||
455 | entry->c.text.write = snd_ca0106_proc_i2c_write; | 452 | entry->c.text.write = snd_ca0106_proc_i2c_write; |
456 | entry->mode |= S_IWUSR; | 453 | entry->mode |= S_IWUSR; |
457 | // entry->private_data = emu; | 454 | // entry->private_data = emu; |
458 | } | 455 | } |
459 | if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) | 456 | if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) |
460 | snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read2); | 457 | snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2); |
461 | return 0; | 458 | return 0; |
462 | } | 459 | } |
463 | 460 | ||
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index e5ce2dabd081..0938c158b5c9 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
@@ -2121,7 +2121,7 @@ static struct snd_kcontrol_new snd_cmipci_mixers[] __devinitdata = { | |||
2121 | CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), | 2121 | CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7), |
2122 | CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), | 2122 | CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7), |
2123 | CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), | 2123 | CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0), |
2124 | CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), | 2124 | CMIPCI_DOUBLE("PC Speaker Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0), |
2125 | CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), | 2125 | CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0), |
2126 | }; | 2126 | }; |
2127 | 2127 | ||
@@ -2602,7 +2602,7 @@ static void __devinit snd_cmipci_proc_init(struct cmipci *cm) | |||
2602 | struct snd_info_entry *entry; | 2602 | struct snd_info_entry *entry; |
2603 | 2603 | ||
2604 | if (! snd_card_proc_new(cm->card, "cmipci", &entry)) | 2604 | if (! snd_card_proc_new(cm->card, "cmipci", &entry)) |
2605 | snd_info_set_text_ops(entry, cm, 1024, snd_cmipci_proc_read); | 2605 | snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read); |
2606 | } | 2606 | } |
2607 | #else /* !CONFIG_PROC_FS */ | 2607 | #else /* !CONFIG_PROC_FS */ |
2608 | static inline void snd_cmipci_proc_init(struct cmipci *cm) {} | 2608 | static inline void snd_cmipci_proc_init(struct cmipci *cm) {} |
@@ -2932,7 +2932,7 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2932 | } | 2932 | } |
2933 | 2933 | ||
2934 | integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff; | 2934 | integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff; |
2935 | if (integrated_midi) | 2935 | if (integrated_midi && mpu_port[dev] == 1) |
2936 | iomidi = cm->iobase + CM_REG_MPU_PCI; | 2936 | iomidi = cm->iobase + CM_REG_MPU_PCI; |
2937 | else { | 2937 | else { |
2938 | iomidi = mpu_port[dev]; | 2938 | iomidi = mpu_port[dev]; |
@@ -2981,7 +2981,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc | |||
2981 | 2981 | ||
2982 | if (iomidi > 0) { | 2982 | if (iomidi > 0) { |
2983 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, | 2983 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI, |
2984 | iomidi, integrated_midi, | 2984 | iomidi, |
2985 | (integrated_midi ? | ||
2986 | MPU401_INFO_INTEGRATED : 0), | ||
2985 | cm->irq, 0, &cm->rmidi)) < 0) { | 2987 | cm->irq, 0, &cm->rmidi)) < 0) { |
2986 | printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); | 2988 | printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi); |
2987 | } | 2989 | } |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index b3c94d83450a..e77a4ce314b7 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
@@ -1184,7 +1184,7 @@ static void __devinit snd_cs4281_proc_init(struct cs4281 * chip) | |||
1184 | struct snd_info_entry *entry; | 1184 | struct snd_info_entry *entry; |
1185 | 1185 | ||
1186 | if (! snd_card_proc_new(chip->card, "cs4281", &entry)) | 1186 | if (! snd_card_proc_new(chip->card, "cs4281", &entry)) |
1187 | snd_info_set_text_ops(entry, chip, 1024, snd_cs4281_proc_read); | 1187 | snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read); |
1188 | if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) { | 1188 | if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) { |
1189 | entry->content = SNDRV_INFO_CONTENT_DATA; | 1189 | entry->content = SNDRV_INFO_CONTENT_DATA; |
1190 | entry->private_data = chip; | 1190 | entry->private_data = chip; |
@@ -1379,6 +1379,13 @@ static int __devinit snd_cs4281_create(struct snd_card *card, | |||
1379 | chip->ba0_addr = pci_resource_start(pci, 0); | 1379 | chip->ba0_addr = pci_resource_start(pci, 0); |
1380 | chip->ba1_addr = pci_resource_start(pci, 1); | 1380 | chip->ba1_addr = pci_resource_start(pci, 1); |
1381 | 1381 | ||
1382 | chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0)); | ||
1383 | chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1)); | ||
1384 | if (!chip->ba0 || !chip->ba1) { | ||
1385 | snd_cs4281_free(chip); | ||
1386 | return -ENOMEM; | ||
1387 | } | ||
1388 | |||
1382 | if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, | 1389 | if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ, |
1383 | "CS4281", chip)) { | 1390 | "CS4281", chip)) { |
1384 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1391 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
@@ -1387,13 +1394,6 @@ static int __devinit snd_cs4281_create(struct snd_card *card, | |||
1387 | } | 1394 | } |
1388 | chip->irq = pci->irq; | 1395 | chip->irq = pci->irq; |
1389 | 1396 | ||
1390 | chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0)); | ||
1391 | chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1)); | ||
1392 | if (!chip->ba0 || !chip->ba1) { | ||
1393 | snd_cs4281_free(chip); | ||
1394 | return -ENOMEM; | ||
1395 | } | ||
1396 | |||
1397 | tmp = snd_cs4281_chip_init(chip); | 1397 | tmp = snd_cs4281_chip_init(chip); |
1398 | if (tmp) { | 1398 | if (tmp) { |
1399 | snd_cs4281_free(chip); | 1399 | snd_cs4281_free(chip); |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 848d772ae3c6..772dc52bfeb2 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
@@ -48,8 +48,8 @@ MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)}," | |||
48 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 48 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
49 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 49 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
50 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 50 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
51 | static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 51 | static int external_amp[SNDRV_CARDS]; |
52 | static int thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 52 | static int thinkpad[SNDRV_CARDS]; |
53 | static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; | 53 | static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; |
54 | 54 | ||
55 | module_param_array(index, int, NULL, 0444); | 55 | module_param_array(index, int, NULL, 0444); |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index 69dbf542a6de..5c2114439204 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -2877,14 +2877,15 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) | |||
2877 | if (chip->region.idx[0].resource) | 2877 | if (chip->region.idx[0].resource) |
2878 | snd_cs46xx_hw_stop(chip); | 2878 | snd_cs46xx_hw_stop(chip); |
2879 | 2879 | ||
2880 | if (chip->irq >= 0) | ||
2881 | free_irq(chip->irq, chip); | ||
2882 | |||
2880 | for (idx = 0; idx < 5; idx++) { | 2883 | for (idx = 0; idx < 5; idx++) { |
2881 | struct snd_cs46xx_region *region = &chip->region.idx[idx]; | 2884 | struct snd_cs46xx_region *region = &chip->region.idx[idx]; |
2882 | if (region->remap_addr) | 2885 | if (region->remap_addr) |
2883 | iounmap(region->remap_addr); | 2886 | iounmap(region->remap_addr); |
2884 | release_and_free_resource(region->resource); | 2887 | release_and_free_resource(region->resource); |
2885 | } | 2888 | } |
2886 | if (chip->irq >= 0) | ||
2887 | free_irq(chip->irq, chip); | ||
2888 | 2889 | ||
2889 | if (chip->active_ctrl) | 2890 | if (chip->active_ctrl) |
2890 | chip->active_ctrl(chip, -chip->amplifier); | 2891 | chip->active_ctrl(chip, -chip->amplifier); |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index f407d2a5ce3b..5c9711c0265c 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -767,7 +767,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
767 | if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) { | 767 | if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) { |
768 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 768 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
769 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; | 769 | entry->mode = S_IFDIR | S_IRUGO | S_IXUGO; |
770 | entry->c.text.read_size = 512; | ||
771 | 770 | ||
772 | if (snd_info_register(entry) < 0) { | 771 | if (snd_info_register(entry) < 0) { |
773 | snd_info_free_entry(entry); | 772 | snd_info_free_entry(entry); |
@@ -784,7 +783,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
784 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 783 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
785 | entry->private_data = chip; | 784 | entry->private_data = chip; |
786 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 785 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
787 | entry->c.text.read_size = 512; | ||
788 | entry->c.text.read = cs46xx_dsp_proc_symbol_table_read; | 786 | entry->c.text.read = cs46xx_dsp_proc_symbol_table_read; |
789 | if (snd_info_register(entry) < 0) { | 787 | if (snd_info_register(entry) < 0) { |
790 | snd_info_free_entry(entry); | 788 | snd_info_free_entry(entry); |
@@ -797,7 +795,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
797 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 795 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
798 | entry->private_data = chip; | 796 | entry->private_data = chip; |
799 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 797 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
800 | entry->c.text.read_size = 512; | ||
801 | entry->c.text.read = cs46xx_dsp_proc_modules_read; | 798 | entry->c.text.read = cs46xx_dsp_proc_modules_read; |
802 | if (snd_info_register(entry) < 0) { | 799 | if (snd_info_register(entry) < 0) { |
803 | snd_info_free_entry(entry); | 800 | snd_info_free_entry(entry); |
@@ -810,7 +807,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
810 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 807 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
811 | entry->private_data = chip; | 808 | entry->private_data = chip; |
812 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 809 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
813 | entry->c.text.read_size = 512; | ||
814 | entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read; | 810 | entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read; |
815 | if (snd_info_register(entry) < 0) { | 811 | if (snd_info_register(entry) < 0) { |
816 | snd_info_free_entry(entry); | 812 | snd_info_free_entry(entry); |
@@ -823,7 +819,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
823 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 819 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
824 | entry->private_data = chip; | 820 | entry->private_data = chip; |
825 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 821 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
826 | entry->c.text.read_size = 512; | ||
827 | entry->c.text.read = cs46xx_dsp_proc_sample_dump_read; | 822 | entry->c.text.read = cs46xx_dsp_proc_sample_dump_read; |
828 | if (snd_info_register(entry) < 0) { | 823 | if (snd_info_register(entry) < 0) { |
829 | snd_info_free_entry(entry); | 824 | snd_info_free_entry(entry); |
@@ -836,7 +831,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
836 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 831 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
837 | entry->private_data = chip; | 832 | entry->private_data = chip; |
838 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 833 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
839 | entry->c.text.read_size = 512; | ||
840 | entry->c.text.read = cs46xx_dsp_proc_task_tree_read; | 834 | entry->c.text.read = cs46xx_dsp_proc_task_tree_read; |
841 | if (snd_info_register(entry) < 0) { | 835 | if (snd_info_register(entry) < 0) { |
842 | snd_info_free_entry(entry); | 836 | snd_info_free_entry(entry); |
@@ -849,7 +843,6 @@ int cs46xx_dsp_proc_init (struct snd_card *card, struct snd_cs46xx *chip) | |||
849 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 843 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
850 | entry->private_data = chip; | 844 | entry->private_data = chip; |
851 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 845 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
852 | entry->c.text.read_size = 1024; | ||
853 | entry->c.text.read = cs46xx_dsp_proc_scb_read; | 846 | entry->c.text.read = cs46xx_dsp_proc_scb_read; |
854 | if (snd_info_register(entry) < 0) { | 847 | if (snd_info_register(entry) < 0) { |
855 | snd_info_free_entry(entry); | 848 | snd_info_free_entry(entry); |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index 2c4ee45fe10c..3844d18af19c 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
@@ -267,7 +267,6 @@ void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip, | |||
267 | entry->private_data = scb_info; | 267 | entry->private_data = scb_info; |
268 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; | 268 | entry->mode = S_IFREG | S_IRUGO | S_IWUSR; |
269 | 269 | ||
270 | entry->c.text.read_size = 512; | ||
271 | entry->c.text.read = cs46xx_dsp_proc_scb_info_read; | 270 | entry->c.text.read = cs46xx_dsp_proc_scb_info_read; |
272 | 271 | ||
273 | if (snd_info_register(entry) < 0) { | 272 | if (snd_info_register(entry) < 0) { |
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index 08d8ee6547d3..2911a8adc1f2 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile | |||
@@ -4,5 +4,9 @@ | |||
4 | 4 | ||
5 | snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o | 5 | snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o |
6 | 6 | ||
7 | ifdef CONFIG_PM | ||
8 | snd-cs5535audio-objs += cs5535audio_pm.o | ||
9 | endif | ||
10 | |||
7 | # Toplevel Module Dependency | 11 | # Toplevel Module Dependency |
8 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o | 12 | obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 2c1213a35dcc..91c18a11fe87 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for audio on multifunction CS5535 companion device | 2 | * Driver for audio on multifunction CS5535/6 companion device |
3 | * Copyright (C) Jaya Kumar | 3 | * Copyright (C) Jaya Kumar |
4 | * | 4 | * |
5 | * Based on Jaroslav Kysela and Takashi Iwai's examples. | 5 | * Based on Jaroslav Kysela and Takashi Iwai's examples. |
@@ -40,16 +40,36 @@ | |||
40 | 40 | ||
41 | #define DRIVER_NAME "cs5535audio" | 41 | #define DRIVER_NAME "cs5535audio" |
42 | 42 | ||
43 | static char *ac97_quirk; | ||
44 | module_param(ac97_quirk, charp, 0444); | ||
45 | MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds."); | ||
46 | |||
47 | static struct ac97_quirk ac97_quirks[] __devinitdata = { | ||
48 | #if 0 /* Not yet confirmed if all 5536 boards are HP only */ | ||
49 | { | ||
50 | .subvendor = PCI_VENDOR_ID_AMD, | ||
51 | .subdevice = PCI_DEVICE_ID_AMD_CS5536_AUDIO, | ||
52 | .name = "AMD RDK", | ||
53 | .type = AC97_TUNE_HP_ONLY | ||
54 | }, | ||
55 | #endif | ||
56 | {} | ||
57 | }; | ||
43 | 58 | ||
44 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | 59 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; |
45 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 60 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
46 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | 61 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
47 | 62 | ||
63 | module_param_array(index, int, NULL, 0444); | ||
64 | MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME); | ||
65 | module_param_array(id, charp, NULL, 0444); | ||
66 | MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME); | ||
67 | module_param_array(enable, bool, NULL, 0444); | ||
68 | MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME); | ||
69 | |||
48 | static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { | 70 | static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = { |
49 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO, | 71 | { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) }, |
50 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, | 72 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) }, |
51 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO, | ||
52 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, | ||
53 | {} | 73 | {} |
54 | }; | 74 | }; |
55 | 75 | ||
@@ -90,7 +110,8 @@ static unsigned short snd_cs5535audio_codec_read(struct cs5535audio *cs5535au, | |||
90 | udelay(1); | 110 | udelay(1); |
91 | } while (--timeout); | 111 | } while (--timeout); |
92 | if (!timeout) | 112 | if (!timeout) |
93 | snd_printk(KERN_ERR "Failure reading cs5535 codec\n"); | 113 | snd_printk(KERN_ERR "Failure reading codec reg 0x%x," |
114 | "Last value=0x%x\n", reg, val); | ||
94 | 115 | ||
95 | return (unsigned short) val; | 116 | return (unsigned short) val; |
96 | } | 117 | } |
@@ -148,6 +169,8 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au) | |||
148 | return err; | 169 | return err; |
149 | } | 170 | } |
150 | 171 | ||
172 | snd_ac97_tune_hardware(cs5535au->ac97, ac97_quirks, ac97_quirk); | ||
173 | |||
151 | return 0; | 174 | return 0; |
152 | } | 175 | } |
153 | 176 | ||
@@ -347,6 +370,8 @@ static int __devinit snd_cs5535audio_probe(struct pci_dev *pci, | |||
347 | if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) | 370 | if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0) |
348 | goto probefail_out; | 371 | goto probefail_out; |
349 | 372 | ||
373 | card->private_data = cs5535au; | ||
374 | |||
350 | if ((err = snd_cs5535audio_mixer(cs5535au)) < 0) | 375 | if ((err = snd_cs5535audio_mixer(cs5535au)) < 0) |
351 | goto probefail_out; | 376 | goto probefail_out; |
352 | 377 | ||
@@ -383,6 +408,10 @@ static struct pci_driver driver = { | |||
383 | .id_table = snd_cs5535audio_ids, | 408 | .id_table = snd_cs5535audio_ids, |
384 | .probe = snd_cs5535audio_probe, | 409 | .probe = snd_cs5535audio_probe, |
385 | .remove = __devexit_p(snd_cs5535audio_remove), | 410 | .remove = __devexit_p(snd_cs5535audio_remove), |
411 | #ifdef CONFIG_PM | ||
412 | .suspend = snd_cs5535audio_suspend, | ||
413 | .resume = snd_cs5535audio_resume, | ||
414 | #endif | ||
386 | }; | 415 | }; |
387 | 416 | ||
388 | static int __init alsa_card_cs5535audio_init(void) | 417 | static int __init alsa_card_cs5535audio_init(void) |
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 5e55a1a1ed65..4fd1f31a6cf9 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h | |||
@@ -74,6 +74,8 @@ | |||
74 | #define PRM_RDY_STS 0x00800000 | 74 | #define PRM_RDY_STS 0x00800000 |
75 | #define ACC_CODEC_CNTL_WR_CMD (~0x80000000) | 75 | #define ACC_CODEC_CNTL_WR_CMD (~0x80000000) |
76 | #define ACC_CODEC_CNTL_RD_CMD 0x80000000 | 76 | #define ACC_CODEC_CNTL_RD_CMD 0x80000000 |
77 | #define ACC_CODEC_CNTL_LNK_SHUTDOWN 0x00040000 | ||
78 | #define ACC_CODEC_CNTL_LNK_WRM_RST 0x00020000 | ||
77 | #define PRD_JMP 0x2000 | 79 | #define PRD_JMP 0x2000 |
78 | #define PRD_EOP 0x4000 | 80 | #define PRD_EOP 0x4000 |
79 | #define PRD_EOT 0x8000 | 81 | #define PRD_EOT 0x8000 |
@@ -88,6 +90,7 @@ struct cs5535audio_dma_ops { | |||
88 | void (*disable_dma)(struct cs5535audio *cs5535au); | 90 | void (*disable_dma)(struct cs5535audio *cs5535au); |
89 | void (*pause_dma)(struct cs5535audio *cs5535au); | 91 | void (*pause_dma)(struct cs5535audio *cs5535au); |
90 | void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr); | 92 | void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr); |
93 | u32 (*read_prd)(struct cs5535audio *cs5535au); | ||
91 | u32 (*read_dma_pntr)(struct cs5535audio *cs5535au); | 94 | u32 (*read_dma_pntr)(struct cs5535audio *cs5535au); |
92 | }; | 95 | }; |
93 | 96 | ||
@@ -103,11 +106,14 @@ struct cs5535audio_dma { | |||
103 | struct snd_pcm_substream *substream; | 106 | struct snd_pcm_substream *substream; |
104 | unsigned int buf_addr, buf_bytes; | 107 | unsigned int buf_addr, buf_bytes; |
105 | unsigned int period_bytes, periods; | 108 | unsigned int period_bytes, periods; |
109 | int suspended; | ||
110 | u32 saved_prd; | ||
106 | }; | 111 | }; |
107 | 112 | ||
108 | struct cs5535audio { | 113 | struct cs5535audio { |
109 | struct snd_card *card; | 114 | struct snd_card *card; |
110 | struct snd_ac97 *ac97; | 115 | struct snd_ac97 *ac97; |
116 | struct snd_pcm *pcm; | ||
111 | int irq; | 117 | int irq; |
112 | struct pci_dev *pci; | 118 | struct pci_dev *pci; |
113 | unsigned long port; | 119 | unsigned long port; |
@@ -117,6 +123,8 @@ struct cs5535audio { | |||
117 | struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; | 123 | struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS]; |
118 | }; | 124 | }; |
119 | 125 | ||
126 | int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state); | ||
127 | int snd_cs5535audio_resume(struct pci_dev *pci); | ||
120 | int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio); | 128 | int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio); |
121 | 129 | ||
122 | #endif /* __SOUND_CS5535AUDIO_H */ | 130 | #endif /* __SOUND_CS5535AUDIO_H */ |
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 60bb82b2ff47..f0a48693d687 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c | |||
@@ -43,7 +43,8 @@ static struct snd_pcm_hardware snd_cs5535audio_playback = | |||
43 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 43 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
44 | SNDRV_PCM_INFO_MMAP_VALID | | 44 | SNDRV_PCM_INFO_MMAP_VALID | |
45 | SNDRV_PCM_INFO_PAUSE | | 45 | SNDRV_PCM_INFO_PAUSE | |
46 | SNDRV_PCM_INFO_SYNC_START | 46 | SNDRV_PCM_INFO_SYNC_START | |
47 | SNDRV_PCM_INFO_RESUME | ||
47 | ), | 48 | ), |
48 | .formats = ( | 49 | .formats = ( |
49 | SNDRV_PCM_FMTBIT_S16_LE | 50 | SNDRV_PCM_FMTBIT_S16_LE |
@@ -193,6 +194,11 @@ static void cs5535audio_playback_setup_prd(struct cs5535audio *cs5535au, | |||
193 | cs_writel(cs5535au, ACC_BM0_PRD, prd_addr); | 194 | cs_writel(cs5535au, ACC_BM0_PRD, prd_addr); |
194 | } | 195 | } |
195 | 196 | ||
197 | static u32 cs5535audio_playback_read_prd(struct cs5535audio *cs5535au) | ||
198 | { | ||
199 | return cs_readl(cs5535au, ACC_BM0_PRD); | ||
200 | } | ||
201 | |||
196 | static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au) | 202 | static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au) |
197 | { | 203 | { |
198 | return cs_readl(cs5535au, ACC_BM0_PNTR); | 204 | return cs_readl(cs5535au, ACC_BM0_PNTR); |
@@ -219,6 +225,11 @@ static void cs5535audio_capture_setup_prd(struct cs5535audio *cs5535au, | |||
219 | cs_writel(cs5535au, ACC_BM1_PRD, prd_addr); | 225 | cs_writel(cs5535au, ACC_BM1_PRD, prd_addr); |
220 | } | 226 | } |
221 | 227 | ||
228 | static u32 cs5535audio_capture_read_prd(struct cs5535audio *cs5535au) | ||
229 | { | ||
230 | return cs_readl(cs5535au, ACC_BM1_PRD); | ||
231 | } | ||
232 | |||
222 | static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au) | 233 | static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au) |
223 | { | 234 | { |
224 | return cs_readl(cs5535au, ACC_BM1_PNTR); | 235 | return cs_readl(cs5535au, ACC_BM1_PNTR); |
@@ -285,9 +296,17 @@ static int snd_cs5535audio_trigger(struct snd_pcm_substream *substream, int cmd) | |||
285 | case SNDRV_PCM_TRIGGER_START: | 296 | case SNDRV_PCM_TRIGGER_START: |
286 | dma->ops->enable_dma(cs5535au); | 297 | dma->ops->enable_dma(cs5535au); |
287 | break; | 298 | break; |
299 | case SNDRV_PCM_TRIGGER_RESUME: | ||
300 | dma->ops->enable_dma(cs5535au); | ||
301 | dma->suspended = 0; | ||
302 | break; | ||
288 | case SNDRV_PCM_TRIGGER_STOP: | 303 | case SNDRV_PCM_TRIGGER_STOP: |
289 | dma->ops->disable_dma(cs5535au); | 304 | dma->ops->disable_dma(cs5535au); |
290 | break; | 305 | break; |
306 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
307 | dma->ops->disable_dma(cs5535au); | ||
308 | dma->suspended = 1; | ||
309 | break; | ||
291 | default: | 310 | default: |
292 | snd_printk(KERN_ERR "unhandled trigger\n"); | 311 | snd_printk(KERN_ERR "unhandled trigger\n"); |
293 | err = -EINVAL; | 312 | err = -EINVAL; |
@@ -375,6 +394,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_playback_dma_ops = { | |||
375 | .enable_dma = cs5535audio_playback_enable_dma, | 394 | .enable_dma = cs5535audio_playback_enable_dma, |
376 | .disable_dma = cs5535audio_playback_disable_dma, | 395 | .disable_dma = cs5535audio_playback_disable_dma, |
377 | .setup_prd = cs5535audio_playback_setup_prd, | 396 | .setup_prd = cs5535audio_playback_setup_prd, |
397 | .read_prd = cs5535audio_playback_read_prd, | ||
378 | .pause_dma = cs5535audio_playback_pause_dma, | 398 | .pause_dma = cs5535audio_playback_pause_dma, |
379 | .read_dma_pntr = cs5535audio_playback_read_dma_pntr, | 399 | .read_dma_pntr = cs5535audio_playback_read_dma_pntr, |
380 | }; | 400 | }; |
@@ -384,6 +404,7 @@ static struct cs5535audio_dma_ops snd_cs5535audio_capture_dma_ops = { | |||
384 | .enable_dma = cs5535audio_capture_enable_dma, | 404 | .enable_dma = cs5535audio_capture_enable_dma, |
385 | .disable_dma = cs5535audio_capture_disable_dma, | 405 | .disable_dma = cs5535audio_capture_disable_dma, |
386 | .setup_prd = cs5535audio_capture_setup_prd, | 406 | .setup_prd = cs5535audio_capture_setup_prd, |
407 | .read_prd = cs5535audio_capture_read_prd, | ||
387 | .pause_dma = cs5535audio_capture_pause_dma, | 408 | .pause_dma = cs5535audio_capture_pause_dma, |
388 | .read_dma_pntr = cs5535audio_capture_read_dma_pntr, | 409 | .read_dma_pntr = cs5535audio_capture_read_dma_pntr, |
389 | }; | 410 | }; |
@@ -413,6 +434,7 @@ int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535au) | |||
413 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 434 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
414 | snd_dma_pci_data(cs5535au->pci), | 435 | snd_dma_pci_data(cs5535au->pci), |
415 | 64*1024, 128*1024); | 436 | 64*1024, 128*1024); |
437 | cs5535au->pcm = pcm; | ||
416 | 438 | ||
417 | return 0; | 439 | return 0; |
418 | } | 440 | } |
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c new file mode 100644 index 000000000000..aad0e69db9c1 --- /dev/null +++ b/sound/pci/cs5535audio/cs5535audio_pm.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * Power management for audio on multifunction CS5535 companion device | ||
3 | * Copyright (C) Jaya Kumar | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <sound/driver.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/control.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/asoundef.h> | ||
30 | #include <sound/pcm.h> | ||
31 | #include <sound/ac97_codec.h> | ||
32 | #include "cs5535audio.h" | ||
33 | |||
34 | static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au) | ||
35 | { | ||
36 | /* | ||
37 | we depend on snd_ac97_suspend to tell the | ||
38 | AC97 codec to shutdown. the amd spec suggests | ||
39 | that the LNK_SHUTDOWN be done at the same time | ||
40 | that the codec power-down is issued. instead, | ||
41 | we do it just after rather than at the same | ||
42 | time. excluding codec specific build_ops->suspend | ||
43 | ac97 powerdown hits: | ||
44 | 0x8000 EAPD | ||
45 | 0x4000 Headphone amplifier | ||
46 | 0x0300 ADC & DAC | ||
47 | 0x0400 Analog Mixer powerdown (Vref on) | ||
48 | I am not sure if this is the best that we can do. | ||
49 | The remainder to be investigated are: | ||
50 | - analog mixer (vref off) 0x0800 | ||
51 | - AC-link powerdown 0x1000 | ||
52 | - codec internal clock 0x2000 | ||
53 | */ | ||
54 | |||
55 | /* set LNK_SHUTDOWN to shutdown AC link */ | ||
56 | cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN); | ||
57 | |||
58 | } | ||
59 | |||
60 | int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) | ||
61 | { | ||
62 | struct snd_card *card = pci_get_drvdata(pci); | ||
63 | struct cs5535audio *cs5535au = card->private_data; | ||
64 | int i; | ||
65 | |||
66 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
67 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { | ||
68 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; | ||
69 | if (dma && dma->substream && !dma->suspended) | ||
70 | dma->saved_prd = dma->ops->read_prd(cs5535au); | ||
71 | } | ||
72 | snd_pcm_suspend_all(cs5535au->pcm); | ||
73 | snd_ac97_suspend(cs5535au->ac97); | ||
74 | /* save important regs, then disable aclink in hw */ | ||
75 | snd_cs5535audio_stop_hardware(cs5535au); | ||
76 | pci_disable_device(pci); | ||
77 | pci_save_state(pci); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | int snd_cs5535audio_resume(struct pci_dev *pci) | ||
83 | { | ||
84 | struct snd_card *card = pci_get_drvdata(pci); | ||
85 | struct cs5535audio *cs5535au = card->private_data; | ||
86 | u32 tmp; | ||
87 | int timeout; | ||
88 | int i; | ||
89 | |||
90 | pci_restore_state(pci); | ||
91 | pci_enable_device(pci); | ||
92 | pci_set_master(pci); | ||
93 | |||
94 | /* set LNK_WRM_RST to reset AC link */ | ||
95 | cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST); | ||
96 | |||
97 | timeout = 50; | ||
98 | do { | ||
99 | tmp = cs_readl(cs5535au, ACC_CODEC_STATUS); | ||
100 | if (tmp & PRM_RDY_STS) | ||
101 | break; | ||
102 | udelay(1); | ||
103 | } while (--timeout); | ||
104 | |||
105 | if (!timeout) | ||
106 | snd_printk(KERN_ERR "Failure getting AC Link ready\n"); | ||
107 | |||
108 | /* we depend on ac97 to perform the codec power up */ | ||
109 | snd_ac97_resume(cs5535au->ac97); | ||
110 | /* set up rate regs, dma. actual initiation is done in trig */ | ||
111 | for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { | ||
112 | struct cs5535audio_dma *dma = &cs5535au->dmas[i]; | ||
113 | if (dma && dma->substream && dma->suspended) { | ||
114 | dma->substream->ops->prepare(dma->substream); | ||
115 | dma->ops->setup_prd(cs5535au, dma->saved_prd); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index 42b11ba1d210..549673ea14a9 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
@@ -46,13 +46,13 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS}," | |||
46 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 46 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
47 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 47 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
48 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 48 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
49 | static int extin[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 49 | static int extin[SNDRV_CARDS]; |
50 | static int extout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 50 | static int extout[SNDRV_CARDS]; |
51 | static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; | 51 | static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; |
52 | static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; | 52 | static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; |
53 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; | 53 | static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; |
54 | static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 54 | static int enable_ir[SNDRV_CARDS]; |
55 | static uint subsystem[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* Force card subsystem model */ | 55 | static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ |
56 | 56 | ||
57 | module_param_array(index, int, NULL, 0444); | 57 | module_param_array(index, int, NULL, 0444); |
58 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); | 58 | MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 6bfa08436efa..42a358f989c3 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -777,14 +777,6 @@ static int snd_emu10k1_dev_free(struct snd_device *device) | |||
777 | 777 | ||
778 | static struct snd_emu_chip_details emu_chip_details[] = { | 778 | static struct snd_emu_chip_details emu_chip_details[] = { |
779 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ | 779 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ |
780 | /* Audigy4 SB0400 */ | ||
781 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, | ||
782 | .driver = "Audigy2", .name = "Audigy 4 [SB0400]", | ||
783 | .id = "Audigy2", | ||
784 | .emu10k2_chip = 1, | ||
785 | .ca0108_chip = 1, | ||
786 | .spk71 = 1, | ||
787 | .ac97_chip = 1} , | ||
788 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | 780 | /* Tested by James@superbug.co.uk 3rd July 2005 */ |
789 | /* DSP: CA0108-IAT | 781 | /* DSP: CA0108-IAT |
790 | * DAC: CS4382-KQ | 782 | * DAC: CS4382-KQ |
@@ -799,13 +791,59 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
799 | .ca0108_chip = 1, | 791 | .ca0108_chip = 1, |
800 | .spk71 = 1, | 792 | .spk71 = 1, |
801 | .ac97_chip = 1} , | 793 | .ac97_chip = 1} , |
794 | /* Audigy4 (Not PRO) SB0610 */ | ||
795 | /* Tested by James@superbug.co.uk 4th April 2006 */ | ||
796 | /* A_IOCFG bits | ||
797 | * Output | ||
798 | * 0: ? | ||
799 | * 1: ? | ||
800 | * 2: ? | ||
801 | * 3: 0 - Digital Out, 1 - Line in | ||
802 | * 4: ? | ||
803 | * 5: ? | ||
804 | * 6: ? | ||
805 | * 7: ? | ||
806 | * Input | ||
807 | * 8: ? | ||
808 | * 9: ? | ||
809 | * A: Green jack sense (Front) | ||
810 | * B: ? | ||
811 | * C: Black jack sense (Rear/Side Right) | ||
812 | * D: Yellow jack sense (Center/LFE/Side Left) | ||
813 | * E: ? | ||
814 | * F: ? | ||
815 | * | ||
816 | * Digital Out/Line in switch using A_IOCFG bit 3 (0x08) | ||
817 | * 0 - Digital Out | ||
818 | * 1 - Line in | ||
819 | */ | ||
820 | /* Mic input not tested. | ||
821 | * Analog CD input not tested | ||
822 | * Digital Out not tested. | ||
823 | * Line in working. | ||
824 | * Audio output 5.1 working. Side outputs not working. | ||
825 | */ | ||
826 | /* DSP: CA10300-IAT LF | ||
827 | * DAC: Cirrus Logic CS4382-KQZ | ||
828 | * ADC: Philips 1361T | ||
829 | * AC97: Sigmatel STAC9750 | ||
830 | * CA0151: None | ||
831 | */ | ||
832 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, | ||
833 | .driver = "Audigy2", .name = "Audigy 4 [SB0610]", | ||
834 | .id = "Audigy2", | ||
835 | .emu10k2_chip = 1, | ||
836 | .ca0108_chip = 1, | ||
837 | .spk71 = 1, | ||
838 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ | ||
839 | .ac97_chip = 1} , | ||
802 | /* Audigy 2 ZS Notebook Cardbus card.*/ | 840 | /* Audigy 2 ZS Notebook Cardbus card.*/ |
803 | /* Tested by James@superbug.co.uk 22th December 2005 */ | 841 | /* Tested by James@superbug.co.uk 22th December 2005 */ |
804 | /* Audio output 7.1/Headphones working. | 842 | /* Audio output 7.1/Headphones working. |
805 | * Digital output working. (AC3 not checked, only PCM) | 843 | * Digital output working. (AC3 not checked, only PCM) |
806 | * Audio inputs not tested. | 844 | * Audio inputs not tested. |
807 | */ | 845 | */ |
808 | /* DSP: Tiny2 | 846 | /* DSP: Tina2 |
809 | * DAC: Wolfson WM8768/WM8568 | 847 | * DAC: Wolfson WM8768/WM8568 |
810 | * ADC: Wolfson WM8775 | 848 | * ADC: Wolfson WM8775 |
811 | * AC97: None | 849 | * AC97: None |
@@ -1421,16 +1459,3 @@ void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu) | |||
1421 | } | 1459 | } |
1422 | } | 1460 | } |
1423 | #endif | 1461 | #endif |
1424 | |||
1425 | /* memory.c */ | ||
1426 | EXPORT_SYMBOL(snd_emu10k1_synth_alloc); | ||
1427 | EXPORT_SYMBOL(snd_emu10k1_synth_free); | ||
1428 | EXPORT_SYMBOL(snd_emu10k1_synth_bzero); | ||
1429 | EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user); | ||
1430 | EXPORT_SYMBOL(snd_emu10k1_memblk_map); | ||
1431 | /* voice.c */ | ||
1432 | EXPORT_SYMBOL(snd_emu10k1_voice_alloc); | ||
1433 | EXPORT_SYMBOL(snd_emu10k1_voice_free); | ||
1434 | /* io.c */ | ||
1435 | EXPORT_SYMBOL(snd_emu10k1_ptr_read); | ||
1436 | EXPORT_SYMBOL(snd_emu10k1_ptr_write); | ||
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index d51290c18167..0fb27e4be07b 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
@@ -1055,8 +1055,7 @@ static int __devinit snd_emu10k1x_proc_init(struct emu10k1x * emu) | |||
1055 | struct snd_info_entry *entry; | 1055 | struct snd_info_entry *entry; |
1056 | 1056 | ||
1057 | if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) { | 1057 | if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) { |
1058 | snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read); | 1058 | snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read); |
1059 | entry->c.text.write_size = 64; | ||
1060 | entry->c.text.write = snd_emu10k1x_proc_reg_write; | 1059 | entry->c.text.write = snd_emu10k1x_proc_reg_write; |
1061 | entry->mode |= S_IWUSR; | 1060 | entry->mode |= S_IWUSR; |
1062 | entry->private_data = emu; | 1061 | entry->private_data = emu; |
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 2a9d12d10680..c31f3d0877fa 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c | |||
@@ -777,6 +777,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
777 | }; | 777 | }; |
778 | static char *audigy_remove_ctls[] = { | 778 | static char *audigy_remove_ctls[] = { |
779 | /* Master/PCM controls on ac97 of Audigy has no effect */ | 779 | /* Master/PCM controls on ac97 of Audigy has no effect */ |
780 | /* On the Audigy2 the AC97 playback is piped into | ||
781 | * the Philips ADC for 24bit capture */ | ||
780 | "PCM Playback Switch", | 782 | "PCM Playback Switch", |
781 | "PCM Playback Volume", | 783 | "PCM Playback Volume", |
782 | "Master Mono Playback Switch", | 784 | "Master Mono Playback Switch", |
@@ -804,6 +806,47 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
804 | "AMic Playback Volume", "Mic Playback Volume", | 806 | "AMic Playback Volume", "Mic Playback Volume", |
805 | NULL | 807 | NULL |
806 | }; | 808 | }; |
809 | static char *audigy_remove_ctls_1361t_adc[] = { | ||
810 | /* On the Audigy2 the AC97 playback is piped into | ||
811 | * the Philips ADC for 24bit capture */ | ||
812 | "PCM Playback Switch", | ||
813 | "PCM Playback Volume", | ||
814 | "Master Mono Playback Switch", | ||
815 | "Master Mono Playback Volume", | ||
816 | "Capture Source", | ||
817 | "Capture Switch", | ||
818 | "Capture Volume", | ||
819 | "Mic Capture Volume", | ||
820 | "Headphone Playback Switch", | ||
821 | "Headphone Playback Volume", | ||
822 | "3D Control - Center", | ||
823 | "3D Control - Depth", | ||
824 | "3D Control - Switch", | ||
825 | "Line2 Playback Volume", | ||
826 | "Line2 Capture Volume", | ||
827 | NULL | ||
828 | }; | ||
829 | static char *audigy_rename_ctls_1361t_adc[] = { | ||
830 | "Master Playback Switch", "Master Capture Switch", | ||
831 | "Master Playback Volume", "Master Capture Volume", | ||
832 | "Wave Master Playback Volume", "Master Playback Volume", | ||
833 | "PC Speaker Playback Switch", "PC Speaker Capture Switch", | ||
834 | "PC Speaker Playback Volume", "PC Speaker Capture Volume", | ||
835 | "Phone Playback Switch", "Phone Capture Switch", | ||
836 | "Phone Playback Volume", "Phone Capture Volume", | ||
837 | "Mic Playback Switch", "Mic Capture Switch", | ||
838 | "Mic Playback Volume", "Mic Capture Volume", | ||
839 | "Line Playback Switch", "Line Capture Switch", | ||
840 | "Line Playback Volume", "Line Capture Volume", | ||
841 | "CD Playback Switch", "CD Capture Switch", | ||
842 | "CD Playback Volume", "CD Capture Volume", | ||
843 | "Aux Playback Switch", "Aux Capture Switch", | ||
844 | "Aux Playback Volume", "Aux Capture Volume", | ||
845 | "Video Playback Switch", "Video Capture Switch", | ||
846 | "Video Playback Volume", "Video Capture Volume", | ||
847 | |||
848 | NULL | ||
849 | }; | ||
807 | 850 | ||
808 | if (emu->card_capabilities->ac97_chip) { | 851 | if (emu->card_capabilities->ac97_chip) { |
809 | struct snd_ac97_bus *pbus; | 852 | struct snd_ac97_bus *pbus; |
@@ -834,7 +877,10 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
834 | snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); | 877 | snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); |
835 | /* set capture source to mic */ | 878 | /* set capture source to mic */ |
836 | snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); | 879 | snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); |
837 | c = audigy_remove_ctls; | 880 | if (emu->card_capabilities->adc_1361t) |
881 | c = audigy_remove_ctls_1361t_adc; | ||
882 | else | ||
883 | c = audigy_remove_ctls; | ||
838 | } else { | 884 | } else { |
839 | /* | 885 | /* |
840 | * Credits for cards based on STAC9758: | 886 | * Credits for cards based on STAC9758: |
@@ -863,11 +909,15 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
863 | } | 909 | } |
864 | 910 | ||
865 | if (emu->audigy) | 911 | if (emu->audigy) |
866 | c = audigy_rename_ctls; | 912 | if (emu->card_capabilities->adc_1361t) |
913 | c = audigy_rename_ctls_1361t_adc; | ||
914 | else | ||
915 | c = audigy_rename_ctls; | ||
867 | else | 916 | else |
868 | c = emu10k1_rename_ctls; | 917 | c = emu10k1_rename_ctls; |
869 | for (; *c; c += 2) | 918 | for (; *c; c += 2) |
870 | rename_ctl(card, c[0], c[1]); | 919 | rename_ctl(card, c[0], c[1]); |
920 | |||
871 | if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ | 921 | if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ |
872 | rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); | 922 | rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); |
873 | rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); | 923 | rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); |
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c index 90f1c52703a1..b939e03aaedf 100644 --- a/sound/pci/emu10k1/emuproc.c +++ b/sound/pci/emu10k1/emuproc.c | |||
@@ -532,57 +532,51 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) | |||
532 | struct snd_info_entry *entry; | 532 | struct snd_info_entry *entry; |
533 | #ifdef CONFIG_SND_DEBUG | 533 | #ifdef CONFIG_SND_DEBUG |
534 | if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { | 534 | if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { |
535 | snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read); | 535 | snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); |
536 | entry->c.text.write_size = 64; | ||
537 | entry->c.text.write = snd_emu_proc_io_reg_write; | 536 | entry->c.text.write = snd_emu_proc_io_reg_write; |
538 | entry->mode |= S_IWUSR; | 537 | entry->mode |= S_IWUSR; |
539 | } | 538 | } |
540 | if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { | 539 | if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) { |
541 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a); | 540 | snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a); |
542 | entry->c.text.write_size = 64; | ||
543 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; | 541 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; |
544 | entry->mode |= S_IWUSR; | 542 | entry->mode |= S_IWUSR; |
545 | } | 543 | } |
546 | if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { | 544 | if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) { |
547 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b); | 545 | snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b); |
548 | entry->c.text.write_size = 64; | ||
549 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; | 546 | entry->c.text.write = snd_emu_proc_ptr_reg_write00; |
550 | entry->mode |= S_IWUSR; | 547 | entry->mode |= S_IWUSR; |
551 | } | 548 | } |
552 | if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { | 549 | if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) { |
553 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a); | 550 | snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a); |
554 | entry->c.text.write_size = 64; | ||
555 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; | 551 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; |
556 | entry->mode |= S_IWUSR; | 552 | entry->mode |= S_IWUSR; |
557 | } | 553 | } |
558 | if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { | 554 | if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) { |
559 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b); | 555 | snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b); |
560 | entry->c.text.write_size = 64; | ||
561 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; | 556 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; |
562 | entry->mode |= S_IWUSR; | 557 | entry->mode |= S_IWUSR; |
563 | } | 558 | } |
564 | if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) { | 559 | if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) { |
565 | snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20c); | 560 | snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c); |
566 | entry->c.text.write_size = 64; | ||
567 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; | 561 | entry->c.text.write = snd_emu_proc_ptr_reg_write20; |
568 | entry->mode |= S_IWUSR; | 562 | entry->mode |= S_IWUSR; |
569 | } | 563 | } |
570 | #endif | 564 | #endif |
571 | 565 | ||
572 | if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) | 566 | if (! snd_card_proc_new(emu->card, "emu10k1", &entry)) |
573 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read); | 567 | snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_read); |
574 | 568 | ||
575 | if (emu->card_capabilities->emu10k2_chip) { | 569 | if (emu->card_capabilities->emu10k2_chip) { |
576 | if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) | 570 | if (! snd_card_proc_new(emu->card, "spdif-in", &entry)) |
577 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read); | 571 | snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_spdif_read); |
578 | } | 572 | } |
579 | if (emu->card_capabilities->ca0151_chip) { | 573 | if (emu->card_capabilities->ca0151_chip) { |
580 | if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) | 574 | if (! snd_card_proc_new(emu->card, "capture-rates", &entry)) |
581 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read); | 575 | snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_rates_read); |
582 | } | 576 | } |
583 | 577 | ||
584 | if (! snd_card_proc_new(emu->card, "voices", &entry)) | 578 | if (! snd_card_proc_new(emu->card, "voices", &entry)) |
585 | snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read); | 579 | snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_voices_read); |
586 | 580 | ||
587 | if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { | 581 | if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) { |
588 | entry->content = SNDRV_INFO_CONTENT_DATA; | 582 | entry->content = SNDRV_INFO_CONTENT_DATA; |
@@ -616,7 +610,6 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu) | |||
616 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 610 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
617 | entry->private_data = emu; | 611 | entry->private_data = emu; |
618 | entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; | 612 | entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/; |
619 | entry->c.text.read_size = 128*1024; | ||
620 | entry->c.text.read = snd_emu10k1_proc_acode_read; | 613 | entry->c.text.read = snd_emu10k1_proc_acode_read; |
621 | } | 614 | } |
622 | return 0; | 615 | return 0; |
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c index ef5304df8c11..029e7856c43b 100644 --- a/sound/pci/emu10k1/io.c +++ b/sound/pci/emu10k1/io.c | |||
@@ -62,6 +62,8 @@ unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, un | |||
62 | } | 62 | } |
63 | } | 63 | } |
64 | 64 | ||
65 | EXPORT_SYMBOL(snd_emu10k1_ptr_read); | ||
66 | |||
65 | void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data) | 67 | void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data) |
66 | { | 68 | { |
67 | unsigned int regptr; | 69 | unsigned int regptr; |
@@ -92,6 +94,8 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i | |||
92 | } | 94 | } |
93 | } | 95 | } |
94 | 96 | ||
97 | EXPORT_SYMBOL(snd_emu10k1_ptr_write); | ||
98 | |||
95 | unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, | 99 | unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, |
96 | unsigned int reg, | 100 | unsigned int reg, |
97 | unsigned int chn) | 101 | unsigned int chn) |
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index e7ec98649f04..4fcaefe5a3c5 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
@@ -287,6 +287,8 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b | |||
287 | return err; | 287 | return err; |
288 | } | 288 | } |
289 | 289 | ||
290 | EXPORT_SYMBOL(snd_emu10k1_memblk_map); | ||
291 | |||
290 | /* | 292 | /* |
291 | * page allocation for DMA | 293 | * page allocation for DMA |
292 | */ | 294 | */ |
@@ -387,6 +389,7 @@ snd_emu10k1_synth_alloc(struct snd_emu10k1 *hw, unsigned int size) | |||
387 | return (struct snd_util_memblk *)blk; | 389 | return (struct snd_util_memblk *)blk; |
388 | } | 390 | } |
389 | 391 | ||
392 | EXPORT_SYMBOL(snd_emu10k1_synth_alloc); | ||
390 | 393 | ||
391 | /* | 394 | /* |
392 | * free a synth sample area | 395 | * free a synth sample area |
@@ -409,6 +412,7 @@ snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *memblk) | |||
409 | return 0; | 412 | return 0; |
410 | } | 413 | } |
411 | 414 | ||
415 | EXPORT_SYMBOL(snd_emu10k1_synth_free); | ||
412 | 416 | ||
413 | /* check new allocation range */ | 417 | /* check new allocation range */ |
414 | static void get_single_page_range(struct snd_util_memhdr *hdr, | 418 | static void get_single_page_range(struct snd_util_memhdr *hdr, |
@@ -540,6 +544,8 @@ int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk | |||
540 | return 0; | 544 | return 0; |
541 | } | 545 | } |
542 | 546 | ||
547 | EXPORT_SYMBOL(snd_emu10k1_synth_bzero); | ||
548 | |||
543 | /* | 549 | /* |
544 | * copy_from_user(blk + offset, data, size) | 550 | * copy_from_user(blk + offset, data, size) |
545 | */ | 551 | */ |
@@ -568,3 +574,5 @@ int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_me | |||
568 | } while (offset < end_offset); | 574 | } while (offset < end_offset); |
569 | return 0; | 575 | return 0; |
570 | } | 576 | } |
577 | |||
578 | EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user); | ||
diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h new file mode 100644 index 000000000000..7ddb5be632cf --- /dev/null +++ b/sound/pci/emu10k1/p17v.h | |||
@@ -0,0 +1,111 @@ | |||
1 | /* | ||
2 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> | ||
3 | * Driver p17v chips | ||
4 | * Version: 0.01 | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /******************************************************************************/ | ||
23 | /* Audigy2Value Tina (P17V) pointer-offset register set, | ||
24 | * accessed through the PTR20 and DATA24 registers */ | ||
25 | /******************************************************************************/ | ||
26 | |||
27 | /* 00 - 07: Not used */ | ||
28 | #define P17V_PLAYBACK_FIFO_PTR 0x08 /* Current playback fifo pointer | ||
29 | * and number of sound samples in cache. | ||
30 | */ | ||
31 | /* 09 - 12: Not used */ | ||
32 | #define P17V_CAPTURE_FIFO_PTR 0x13 /* Current capture fifo pointer | ||
33 | * and number of sound samples in cache. | ||
34 | */ | ||
35 | /* 14 - 17: Not used */ | ||
36 | #define P17V_PB_CHN_SEL 0x18 /* P17v playback channel select */ | ||
37 | #define P17V_SE_SLOT_SEL_L 0x19 /* Sound Engine slot select low */ | ||
38 | #define P17V_SE_SLOT_SEL_H 0x1a /* Sound Engine slot select high */ | ||
39 | /* 1b - 1f: Not used */ | ||
40 | /* 20 - 2f: Not used */ | ||
41 | /* 30 - 3b: Not used */ | ||
42 | #define P17V_SPI 0x3c /* SPI interface register */ | ||
43 | #define P17V_I2C_ADDR 0x3d /* I2C Address */ | ||
44 | #define P17V_I2C_0 0x3e /* I2C Data */ | ||
45 | #define P17V_I2C_1 0x3f /* I2C Data */ | ||
46 | |||
47 | #define P17V_START_AUDIO 0x40 /* Start Audio bit */ | ||
48 | /* 41 - 47: Reserved */ | ||
49 | #define P17V_START_CAPTURE 0x48 /* Start Capture bit */ | ||
50 | #define P17V_CAPTURE_FIFO_BASE 0x49 /* Record FIFO base address */ | ||
51 | #define P17V_CAPTURE_FIFO_SIZE 0x4a /* Record FIFO buffer size */ | ||
52 | #define P17V_CAPTURE_FIFO_INDEX 0x4b /* Record FIFO capture index */ | ||
53 | #define P17V_CAPTURE_VOL_H 0x4c /* P17v capture volume control */ | ||
54 | #define P17V_CAPTURE_VOL_L 0x4d /* P17v capture volume control */ | ||
55 | /* 4e - 4f: Not used */ | ||
56 | /* 50 - 5f: Not used */ | ||
57 | #define P17V_SRCSel 0x60 /* SRC48 and SRCMulti sample rate select | ||
58 | * and output select | ||
59 | */ | ||
60 | #define P17V_MIXER_AC97_10K1_VOL_L 0x61 /* 10K to Mixer_AC97 input volume control */ | ||
61 | #define P17V_MIXER_AC97_10K1_VOL_H 0x62 /* 10K to Mixer_AC97 input volume control */ | ||
62 | #define P17V_MIXER_AC97_P17V_VOL_L 0x63 /* P17V to Mixer_AC97 input volume control */ | ||
63 | #define P17V_MIXER_AC97_P17V_VOL_H 0x64 /* P17V to Mixer_AC97 input volume control */ | ||
64 | #define P17V_MIXER_AC97_SRP_REC_VOL_L 0x65 /* SRP Record to Mixer_AC97 input volume control */ | ||
65 | #define P17V_MIXER_AC97_SRP_REC_VOL_H 0x66 /* SRP Record to Mixer_AC97 input volume control */ | ||
66 | /* 67 - 68: Reserved */ | ||
67 | #define P17V_MIXER_Spdif_10K1_VOL_L 0x69 /* 10K to Mixer_Spdif input volume control */ | ||
68 | #define P17V_MIXER_Spdif_10K1_VOL_H 0x6A /* 10K to Mixer_Spdif input volume control */ | ||
69 | #define P17V_MIXER_Spdif_P17V_VOL_L 0x6B /* P17V to Mixer_Spdif input volume control */ | ||
70 | #define P17V_MIXER_Spdif_P17V_VOL_H 0x6C /* P17V to Mixer_Spdif input volume control */ | ||
71 | #define P17V_MIXER_Spdif_SRP_REC_VOL_L 0x6D /* SRP Record to Mixer_Spdif input volume control */ | ||
72 | #define P17V_MIXER_Spdif_SRP_REC_VOL_H 0x6E /* SRP Record to Mixer_Spdif input volume control */ | ||
73 | /* 6f - 70: Reserved */ | ||
74 | #define P17V_MIXER_I2S_10K1_VOL_L 0x71 /* 10K to Mixer_I2S input volume control */ | ||
75 | #define P17V_MIXER_I2S_10K1_VOL_H 0x72 /* 10K to Mixer_I2S input volume control */ | ||
76 | #define P17V_MIXER_I2S_P17V_VOL_L 0x73 /* P17V to Mixer_I2S input volume control */ | ||
77 | #define P17V_MIXER_I2S_P17V_VOL_H 0x74 /* P17V to Mixer_I2S input volume control */ | ||
78 | #define P17V_MIXER_I2S_SRP_REC_VOL_L 0x75 /* SRP Record to Mixer_I2S input volume control */ | ||
79 | #define P17V_MIXER_I2S_SRP_REC_VOL_H 0x76 /* SRP Record to Mixer_I2S input volume control */ | ||
80 | /* 77 - 78: Reserved */ | ||
81 | #define P17V_MIXER_AC97_ENABLE 0x79 /* Mixer AC97 input audio enable */ | ||
82 | #define P17V_MIXER_SPDIF_ENABLE 0x7A /* Mixer SPDIF input audio enable */ | ||
83 | #define P17V_MIXER_I2S_ENABLE 0x7B /* Mixer I2S input audio enable */ | ||
84 | #define P17V_AUDIO_OUT_ENABLE 0x7C /* Audio out enable */ | ||
85 | #define P17V_MIXER_ATT 0x7D /* SRP Mixer Attenuation Select */ | ||
86 | #define P17V_SRP_RECORD_SRR 0x7E /* SRP Record channel source Select */ | ||
87 | #define P17V_SOFT_RESET_SRP_MIXER 0x7F /* SRP and mixer soft reset */ | ||
88 | |||
89 | #define P17V_AC97_OUT_MASTER_VOL_L 0x80 /* AC97 Output master volume control */ | ||
90 | #define P17V_AC97_OUT_MASTER_VOL_H 0x81 /* AC97 Output master volume control */ | ||
91 | #define P17V_SPDIF_OUT_MASTER_VOL_L 0x82 /* SPDIF Output master volume control */ | ||
92 | #define P17V_SPDIF_OUT_MASTER_VOL_H 0x83 /* SPDIF Output master volume control */ | ||
93 | #define P17V_I2S_OUT_MASTER_VOL_L 0x84 /* I2S Output master volume control */ | ||
94 | #define P17V_I2S_OUT_MASTER_VOL_H 0x85 /* I2S Output master volume control */ | ||
95 | /* 86 - 87: Not used */ | ||
96 | #define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE 0x88 /* I2S out mono channel swap | ||
97 | * and phase inverse */ | ||
98 | #define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE 0x89 /* SPDIF out mono channel swap | ||
99 | * and phase inverse */ | ||
100 | /* 8A: Not used */ | ||
101 | #define P17V_SRP_P17V_ESR 0x8B /* SRP_P17V estimated sample rate and rate lock */ | ||
102 | #define P17V_SRP_REC_ESR 0x8C /* SRP_REC estimated sample rate and rate lock */ | ||
103 | #define P17V_SRP_BYPASS 0x8D /* srps channel bypass and srps bypass */ | ||
104 | /* 8E - 92: Not used */ | ||
105 | #define P17V_I2S_SRC_SEL 0x93 /* I2SIN mode sel */ | ||
106 | |||
107 | |||
108 | |||
109 | |||
110 | |||
111 | |||
diff --git a/sound/pci/emu10k1/tina2.h b/sound/pci/emu10k1/tina2.h index 5c43abf03e89..f2d8eb6c89e1 100644 --- a/sound/pci/emu10k1/tina2.h +++ b/sound/pci/emu10k1/tina2.h | |||
@@ -1,11 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> | 2 | * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> |
3 | * Driver p16v chips | 3 | * Driver tina2 chips |
4 | * Version: 0.21 | 4 | * Version: 0.1 |
5 | * | ||
6 | * | ||
7 | * This code was initally based on code from ALSA's emu10k1x.c which is: | ||
8 | * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com> | ||
9 | * | 5 | * |
10 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c index 56ffb7dc3ee2..94eca82dd4fc 100644 --- a/sound/pci/emu10k1/voice.c +++ b/sound/pci/emu10k1/voice.c | |||
@@ -139,6 +139,8 @@ int snd_emu10k1_voice_alloc(struct snd_emu10k1 *emu, int type, int number, | |||
139 | return result; | 139 | return result; |
140 | } | 140 | } |
141 | 141 | ||
142 | EXPORT_SYMBOL(snd_emu10k1_voice_alloc); | ||
143 | |||
142 | int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, | 144 | int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, |
143 | struct snd_emu10k1_voice *pvoice) | 145 | struct snd_emu10k1_voice *pvoice) |
144 | { | 146 | { |
@@ -153,3 +155,5 @@ int snd_emu10k1_voice_free(struct snd_emu10k1 *emu, | |||
153 | spin_unlock_irqrestore(&emu->voice_lock, flags); | 155 | spin_unlock_irqrestore(&emu->voice_lock, flags); |
154 | return 0; | 156 | return 0; |
155 | } | 157 | } |
158 | |||
159 | EXPORT_SYMBOL(snd_emu10k1_voice_free); | ||
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index ca9e34e88f62..9d46bbee2a40 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -1915,7 +1915,7 @@ static void __devinit snd_ensoniq_proc_init(struct ensoniq * ensoniq) | |||
1915 | struct snd_info_entry *entry; | 1915 | struct snd_info_entry *entry; |
1916 | 1916 | ||
1917 | if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry)) | 1917 | if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry)) |
1918 | snd_info_set_text_ops(entry, ensoniq, 1024, snd_ensoniq_proc_read); | 1918 | snd_info_set_text_ops(entry, ensoniq, snd_ensoniq_proc_read); |
1919 | } | 1919 | } |
1920 | 1920 | ||
1921 | /* | 1921 | /* |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index 6f9094ca4fb4..ca6603fe0b11 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
@@ -1756,7 +1756,8 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci, | |||
1756 | } | 1756 | } |
1757 | } | 1757 | } |
1758 | if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, | 1758 | if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, |
1759 | chip->mpu_port, 1, chip->irq, 0, &chip->rmidi) < 0) { | 1759 | chip->mpu_port, MPU401_INFO_INTEGRATED, |
1760 | chip->irq, 0, &chip->rmidi) < 0) { | ||
1760 | printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); | 1761 | printk(KERN_ERR "es1938: unable to initialize MPU-401\n"); |
1761 | } else { | 1762 | } else { |
1762 | // this line is vital for MIDI interrupt handling on ess-solo1 | 1763 | // this line is vital for MIDI interrupt handling on ess-solo1 |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index 5ff4175c7b6d..bfa0876e715e 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
@@ -132,7 +132,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * | |||
132 | static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 }; | 132 | static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 }; |
133 | static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 }; | 133 | static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 }; |
134 | static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 }; | 134 | static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 }; |
135 | static int clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 135 | static int clock[SNDRV_CARDS]; |
136 | static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; | 136 | static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; |
137 | static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; | 137 | static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; |
138 | #ifdef SUPPORT_JOYSTICK | 138 | #ifdef SUPPORT_JOYSTICK |
@@ -2727,7 +2727,8 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci, | |||
2727 | } | 2727 | } |
2728 | if (enable_mpu[dev]) { | 2728 | if (enable_mpu[dev]) { |
2729 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, | 2729 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, |
2730 | chip->io_port + ESM_MPU401_PORT, 1, | 2730 | chip->io_port + ESM_MPU401_PORT, |
2731 | MPU401_INFO_INTEGRATED, | ||
2731 | chip->irq, 0, &chip->rmidi)) < 0) { | 2732 | chip->irq, 0, &chip->rmidi)) < 0) { |
2732 | printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n"); | 2733 | printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n"); |
2733 | } | 2734 | } |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index d72fc28c580e..0afa573dd244 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
@@ -56,7 +56,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * | |||
56 | * 3 = MediaForte 64-PCR | 56 | * 3 = MediaForte 64-PCR |
57 | * High 16-bits are video (radio) device number + 1 | 57 | * High 16-bits are video (radio) device number + 1 |
58 | */ | 58 | */ |
59 | static int tea575x_tuner[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; | 59 | static int tea575x_tuner[SNDRV_CARDS]; |
60 | 60 | ||
61 | module_param_array(index, int, NULL, 0444); | 61 | module_param_array(index, int, NULL, 0444); |
62 | MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); | 62 | MODULE_PARM_DESC(index, "Index value for the FM801 soundcard."); |
@@ -1448,7 +1448,8 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, | |||
1448 | return err; | 1448 | return err; |
1449 | } | 1449 | } |
1450 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, | 1450 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801, |
1451 | FM801_REG(chip, MPU401_DATA), 1, | 1451 | FM801_REG(chip, MPU401_DATA), |
1452 | MPU401_INFO_INTEGRATED, | ||
1452 | chip->irq, 0, &chip->rmidi)) < 0) { | 1453 | chip->irq, 0, &chip->rmidi)) < 0) { |
1453 | snd_card_free(card); | 1454 | snd_card_free(card); |
1454 | return err; | 1455 | return err; |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index ddfb5ff7fb8f..dbacba6177db 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o | 2 | snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o patch_atihdmi.o |
3 | ifdef CONFIG_PROC_FS | 3 | ifdef CONFIG_PROC_FS |
4 | snd-hda-codec-objs += hda_proc.o | 4 | snd-hda-codec-objs += hda_proc.o |
5 | endif | 5 | endif |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 5bee3b536478..8c2a8174ece1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -86,6 +86,8 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int dire | |||
86 | return res; | 86 | return res; |
87 | } | 87 | } |
88 | 88 | ||
89 | EXPORT_SYMBOL(snd_hda_codec_read); | ||
90 | |||
89 | /** | 91 | /** |
90 | * snd_hda_codec_write - send a single command without waiting for response | 92 | * snd_hda_codec_write - send a single command without waiting for response |
91 | * @codec: the HDA codec | 93 | * @codec: the HDA codec |
@@ -108,6 +110,8 @@ int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, | |||
108 | return err; | 110 | return err; |
109 | } | 111 | } |
110 | 112 | ||
113 | EXPORT_SYMBOL(snd_hda_codec_write); | ||
114 | |||
111 | /** | 115 | /** |
112 | * snd_hda_sequence_write - sequence writes | 116 | * snd_hda_sequence_write - sequence writes |
113 | * @codec: the HDA codec | 117 | * @codec: the HDA codec |
@@ -122,6 +126,8 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq) | |||
122 | snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); | 126 | snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); |
123 | } | 127 | } |
124 | 128 | ||
129 | EXPORT_SYMBOL(snd_hda_sequence_write); | ||
130 | |||
125 | /** | 131 | /** |
126 | * snd_hda_get_sub_nodes - get the range of sub nodes | 132 | * snd_hda_get_sub_nodes - get the range of sub nodes |
127 | * @codec: the HDA codec | 133 | * @codec: the HDA codec |
@@ -140,6 +146,8 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *sta | |||
140 | return (int)(parm & 0x7fff); | 146 | return (int)(parm & 0x7fff); |
141 | } | 147 | } |
142 | 148 | ||
149 | EXPORT_SYMBOL(snd_hda_get_sub_nodes); | ||
150 | |||
143 | /** | 151 | /** |
144 | * snd_hda_get_connections - get connection list | 152 | * snd_hda_get_connections - get connection list |
145 | * @codec: the HDA codec | 153 | * @codec: the HDA codec |
@@ -256,6 +264,8 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) | |||
256 | return 0; | 264 | return 0; |
257 | } | 265 | } |
258 | 266 | ||
267 | EXPORT_SYMBOL(snd_hda_queue_unsol_event); | ||
268 | |||
259 | /* | 269 | /* |
260 | * process queueud unsolicited events | 270 | * process queueud unsolicited events |
261 | */ | 271 | */ |
@@ -384,6 +394,7 @@ int snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, | |||
384 | return 0; | 394 | return 0; |
385 | } | 395 | } |
386 | 396 | ||
397 | EXPORT_SYMBOL(snd_hda_bus_new); | ||
387 | 398 | ||
388 | /* | 399 | /* |
389 | * find a matching codec preset | 400 | * find a matching codec preset |
@@ -587,6 +598,8 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr, | |||
587 | return 0; | 598 | return 0; |
588 | } | 599 | } |
589 | 600 | ||
601 | EXPORT_SYMBOL(snd_hda_codec_new); | ||
602 | |||
590 | /** | 603 | /** |
591 | * snd_hda_codec_setup_stream - set up the codec for streaming | 604 | * snd_hda_codec_setup_stream - set up the codec for streaming |
592 | * @codec: the CODEC to set up | 605 | * @codec: the CODEC to set up |
@@ -609,6 +622,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre | |||
609 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); | 622 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format); |
610 | } | 623 | } |
611 | 624 | ||
625 | EXPORT_SYMBOL(snd_hda_codec_setup_stream); | ||
612 | 626 | ||
613 | /* | 627 | /* |
614 | * amp access functions | 628 | * amp access functions |
@@ -1294,6 +1308,7 @@ int snd_hda_build_controls(struct hda_bus *bus) | |||
1294 | return 0; | 1308 | return 0; |
1295 | } | 1309 | } |
1296 | 1310 | ||
1311 | EXPORT_SYMBOL(snd_hda_build_controls); | ||
1297 | 1312 | ||
1298 | /* | 1313 | /* |
1299 | * stream formats | 1314 | * stream formats |
@@ -1382,6 +1397,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate, | |||
1382 | return val; | 1397 | return val; |
1383 | } | 1398 | } |
1384 | 1399 | ||
1400 | EXPORT_SYMBOL(snd_hda_calc_stream_format); | ||
1401 | |||
1385 | /** | 1402 | /** |
1386 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats | 1403 | * snd_hda_query_supported_pcm - query the supported PCM rates and formats |
1387 | * @codec: the HDA codec | 1404 | * @codec: the HDA codec |
@@ -1663,6 +1680,7 @@ int snd_hda_build_pcms(struct hda_bus *bus) | |||
1663 | return 0; | 1680 | return 0; |
1664 | } | 1681 | } |
1665 | 1682 | ||
1683 | EXPORT_SYMBOL(snd_hda_build_pcms); | ||
1666 | 1684 | ||
1667 | /** | 1685 | /** |
1668 | * snd_hda_check_board_config - compare the current codec with the config table | 1686 | * snd_hda_check_board_config - compare the current codec with the config table |
@@ -2165,6 +2183,8 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state) | |||
2165 | return 0; | 2183 | return 0; |
2166 | } | 2184 | } |
2167 | 2185 | ||
2186 | EXPORT_SYMBOL(snd_hda_suspend); | ||
2187 | |||
2168 | /** | 2188 | /** |
2169 | * snd_hda_resume - resume the codecs | 2189 | * snd_hda_resume - resume the codecs |
2170 | * @bus: the HDA bus | 2190 | * @bus: the HDA bus |
@@ -2187,6 +2207,8 @@ int snd_hda_resume(struct hda_bus *bus) | |||
2187 | return 0; | 2207 | return 0; |
2188 | } | 2208 | } |
2189 | 2209 | ||
2210 | EXPORT_SYMBOL(snd_hda_resume); | ||
2211 | |||
2190 | /** | 2212 | /** |
2191 | * snd_hda_resume_ctls - resume controls in the new control list | 2213 | * snd_hda_resume_ctls - resume controls in the new control list |
2192 | * @codec: the HDA codec | 2214 | * @codec: the HDA codec |
@@ -2247,25 +2269,6 @@ int snd_hda_resume_spdif_in(struct hda_codec *codec) | |||
2247 | #endif | 2269 | #endif |
2248 | 2270 | ||
2249 | /* | 2271 | /* |
2250 | * symbols exported for controller modules | ||
2251 | */ | ||
2252 | EXPORT_SYMBOL(snd_hda_codec_read); | ||
2253 | EXPORT_SYMBOL(snd_hda_codec_write); | ||
2254 | EXPORT_SYMBOL(snd_hda_sequence_write); | ||
2255 | EXPORT_SYMBOL(snd_hda_get_sub_nodes); | ||
2256 | EXPORT_SYMBOL(snd_hda_queue_unsol_event); | ||
2257 | EXPORT_SYMBOL(snd_hda_bus_new); | ||
2258 | EXPORT_SYMBOL(snd_hda_codec_new); | ||
2259 | EXPORT_SYMBOL(snd_hda_codec_setup_stream); | ||
2260 | EXPORT_SYMBOL(snd_hda_calc_stream_format); | ||
2261 | EXPORT_SYMBOL(snd_hda_build_pcms); | ||
2262 | EXPORT_SYMBOL(snd_hda_build_controls); | ||
2263 | #ifdef CONFIG_PM | ||
2264 | EXPORT_SYMBOL(snd_hda_suspend); | ||
2265 | EXPORT_SYMBOL(snd_hda_resume); | ||
2266 | #endif | ||
2267 | |||
2268 | /* | ||
2269 | * INIT part | 2272 | * INIT part |
2270 | */ | 2273 | */ |
2271 | 2274 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index e821d65afa11..4070b5cd9b6b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -82,6 +82,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6}," | |||
82 | "{Intel, ICH8}," | 82 | "{Intel, ICH8}," |
83 | "{ATI, SB450}," | 83 | "{ATI, SB450}," |
84 | "{ATI, SB600}," | 84 | "{ATI, SB600}," |
85 | "{ATI, RS600}," | ||
85 | "{VIA, VT8251}," | 86 | "{VIA, VT8251}," |
86 | "{VIA, VT8237A}," | 87 | "{VIA, VT8237A}," |
87 | "{SiS, SIS966}," | 88 | "{SiS, SIS966}," |
@@ -167,6 +168,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; | |||
167 | #define ULI_PLAYBACK_INDEX 5 | 168 | #define ULI_PLAYBACK_INDEX 5 |
168 | #define ULI_NUM_PLAYBACK 6 | 169 | #define ULI_NUM_PLAYBACK 6 |
169 | 170 | ||
171 | /* ATI HDMI has 1 playback and 0 capture */ | ||
172 | #define ATIHDMI_CAPTURE_INDEX 0 | ||
173 | #define ATIHDMI_NUM_CAPTURE 0 | ||
174 | #define ATIHDMI_PLAYBACK_INDEX 0 | ||
175 | #define ATIHDMI_NUM_PLAYBACK 1 | ||
176 | |||
170 | /* this number is statically defined for simplicity */ | 177 | /* this number is statically defined for simplicity */ |
171 | #define MAX_AZX_DEV 16 | 178 | #define MAX_AZX_DEV 16 |
172 | 179 | ||
@@ -331,6 +338,7 @@ struct azx { | |||
331 | enum { | 338 | enum { |
332 | AZX_DRIVER_ICH, | 339 | AZX_DRIVER_ICH, |
333 | AZX_DRIVER_ATI, | 340 | AZX_DRIVER_ATI, |
341 | AZX_DRIVER_ATIHDMI, | ||
334 | AZX_DRIVER_VIA, | 342 | AZX_DRIVER_VIA, |
335 | AZX_DRIVER_SIS, | 343 | AZX_DRIVER_SIS, |
336 | AZX_DRIVER_ULI, | 344 | AZX_DRIVER_ULI, |
@@ -340,6 +348,7 @@ enum { | |||
340 | static char *driver_short_names[] __devinitdata = { | 348 | static char *driver_short_names[] __devinitdata = { |
341 | [AZX_DRIVER_ICH] = "HDA Intel", | 349 | [AZX_DRIVER_ICH] = "HDA Intel", |
342 | [AZX_DRIVER_ATI] = "HDA ATI SB", | 350 | [AZX_DRIVER_ATI] = "HDA ATI SB", |
351 | [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", | ||
343 | [AZX_DRIVER_VIA] = "HDA VIA VT82xx", | 352 | [AZX_DRIVER_VIA] = "HDA VIA VT82xx", |
344 | [AZX_DRIVER_SIS] = "HDA SIS966", | 353 | [AZX_DRIVER_SIS] = "HDA SIS966", |
345 | [AZX_DRIVER_ULI] = "HDA ULI M5461", | 354 | [AZX_DRIVER_ULI] = "HDA ULI M5461", |
@@ -1393,10 +1402,10 @@ static int azx_free(struct azx *chip) | |||
1393 | msleep(1); | 1402 | msleep(1); |
1394 | } | 1403 | } |
1395 | 1404 | ||
1396 | if (chip->remap_addr) | ||
1397 | iounmap(chip->remap_addr); | ||
1398 | if (chip->irq >= 0) | 1405 | if (chip->irq >= 0) |
1399 | free_irq(chip->irq, (void*)chip); | 1406 | free_irq(chip->irq, (void*)chip); |
1407 | if (chip->remap_addr) | ||
1408 | iounmap(chip->remap_addr); | ||
1400 | 1409 | ||
1401 | if (chip->bdl.area) | 1410 | if (chip->bdl.area) |
1402 | snd_dma_free_pages(&chip->bdl); | 1411 | snd_dma_free_pages(&chip->bdl); |
@@ -1495,6 +1504,12 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
1495 | chip->playback_index_offset = ULI_PLAYBACK_INDEX; | 1504 | chip->playback_index_offset = ULI_PLAYBACK_INDEX; |
1496 | chip->capture_index_offset = ULI_CAPTURE_INDEX; | 1505 | chip->capture_index_offset = ULI_CAPTURE_INDEX; |
1497 | break; | 1506 | break; |
1507 | case AZX_DRIVER_ATIHDMI: | ||
1508 | chip->playback_streams = ATIHDMI_NUM_PLAYBACK; | ||
1509 | chip->capture_streams = ATIHDMI_NUM_CAPTURE; | ||
1510 | chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX; | ||
1511 | chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX; | ||
1512 | break; | ||
1498 | default: | 1513 | default: |
1499 | chip->playback_streams = ICH6_NUM_PLAYBACK; | 1514 | chip->playback_streams = ICH6_NUM_PLAYBACK; |
1500 | chip->capture_streams = ICH6_NUM_CAPTURE; | 1515 | chip->capture_streams = ICH6_NUM_CAPTURE; |
@@ -1621,6 +1636,7 @@ static struct pci_device_id azx_ids[] __devinitdata = { | |||
1621 | { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ | 1636 | { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */ |
1622 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ | 1637 | { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */ |
1623 | { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ | 1638 | { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */ |
1639 | { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */ | ||
1624 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ | 1640 | { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */ |
1625 | { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ | 1641 | { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */ |
1626 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ | 1642 | { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */ |
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h index acaef3c811b8..0b668793face 100644 --- a/sound/pci/hda/hda_patch.h +++ b/sound/pci/hda/hda_patch.h | |||
@@ -12,6 +12,8 @@ extern struct hda_codec_preset snd_hda_preset_analog[]; | |||
12 | extern struct hda_codec_preset snd_hda_preset_sigmatel[]; | 12 | extern struct hda_codec_preset snd_hda_preset_sigmatel[]; |
13 | /* SiLabs 3054/3055 modem codecs */ | 13 | /* SiLabs 3054/3055 modem codecs */ |
14 | extern struct hda_codec_preset snd_hda_preset_si3054[]; | 14 | extern struct hda_codec_preset snd_hda_preset_si3054[]; |
15 | /* ATI HDMI codecs */ | ||
16 | extern struct hda_codec_preset snd_hda_preset_atihdmi[]; | ||
15 | 17 | ||
16 | static const struct hda_codec_preset *hda_preset_tables[] = { | 18 | static const struct hda_codec_preset *hda_preset_tables[] = { |
17 | snd_hda_preset_realtek, | 19 | snd_hda_preset_realtek, |
@@ -19,5 +21,6 @@ static const struct hda_codec_preset *hda_preset_tables[] = { | |||
19 | snd_hda_preset_analog, | 21 | snd_hda_preset_analog, |
20 | snd_hda_preset_sigmatel, | 22 | snd_hda_preset_sigmatel, |
21 | snd_hda_preset_si3054, | 23 | snd_hda_preset_si3054, |
24 | snd_hda_preset_atihdmi, | ||
22 | NULL | 25 | NULL |
23 | }; | 26 | }; |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index ca514a6a5875..c2f0fe85bf35 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -182,6 +182,10 @@ static void print_pin_caps(struct snd_info_buffer *buffer, | |||
182 | snd_iprintf(buffer, " OUT"); | 182 | snd_iprintf(buffer, " OUT"); |
183 | if (caps & AC_PINCAP_HP_DRV) | 183 | if (caps & AC_PINCAP_HP_DRV) |
184 | snd_iprintf(buffer, " HP"); | 184 | snd_iprintf(buffer, " HP"); |
185 | if (caps & AC_PINCAP_EAPD) | ||
186 | snd_iprintf(buffer, " EAPD"); | ||
187 | if (caps & AC_PINCAP_PRES_DETECT) | ||
188 | snd_iprintf(buffer, " Detect"); | ||
185 | snd_iprintf(buffer, "\n"); | 189 | snd_iprintf(buffer, "\n"); |
186 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); | 190 | caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); |
187 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, | 191 | snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps, |
@@ -318,7 +322,7 @@ int snd_hda_codec_proc_new(struct hda_codec *codec) | |||
318 | if (err < 0) | 322 | if (err < 0) |
319 | return err; | 323 | return err; |
320 | 324 | ||
321 | snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info); | 325 | snd_info_set_text_ops(entry, codec, print_codec_info); |
322 | return 0; | 326 | return 0; |
323 | } | 327 | } |
324 | 328 | ||
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 40f000ba1362..dd4e00a82b55 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -789,6 +789,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { | |||
789 | { .modelname = "3stack", .config = AD1986A_3STACK }, | 789 | { .modelname = "3stack", .config = AD1986A_3STACK }, |
790 | { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, | 790 | { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, |
791 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ | 791 | .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ |
792 | { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, | ||
793 | .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ | ||
792 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, | 794 | { .modelname = "laptop", .config = AD1986A_LAPTOP }, |
793 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, | 795 | { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, |
794 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ | 796 | .config = AD1986A_LAPTOP }, /* FSC V2060 */ |
@@ -809,6 +811,8 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { | |||
809 | .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */ | 811 | .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */ |
810 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af, | 812 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af, |
811 | .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */ | 813 | .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */ |
814 | { .pci_subvendor = 0x17aa, .pci_subdevice = 0x2066, | ||
815 | .config = AD1986A_LAPTOP_EAPD }, /* Lenovo 3000 N100-07684JU */ | ||
812 | {} | 816 | {} |
813 | }; | 817 | }; |
814 | 818 | ||
@@ -963,7 +967,7 @@ static struct snd_kcontrol_new ad1983_mixers[] = { | |||
963 | }, | 967 | }, |
964 | { | 968 | { |
965 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 969 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
966 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", | 970 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", |
967 | .info = ad1983_spdif_route_info, | 971 | .info = ad1983_spdif_route_info, |
968 | .get = ad1983_spdif_route_get, | 972 | .get = ad1983_spdif_route_get, |
969 | .put = ad1983_spdif_route_put, | 973 | .put = ad1983_spdif_route_put, |
@@ -1103,7 +1107,7 @@ static struct snd_kcontrol_new ad1981_mixers[] = { | |||
1103 | /* identical with AD1983 */ | 1107 | /* identical with AD1983 */ |
1104 | { | 1108 | { |
1105 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 1109 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
1106 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", | 1110 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", |
1107 | .info = ad1983_spdif_route_info, | 1111 | .info = ad1983_spdif_route_info, |
1108 | .get = ad1983_spdif_route_get, | 1112 | .get = ad1983_spdif_route_get, |
1109 | .put = ad1983_spdif_route_put, | 1113 | .put = ad1983_spdif_route_put, |
@@ -1329,13 +1333,60 @@ static int ad1981_hp_init(struct hda_codec *codec) | |||
1329 | return 0; | 1333 | return 0; |
1330 | } | 1334 | } |
1331 | 1335 | ||
1336 | /* configuration for Lenovo Thinkpad T60 */ | ||
1337 | static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = { | ||
1338 | HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT), | ||
1339 | HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT), | ||
1340 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT), | ||
1341 | HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
1342 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), | ||
1343 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
1344 | HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT), | ||
1345 | HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT), | ||
1346 | HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT), | ||
1347 | HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT), | ||
1348 | HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT), | ||
1349 | { | ||
1350 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1351 | .name = "Capture Source", | ||
1352 | .info = ad198x_mux_enum_info, | ||
1353 | .get = ad198x_mux_enum_get, | ||
1354 | .put = ad198x_mux_enum_put, | ||
1355 | }, | ||
1356 | /* identical with AD1983 */ | ||
1357 | { | ||
1358 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1359 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", | ||
1360 | .info = ad1983_spdif_route_info, | ||
1361 | .get = ad1983_spdif_route_get, | ||
1362 | .put = ad1983_spdif_route_put, | ||
1363 | }, | ||
1364 | { } /* end */ | ||
1365 | }; | ||
1366 | |||
1367 | static struct hda_input_mux ad1981_thinkpad_capture_source = { | ||
1368 | .num_items = 3, | ||
1369 | .items = { | ||
1370 | { "Mic", 0x0 }, | ||
1371 | { "Mix", 0x2 }, | ||
1372 | { "CD", 0x4 }, | ||
1373 | }, | ||
1374 | }; | ||
1375 | |||
1332 | /* models */ | 1376 | /* models */ |
1333 | enum { AD1981_BASIC, AD1981_HP }; | 1377 | enum { AD1981_BASIC, AD1981_HP, AD1981_THINKPAD }; |
1334 | 1378 | ||
1335 | static struct hda_board_config ad1981_cfg_tbl[] = { | 1379 | static struct hda_board_config ad1981_cfg_tbl[] = { |
1336 | { .modelname = "hp", .config = AD1981_HP }, | 1380 | { .modelname = "hp", .config = AD1981_HP }, |
1337 | /* All HP models */ | 1381 | /* All HP models */ |
1338 | { .pci_subvendor = 0x103c, .config = AD1981_HP }, | 1382 | { .pci_subvendor = 0x103c, .config = AD1981_HP }, |
1383 | { .pci_subvendor = 0x30b0, .pci_subdevice = 0x103c, | ||
1384 | .config = AD1981_HP }, /* HP nx6320 (reversed SSID, H/W bug) */ | ||
1385 | { .modelname = "thinkpad", .config = AD1981_THINKPAD }, | ||
1386 | /* Lenovo Thinkpad T60/X60/Z6xx */ | ||
1387 | { .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD }, | ||
1388 | { .pci_subvendor = 0x1014, .pci_subdevice = 0x0597, | ||
1389 | .config = AD1981_THINKPAD }, /* Z60m/t */ | ||
1339 | { .modelname = "basic", .config = AD1981_BASIC }, | 1390 | { .modelname = "basic", .config = AD1981_BASIC }, |
1340 | {} | 1391 | {} |
1341 | }; | 1392 | }; |
@@ -1381,6 +1432,10 @@ static int patch_ad1981(struct hda_codec *codec) | |||
1381 | codec->patch_ops.init = ad1981_hp_init; | 1432 | codec->patch_ops.init = ad1981_hp_init; |
1382 | codec->patch_ops.unsol_event = ad1981_hp_unsol_event; | 1433 | codec->patch_ops.unsol_event = ad1981_hp_unsol_event; |
1383 | break; | 1434 | break; |
1435 | case AD1981_THINKPAD: | ||
1436 | spec->mixers[0] = ad1981_thinkpad_mixers; | ||
1437 | spec->input_mux = &ad1981_thinkpad_capture_source; | ||
1438 | break; | ||
1384 | } | 1439 | } |
1385 | 1440 | ||
1386 | return 0; | 1441 | return 0; |
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c new file mode 100644 index 000000000000..a27440ffd1c8 --- /dev/null +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Universal Interface for Intel High Definition Audio Codec | ||
3 | * | ||
4 | * HD audio interface patch for ATI HDMI codecs | ||
5 | * | ||
6 | * Copyright (c) 2006 ATI Technologies Inc. | ||
7 | * | ||
8 | * | ||
9 | * This driver is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This driver is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <sound/driver.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <sound/core.h> | ||
30 | #include "hda_codec.h" | ||
31 | #include "hda_local.h" | ||
32 | |||
33 | struct atihdmi_spec { | ||
34 | struct hda_multi_out multiout; | ||
35 | |||
36 | struct hda_pcm pcm_rec; | ||
37 | }; | ||
38 | |||
39 | static struct hda_verb atihdmi_basic_init[] = { | ||
40 | /* enable digital output on pin widget */ | ||
41 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
42 | {} /* terminator */ | ||
43 | }; | ||
44 | |||
45 | /* | ||
46 | * Controls | ||
47 | */ | ||
48 | static int atihdmi_build_controls(struct hda_codec *codec) | ||
49 | { | ||
50 | struct atihdmi_spec *spec = codec->spec; | ||
51 | int err; | ||
52 | |||
53 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
54 | if (err < 0) | ||
55 | return err; | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int atihdmi_init(struct hda_codec *codec) | ||
61 | { | ||
62 | snd_hda_sequence_write(codec, atihdmi_basic_init); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | #ifdef CONFIG_PM | ||
67 | /* | ||
68 | * resume | ||
69 | */ | ||
70 | static int atihdmi_resume(struct hda_codec *codec) | ||
71 | { | ||
72 | atihdmi_init(codec); | ||
73 | snd_hda_resume_spdif_out(codec); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | /* | ||
80 | * Digital out | ||
81 | */ | ||
82 | static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
83 | struct hda_codec *codec, | ||
84 | struct snd_pcm_substream *substream) | ||
85 | { | ||
86 | struct atihdmi_spec *spec = codec->spec; | ||
87 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
88 | } | ||
89 | |||
90 | static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
91 | struct hda_codec *codec, | ||
92 | struct snd_pcm_substream *substream) | ||
93 | { | ||
94 | struct atihdmi_spec *spec = codec->spec; | ||
95 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
96 | } | ||
97 | |||
98 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | ||
99 | .substreams = 1, | ||
100 | .channels_min = 2, | ||
101 | .channels_max = 2, | ||
102 | .nid = 0x2, /* NID to query formats and rates and setup streams */ | ||
103 | .ops = { | ||
104 | .open = atihdmi_dig_playback_pcm_open, | ||
105 | .close = atihdmi_dig_playback_pcm_close | ||
106 | }, | ||
107 | }; | ||
108 | |||
109 | static int atihdmi_build_pcms(struct hda_codec *codec) | ||
110 | { | ||
111 | struct atihdmi_spec *spec = codec->spec; | ||
112 | struct hda_pcm *info = &spec->pcm_rec; | ||
113 | |||
114 | codec->num_pcms = 1; | ||
115 | codec->pcm_info = info; | ||
116 | |||
117 | info->name = "ATI HDMI"; | ||
118 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static void atihdmi_free(struct hda_codec *codec) | ||
124 | { | ||
125 | kfree(codec->spec); | ||
126 | } | ||
127 | |||
128 | static struct hda_codec_ops atihdmi_patch_ops = { | ||
129 | .build_controls = atihdmi_build_controls, | ||
130 | .build_pcms = atihdmi_build_pcms, | ||
131 | .init = atihdmi_init, | ||
132 | .free = atihdmi_free, | ||
133 | #ifdef CONFIG_PM | ||
134 | .resume = atihdmi_resume, | ||
135 | #endif | ||
136 | }; | ||
137 | |||
138 | static int patch_atihdmi(struct hda_codec *codec) | ||
139 | { | ||
140 | struct atihdmi_spec *spec; | ||
141 | |||
142 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
143 | if (spec == NULL) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | codec->spec = spec; | ||
147 | |||
148 | spec->multiout.num_dacs = 0; /* no analog */ | ||
149 | spec->multiout.max_channels = 2; | ||
150 | spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital, | ||
151 | * seems to be unused in pure-digital | ||
152 | * case. */ | ||
153 | |||
154 | codec->patch_ops = atihdmi_patch_ops; | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * patch entries | ||
161 | */ | ||
162 | struct hda_codec_preset snd_hda_preset_atihdmi[] = { | ||
163 | { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, | ||
164 | {} /* terminator */ | ||
165 | }; | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f0e9a9c90780..98b9f16c26ff 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2174,6 +2174,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2174 | 2174 | ||
2175 | { .modelname = "lg", .config = ALC880_LG }, | 2175 | { .modelname = "lg", .config = ALC880_LG }, |
2176 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, | 2176 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, |
2177 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0068, .config = ALC880_LG }, | ||
2177 | 2178 | ||
2178 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, | 2179 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, |
2179 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, | 2180 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, |
@@ -3105,6 +3106,7 @@ static struct hda_verb alc260_init_verbs[] = { | |||
3105 | { } | 3106 | { } |
3106 | }; | 3107 | }; |
3107 | 3108 | ||
3109 | #if 0 /* should be identical with alc260_init_verbs? */ | ||
3108 | static struct hda_verb alc260_hp_init_verbs[] = { | 3110 | static struct hda_verb alc260_hp_init_verbs[] = { |
3109 | /* Headphone and output */ | 3111 | /* Headphone and output */ |
3110 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | 3112 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, |
@@ -3151,6 +3153,7 @@ static struct hda_verb alc260_hp_init_verbs[] = { | |||
3151 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | 3153 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, |
3152 | { } | 3154 | { } |
3153 | }; | 3155 | }; |
3156 | #endif | ||
3154 | 3157 | ||
3155 | static struct hda_verb alc260_hp_3013_init_verbs[] = { | 3158 | static struct hda_verb alc260_hp_3013_init_verbs[] = { |
3156 | /* Line out and output */ | 3159 | /* Line out and output */ |
@@ -3822,12 +3825,16 @@ static struct hda_board_config alc260_cfg_tbl[] = { | |||
3822 | { .modelname = "basic", .config = ALC260_BASIC }, | 3825 | { .modelname = "basic", .config = ALC260_BASIC }, |
3823 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, | 3826 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, |
3824 | .config = ALC260_BASIC }, /* Sony VAIO */ | 3827 | .config = ALC260_BASIC }, /* Sony VAIO */ |
3828 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cc, | ||
3829 | .config = ALC260_BASIC }, /* Sony VAIO VGN-S3HP */ | ||
3830 | { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cd, | ||
3831 | .config = ALC260_BASIC }, /* Sony VAIO */ | ||
3825 | { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, | 3832 | { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, |
3826 | .config = ALC260_BASIC }, /* CTL Travel Master U553W */ | 3833 | .config = ALC260_BASIC }, /* CTL Travel Master U553W */ |
3827 | { .modelname = "hp", .config = ALC260_HP }, | 3834 | { .modelname = "hp", .config = ALC260_HP }, |
3828 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, | 3835 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, |
3829 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, | 3836 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, |
3830 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP }, | 3837 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, |
3831 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, | 3838 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, |
3832 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP }, | 3839 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP }, |
3833 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP }, | 3840 | { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP }, |
@@ -3862,7 +3869,7 @@ static struct alc_config_preset alc260_presets[] = { | |||
3862 | .mixers = { alc260_base_output_mixer, | 3869 | .mixers = { alc260_base_output_mixer, |
3863 | alc260_input_mixer, | 3870 | alc260_input_mixer, |
3864 | alc260_capture_alt_mixer }, | 3871 | alc260_capture_alt_mixer }, |
3865 | .init_verbs = { alc260_hp_init_verbs }, | 3872 | .init_verbs = { alc260_init_verbs }, |
3866 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), | 3873 | .num_dacs = ARRAY_SIZE(alc260_dac_nids), |
3867 | .dac_nids = alc260_dac_nids, | 3874 | .dac_nids = alc260_dac_nids, |
3868 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), | 3875 | .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids), |
@@ -4094,21 +4101,6 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { | |||
4094 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | 4101 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), |
4095 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | 4102 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), |
4096 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | 4103 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), |
4097 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | ||
4098 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | ||
4099 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | ||
4100 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | ||
4101 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | ||
4102 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | ||
4103 | { | ||
4104 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
4105 | /* .name = "Capture Source", */ | ||
4106 | .name = "Input Source", | ||
4107 | .count = 3, | ||
4108 | .info = alc882_mux_enum_info, | ||
4109 | .get = alc882_mux_enum_get, | ||
4110 | .put = alc882_mux_enum_put, | ||
4111 | }, | ||
4112 | { } /* end */ | 4104 | { } /* end */ |
4113 | }; | 4105 | }; |
4114 | 4106 | ||
@@ -4342,8 +4334,6 @@ static struct alc_config_preset alc882_presets[] = { | |||
4342 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | 4334 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), |
4343 | .dac_nids = alc882_dac_nids, | 4335 | .dac_nids = alc882_dac_nids, |
4344 | .dig_out_nid = ALC882_DIGOUT_NID, | 4336 | .dig_out_nid = ALC882_DIGOUT_NID, |
4345 | .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), | ||
4346 | .adc_nids = alc882_adc_nids, | ||
4347 | .dig_in_nid = ALC882_DIGIN_NID, | 4337 | .dig_in_nid = ALC882_DIGIN_NID, |
4348 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), | 4338 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), |
4349 | .channel_mode = alc882_ch_modes, | 4339 | .channel_mode = alc882_ch_modes, |
@@ -4355,8 +4345,6 @@ static struct alc_config_preset alc882_presets[] = { | |||
4355 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | 4345 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), |
4356 | .dac_nids = alc882_dac_nids, | 4346 | .dac_nids = alc882_dac_nids, |
4357 | .dig_out_nid = ALC882_DIGOUT_NID, | 4347 | .dig_out_nid = ALC882_DIGOUT_NID, |
4358 | .num_adc_nids = ARRAY_SIZE(alc882_adc_nids), | ||
4359 | .adc_nids = alc882_adc_nids, | ||
4360 | .dig_in_nid = ALC882_DIGIN_NID, | 4348 | .dig_in_nid = ALC882_DIGIN_NID, |
4361 | .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), | 4349 | .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), |
4362 | .channel_mode = alc882_sixstack_modes, | 4350 | .channel_mode = alc882_sixstack_modes, |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 8c440fb98603..36f199442fdc 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #define STAC_REF 0 | 41 | #define STAC_REF 0 |
42 | #define STAC_D945GTP3 1 | 42 | #define STAC_D945GTP3 1 |
43 | #define STAC_D945GTP5 2 | 43 | #define STAC_D945GTP5 2 |
44 | #define STAC_MACMINI 3 | ||
44 | 45 | ||
45 | struct sigmatel_spec { | 46 | struct sigmatel_spec { |
46 | struct snd_kcontrol_new *mixers[4]; | 47 | struct snd_kcontrol_new *mixers[4]; |
@@ -52,6 +53,7 @@ struct sigmatel_spec { | |||
52 | unsigned int mic_switch: 1; | 53 | unsigned int mic_switch: 1; |
53 | unsigned int alt_switch: 1; | 54 | unsigned int alt_switch: 1; |
54 | unsigned int hp_detect: 1; | 55 | unsigned int hp_detect: 1; |
56 | unsigned int gpio_mute: 1; | ||
55 | 57 | ||
56 | /* playback */ | 58 | /* playback */ |
57 | struct hda_multi_out multiout; | 59 | struct hda_multi_out multiout; |
@@ -293,6 +295,7 @@ static unsigned int *stac922x_brd_tbl[] = { | |||
293 | ref922x_pin_configs, | 295 | ref922x_pin_configs, |
294 | d945gtp3_pin_configs, | 296 | d945gtp3_pin_configs, |
295 | d945gtp5_pin_configs, | 297 | d945gtp5_pin_configs, |
298 | NULL, /* STAC_MACMINI */ | ||
296 | }; | 299 | }; |
297 | 300 | ||
298 | static struct hda_board_config stac922x_cfg_tbl[] = { | 301 | static struct hda_board_config stac922x_cfg_tbl[] = { |
@@ -324,6 +327,9 @@ static struct hda_board_config stac922x_cfg_tbl[] = { | |||
324 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, | 327 | { .pci_subvendor = PCI_VENDOR_ID_INTEL, |
325 | .pci_subdevice = 0x0417, | 328 | .pci_subdevice = 0x0417, |
326 | .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ | 329 | .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ |
330 | { .pci_subvendor = 0x8384, | ||
331 | .pci_subdevice = 0x7680, | ||
332 | .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ | ||
327 | {} /* terminator */ | 333 | {} /* terminator */ |
328 | }; | 334 | }; |
329 | 335 | ||
@@ -841,6 +847,19 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
841 | } | 847 | } |
842 | } | 848 | } |
843 | 849 | ||
850 | if (imux->num_items == 1) { | ||
851 | /* | ||
852 | * Set the current input for the muxes. | ||
853 | * The STAC9221 has two input muxes with identical source | ||
854 | * NID lists. Hopefully this won't get confused. | ||
855 | */ | ||
856 | for (i = 0; i < spec->num_muxes; i++) { | ||
857 | snd_hda_codec_write(codec, spec->mux_nids[i], 0, | ||
858 | AC_VERB_SET_CONNECT_SEL, | ||
859 | imux->items[0].index); | ||
860 | } | ||
861 | } | ||
862 | |||
844 | return 0; | 863 | return 0; |
845 | } | 864 | } |
846 | 865 | ||
@@ -946,6 +965,45 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
946 | return 1; | 965 | return 1; |
947 | } | 966 | } |
948 | 967 | ||
968 | /* | ||
969 | * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a | ||
970 | * funky external mute control using GPIO pins. | ||
971 | */ | ||
972 | |||
973 | static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) | ||
974 | { | ||
975 | unsigned int gpiostate, gpiomask, gpiodir; | ||
976 | |||
977 | gpiostate = snd_hda_codec_read(codec, codec->afg, 0, | ||
978 | AC_VERB_GET_GPIO_DATA, 0); | ||
979 | |||
980 | if (!muted) | ||
981 | gpiostate |= (1 << pin); | ||
982 | else | ||
983 | gpiostate &= ~(1 << pin); | ||
984 | |||
985 | gpiomask = snd_hda_codec_read(codec, codec->afg, 0, | ||
986 | AC_VERB_GET_GPIO_MASK, 0); | ||
987 | gpiomask |= (1 << pin); | ||
988 | |||
989 | gpiodir = snd_hda_codec_read(codec, codec->afg, 0, | ||
990 | AC_VERB_GET_GPIO_DIRECTION, 0); | ||
991 | gpiodir |= (1 << pin); | ||
992 | |||
993 | /* AppleHDA seems to do this -- WTF is this verb?? */ | ||
994 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0); | ||
995 | |||
996 | snd_hda_codec_write(codec, codec->afg, 0, | ||
997 | AC_VERB_SET_GPIO_MASK, gpiomask); | ||
998 | snd_hda_codec_write(codec, codec->afg, 0, | ||
999 | AC_VERB_SET_GPIO_DIRECTION, gpiodir); | ||
1000 | |||
1001 | msleep(1); | ||
1002 | |||
1003 | snd_hda_codec_write(codec, codec->afg, 0, | ||
1004 | AC_VERB_SET_GPIO_DATA, gpiostate); | ||
1005 | } | ||
1006 | |||
949 | static int stac92xx_init(struct hda_codec *codec) | 1007 | static int stac92xx_init(struct hda_codec *codec) |
950 | { | 1008 | { |
951 | struct sigmatel_spec *spec = codec->spec; | 1009 | struct sigmatel_spec *spec = codec->spec; |
@@ -982,6 +1040,11 @@ static int stac92xx_init(struct hda_codec *codec) | |||
982 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, | 1040 | stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin, |
983 | AC_PINCTL_IN_EN); | 1041 | AC_PINCTL_IN_EN); |
984 | 1042 | ||
1043 | if (spec->gpio_mute) { | ||
1044 | stac922x_gpio_mute(codec, 0, 0); | ||
1045 | stac922x_gpio_mute(codec, 1, 0); | ||
1046 | } | ||
1047 | |||
985 | return 0; | 1048 | return 0; |
986 | } | 1049 | } |
987 | 1050 | ||
@@ -1132,7 +1195,7 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1132 | spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); | 1195 | spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); |
1133 | if (spec->board_config < 0) | 1196 | if (spec->board_config < 0) |
1134 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n"); | 1197 | snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n"); |
1135 | else { | 1198 | else if (stac922x_brd_tbl[spec->board_config] != NULL) { |
1136 | spec->num_pins = 10; | 1199 | spec->num_pins = 10; |
1137 | spec->pin_nids = stac922x_pin_nids; | 1200 | spec->pin_nids = stac922x_pin_nids; |
1138 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; | 1201 | spec->pin_configs = stac922x_brd_tbl[spec->board_config]; |
@@ -1154,6 +1217,9 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1154 | return err; | 1217 | return err; |
1155 | } | 1218 | } |
1156 | 1219 | ||
1220 | if (spec->board_config == STAC_MACMINI) | ||
1221 | spec->gpio_mute = 1; | ||
1222 | |||
1157 | codec->patch_ops = stac92xx_patch_ops; | 1223 | codec->patch_ops = stac92xx_patch_ops; |
1158 | 1224 | ||
1159 | return 0; | 1225 | return 0; |
@@ -1262,13 +1328,13 @@ static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, | |||
1262 | int change; | 1328 | int change; |
1263 | 1329 | ||
1264 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, | 1330 | change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0, |
1265 | 0x80, valp[0] & 0x80); | 1331 | 0x80, (valp[0] ? 0 : 0x80)); |
1266 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, | 1332 | change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0, |
1267 | 0x80, valp[1] & 0x80); | 1333 | 0x80, (valp[1] ? 0 : 0x80)); |
1268 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, | 1334 | snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0, |
1269 | 0x80, valp[0] & 0x80); | 1335 | 0x80, (valp[0] ? 0 : 0x80)); |
1270 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, | 1336 | snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0, |
1271 | 0x80, valp[1] & 0x80); | 1337 | 0x80, (valp[1] ? 0 : 0x80)); |
1272 | return change; | 1338 | return change; |
1273 | } | 1339 | } |
1274 | 1340 | ||
@@ -1370,6 +1436,12 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
1370 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, | 1436 | { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, |
1371 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, | 1437 | { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, |
1372 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, | 1438 | { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, |
1439 | { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac922x }, | ||
1440 | { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac922x }, | ||
1441 | { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac922x }, | ||
1442 | { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac922x }, | ||
1443 | { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac922x }, | ||
1444 | { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac922x }, | ||
1373 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, | 1445 | { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, |
1374 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, | 1446 | { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, |
1375 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, | 1447 | { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 336dc489aee1..ca74f5b85f42 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
@@ -1281,9 +1281,15 @@ static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable) | |||
1281 | 1281 | ||
1282 | tmp2 = tmp = snd_ice1712_gpio_read(ice); | 1282 | tmp2 = tmp = snd_ice1712_gpio_read(ice); |
1283 | if (enable) | 1283 | if (enable) |
1284 | tmp |= AUREON_HP_SEL; | 1284 | if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) |
1285 | tmp |= AUREON_HP_SEL; | ||
1286 | else | ||
1287 | tmp |= PRODIGY_HP_SEL; | ||
1285 | else | 1288 | else |
1286 | tmp &= ~ AUREON_HP_SEL; | 1289 | if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) |
1290 | tmp &= ~ AUREON_HP_SEL; | ||
1291 | else | ||
1292 | tmp &= ~ PRODIGY_HP_SEL; | ||
1287 | if (tmp != tmp2) { | 1293 | if (tmp != tmp2) { |
1288 | snd_ice1712_gpio_write(ice, tmp); | 1294 | snd_ice1712_gpio_write(ice, tmp); |
1289 | return 1; | 1295 | return 1; |
@@ -2079,16 +2085,16 @@ static unsigned char prodigy71_eeprom[] __devinitdata = { | |||
2079 | }; | 2085 | }; |
2080 | 2086 | ||
2081 | static unsigned char prodigy71lt_eeprom[] __devinitdata = { | 2087 | static unsigned char prodigy71lt_eeprom[] __devinitdata = { |
2082 | 0x0b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */ | 2088 | 0x4b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */ |
2083 | 0x80, /* ACLINK: I2S */ | 2089 | 0x80, /* ACLINK: I2S */ |
2084 | 0xfc, /* I2S: vol, 96k, 24bit, 192k */ | 2090 | 0xfc, /* I2S: vol, 96k, 24bit, 192k */ |
2085 | 0xc3, /* SPDUF: out-en, out-int */ | 2091 | 0xc3, /* SPDIF: out-en, out-int, spdif-in */ |
2086 | 0x00, /* GPIO_DIR */ | 2092 | 0xff, /* GPIO_DIR */ |
2087 | 0x07, /* GPIO_DIR1 */ | 2093 | 0xff, /* GPIO_DIR1 */ |
2088 | 0x00, /* GPIO_DIR2 */ | 2094 | 0x5f, /* GPIO_DIR2 */ |
2089 | 0xff, /* GPIO_MASK */ | 2095 | 0x00, /* GPIO_MASK */ |
2090 | 0xf8, /* GPIO_MASK1 */ | 2096 | 0x00, /* GPIO_MASK1 */ |
2091 | 0xff, /* GPIO_MASK2 */ | 2097 | 0x00, /* GPIO_MASK2 */ |
2092 | 0x00, /* GPIO_STATE */ | 2098 | 0x00, /* GPIO_STATE */ |
2093 | 0x00, /* GPIO_STATE1 */ | 2099 | 0x00, /* GPIO_STATE1 */ |
2094 | 0x00, /* GPIO_STATE2 */ | 2100 | 0x00, /* GPIO_STATE2 */ |
diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h index 98a6752280f2..3b7bea656c57 100644 --- a/sound/pci/ice1712/aureon.h +++ b/sound/pci/ice1712/aureon.h | |||
@@ -58,5 +58,6 @@ extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; | |||
58 | #define PRODIGY_WM_CS (1 << 8) | 58 | #define PRODIGY_WM_CS (1 << 8) |
59 | #define PRODIGY_SPI_MOSI (1 << 10) | 59 | #define PRODIGY_SPI_MOSI (1 << 10) |
60 | #define PRODIGY_SPI_CLK (1 << 9) | 60 | #define PRODIGY_SPI_CLK (1 << 9) |
61 | #define PRODIGY_HP_SEL (1 << 5) | ||
61 | 62 | ||
62 | #endif /* __SOUND_AUREON_H */ | 63 | #endif /* __SOUND_AUREON_H */ |
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c index 2c529e741384..b135389fec6c 100644 --- a/sound/pci/ice1712/ews.c +++ b/sound/pci/ice1712/ews.c | |||
@@ -1031,6 +1031,9 @@ struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = { | |||
1031 | .model = "dmx6fire", | 1031 | .model = "dmx6fire", |
1032 | .chip_init = snd_ice1712_ews_init, | 1032 | .chip_init = snd_ice1712_ews_init, |
1033 | .build_controls = snd_ice1712_ews_add_controls, | 1033 | .build_controls = snd_ice1712_ews_add_controls, |
1034 | .mpu401_1_name = "MIDI-Front DMX6fire", | ||
1035 | .mpu401_2_name = "Wavetable DMX6fire", | ||
1036 | .mpu401_2_info_flags = MPU401_INFO_OUTPUT, | ||
1034 | }, | 1037 | }, |
1035 | { } /* terminator */ | 1038 | { } /* terminator */ |
1036 | }; | 1039 | }; |
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index c56793b381e2..845907159b74 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c | |||
@@ -61,7 +61,6 @@ | |||
61 | #include <sound/core.h> | 61 | #include <sound/core.h> |
62 | #include <sound/cs8427.h> | 62 | #include <sound/cs8427.h> |
63 | #include <sound/info.h> | 63 | #include <sound/info.h> |
64 | #include <sound/mpu401.h> | ||
65 | #include <sound/initval.h> | 64 | #include <sound/initval.h> |
66 | 65 | ||
67 | #include <sound/asoundef.h> | 66 | #include <sound/asoundef.h> |
@@ -1596,7 +1595,7 @@ static void __devinit snd_ice1712_proc_init(struct snd_ice1712 * ice) | |||
1596 | struct snd_info_entry *entry; | 1595 | struct snd_info_entry *entry; |
1597 | 1596 | ||
1598 | if (! snd_card_proc_new(ice->card, "ice1712", &entry)) | 1597 | if (! snd_card_proc_new(ice->card, "ice1712", &entry)) |
1599 | snd_info_set_text_ops(entry, ice, 1024, snd_ice1712_proc_read); | 1598 | snd_info_set_text_ops(entry, ice, snd_ice1712_proc_read); |
1600 | } | 1599 | } |
1601 | 1600 | ||
1602 | /* | 1601 | /* |
@@ -2398,13 +2397,14 @@ static int __devinit snd_ice1712_chip_init(struct snd_ice1712 *ice) | |||
2398 | udelay(200); | 2397 | udelay(200); |
2399 | outb(ICE1712_NATIVE, ICEREG(ice, CONTROL)); | 2398 | outb(ICE1712_NATIVE, ICEREG(ice, CONTROL)); |
2400 | udelay(200); | 2399 | udelay(200); |
2401 | if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) { | 2400 | if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && |
2402 | /* Limit active ADCs and DACs to 6; */ | 2401 | !ice->dxr_enable) |
2403 | /* Note: DXR extension not supported */ | 2402 | /* Set eeprom value to limit active ADCs and DACs to 6; |
2404 | pci_write_config_byte(ice->pci, 0x60, 0x2a); | 2403 | * Also disable AC97 as no hardware in standard 6fire card/box |
2405 | } else { | 2404 | * Note: DXR extensions are not currently supported |
2406 | pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); | 2405 | */ |
2407 | } | 2406 | ice->eeprom.data[ICE_EEP1_CODEC] = 0x3a; |
2407 | pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]); | ||
2408 | pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]); | 2408 | pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]); |
2409 | pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]); | 2409 | pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]); |
2410 | pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]); | 2410 | pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]); |
@@ -2737,21 +2737,38 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci, | |||
2737 | 2737 | ||
2738 | if (! c->no_mpu401) { | 2738 | if (! c->no_mpu401) { |
2739 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, | 2739 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, |
2740 | ICEREG(ice, MPU1_CTRL), 1, | 2740 | ICEREG(ice, MPU1_CTRL), |
2741 | (c->mpu401_1_info_flags | | ||
2742 | MPU401_INFO_INTEGRATED), | ||
2741 | ice->irq, 0, | 2743 | ice->irq, 0, |
2742 | &ice->rmidi[0])) < 0) { | 2744 | &ice->rmidi[0])) < 0) { |
2743 | snd_card_free(card); | 2745 | snd_card_free(card); |
2744 | return err; | 2746 | return err; |
2745 | } | 2747 | } |
2746 | 2748 | if (c->mpu401_1_name) | |
2747 | if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) | 2749 | /* Prefered name available in card_info */ |
2750 | snprintf(ice->rmidi[0]->name, | ||
2751 | sizeof(ice->rmidi[0]->name), | ||
2752 | "%s %d", c->mpu401_1_name, card->number); | ||
2753 | |||
2754 | if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) { | ||
2755 | /* 2nd port used */ | ||
2748 | if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, | 2756 | if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712, |
2749 | ICEREG(ice, MPU2_CTRL), 1, | 2757 | ICEREG(ice, MPU2_CTRL), |
2758 | (c->mpu401_2_info_flags | | ||
2759 | MPU401_INFO_INTEGRATED), | ||
2750 | ice->irq, 0, | 2760 | ice->irq, 0, |
2751 | &ice->rmidi[1])) < 0) { | 2761 | &ice->rmidi[1])) < 0) { |
2752 | snd_card_free(card); | 2762 | snd_card_free(card); |
2753 | return err; | 2763 | return err; |
2754 | } | 2764 | } |
2765 | if (c->mpu401_2_name) | ||
2766 | /* Prefered name available in card_info */ | ||
2767 | snprintf(ice->rmidi[1]->name, | ||
2768 | sizeof(ice->rmidi[1]->name), | ||
2769 | "%s %d", c->mpu401_2_name, | ||
2770 | card->number); | ||
2771 | } | ||
2755 | } | 2772 | } |
2756 | 2773 | ||
2757 | snd_ice1712_set_input_clock_source(ice, 0); | 2774 | snd_ice1712_set_input_clock_source(ice, 0); |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 053f8e56fd68..ce27eac40d4e 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/ak4xxx-adda.h> | 29 | #include <sound/ak4xxx-adda.h> |
30 | #include <sound/ak4114.h> | 30 | #include <sound/ak4114.h> |
31 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
32 | #include <sound/mpu401.h> | ||
32 | 33 | ||
33 | 34 | ||
34 | /* | 35 | /* |
@@ -495,6 +496,10 @@ struct snd_ice1712_card_info { | |||
495 | int (*chip_init)(struct snd_ice1712 *); | 496 | int (*chip_init)(struct snd_ice1712 *); |
496 | int (*build_controls)(struct snd_ice1712 *); | 497 | int (*build_controls)(struct snd_ice1712 *); |
497 | unsigned int no_mpu401: 1; | 498 | unsigned int no_mpu401: 1; |
499 | unsigned int mpu401_1_info_flags; | ||
500 | unsigned int mpu401_2_info_flags; | ||
501 | const char *mpu401_1_name; | ||
502 | const char *mpu401_2_name; | ||
498 | unsigned int eeprom_size; | 503 | unsigned int eeprom_size; |
499 | unsigned char *eeprom_data; | 504 | unsigned char *eeprom_data; |
500 | }; | 505 | }; |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index b1c007e022d2..34a58c629f47 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -1293,7 +1293,7 @@ static void __devinit snd_vt1724_proc_init(struct snd_ice1712 * ice) | |||
1293 | struct snd_info_entry *entry; | 1293 | struct snd_info_entry *entry; |
1294 | 1294 | ||
1295 | if (! snd_card_proc_new(ice->card, "ice1724", &entry)) | 1295 | if (! snd_card_proc_new(ice->card, "ice1724", &entry)) |
1296 | snd_info_set_text_ops(entry, ice, 1024, snd_vt1724_proc_read); | 1296 | snd_info_set_text_ops(entry, ice, snd_vt1724_proc_read); |
1297 | } | 1297 | } |
1298 | 1298 | ||
1299 | /* | 1299 | /* |
@@ -2388,7 +2388,8 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci, | |||
2388 | if (! c->no_mpu401) { | 2388 | if (! c->no_mpu401) { |
2389 | if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) { | 2389 | if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) { |
2390 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, | 2390 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712, |
2391 | ICEREG1724(ice, MPU_CTRL), 1, | 2391 | ICEREG1724(ice, MPU_CTRL), |
2392 | MPU401_INFO_INTEGRATED, | ||
2392 | ice->irq, 0, | 2393 | ice->irq, 0, |
2393 | &ice->rmidi[0])) < 0) { | 2394 | &ice->rmidi[0])) < 0) { |
2394 | snd_card_free(card); | 2395 | snd_card_free(card); |
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c index d23fb3fc2133..0efcad9260a5 100644 --- a/sound/pci/ice1712/pontis.c +++ b/sound/pci/ice1712/pontis.c | |||
@@ -680,9 +680,8 @@ static void wm_proc_init(struct snd_ice1712 *ice) | |||
680 | { | 680 | { |
681 | struct snd_info_entry *entry; | 681 | struct snd_info_entry *entry; |
682 | if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) { | 682 | if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) { |
683 | snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read); | 683 | snd_info_set_text_ops(entry, ice, wm_proc_regs_read); |
684 | entry->mode |= S_IWUSR; | 684 | entry->mode |= S_IWUSR; |
685 | entry->c.text.write_size = 1024; | ||
686 | entry->c.text.write = wm_proc_regs_write; | 685 | entry->c.text.write = wm_proc_regs_write; |
687 | } | 686 | } |
688 | } | 687 | } |
@@ -705,9 +704,8 @@ static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buff | |||
705 | static void cs_proc_init(struct snd_ice1712 *ice) | 704 | static void cs_proc_init(struct snd_ice1712 *ice) |
706 | { | 705 | { |
707 | struct snd_info_entry *entry; | 706 | struct snd_info_entry *entry; |
708 | if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) { | 707 | if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) |
709 | snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read); | 708 | snd_info_set_text_ops(entry, ice, cs_proc_regs_read); |
710 | } | ||
711 | } | 709 | } |
712 | 710 | ||
713 | 711 | ||
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 0df7602568e2..edc14475ef82 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -66,7 +66,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," | |||
66 | 66 | ||
67 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ | 67 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ |
68 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ | 68 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ |
69 | static int ac97_clock = 0; | 69 | static int ac97_clock; |
70 | static char *ac97_quirk; | 70 | static char *ac97_quirk; |
71 | static int buggy_semaphore; | 71 | static int buggy_semaphore; |
72 | static int buggy_irq = -1; /* auto-check */ | 72 | static int buggy_irq = -1; /* auto-check */ |
@@ -1807,6 +1807,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { | |||
1807 | }, | 1807 | }, |
1808 | { | 1808 | { |
1809 | .subvendor = 0x1028, | 1809 | .subvendor = 0x1028, |
1810 | .subdevice = 0x014e, | ||
1811 | .name = "Dell D800", /* STAC9750/51 */ | ||
1812 | .type = AC97_TUNE_HP_ONLY | ||
1813 | }, | ||
1814 | { | ||
1815 | .subvendor = 0x1028, | ||
1810 | .subdevice = 0x0163, | 1816 | .subdevice = 0x0163, |
1811 | .name = "Dell Unknown", /* STAC9750/51 */ | 1817 | .name = "Dell Unknown", /* STAC9750/51 */ |
1812 | .type = AC97_TUNE_HP_ONLY | 1818 | .type = AC97_TUNE_HP_ONLY |
@@ -2645,7 +2651,7 @@ static void __devinit snd_intel8x0_proc_init(struct intel8x0 * chip) | |||
2645 | struct snd_info_entry *entry; | 2651 | struct snd_info_entry *entry; |
2646 | 2652 | ||
2647 | if (! snd_card_proc_new(chip->card, "intel8x0", &entry)) | 2653 | if (! snd_card_proc_new(chip->card, "intel8x0", &entry)) |
2648 | snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0_proc_read); | 2654 | snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read); |
2649 | } | 2655 | } |
2650 | #else | 2656 | #else |
2651 | #define snd_intel8x0_proc_init(x) | 2657 | #define snd_intel8x0_proc_init(x) |
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 720635f0cb81..24703d75b65a 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -59,7 +59,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH}," | |||
59 | 59 | ||
60 | static int index = -2; /* Exclude the first card */ | 60 | static int index = -2; /* Exclude the first card */ |
61 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ | 61 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ |
62 | static int ac97_clock = 0; | 62 | static int ac97_clock; |
63 | 63 | ||
64 | module_param(index, int, 0444); | 64 | module_param(index, int, 0444); |
65 | MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard."); | 65 | MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard."); |
@@ -1092,7 +1092,7 @@ static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip) | |||
1092 | struct snd_info_entry *entry; | 1092 | struct snd_info_entry *entry; |
1093 | 1093 | ||
1094 | if (! snd_card_proc_new(chip->card, "intel8x0m", &entry)) | 1094 | if (! snd_card_proc_new(chip->card, "intel8x0m", &entry)) |
1095 | snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0m_proc_read); | 1095 | snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read); |
1096 | } | 1096 | } |
1097 | #else /* !CONFIG_PROC_FS */ | 1097 | #else /* !CONFIG_PROC_FS */ |
1098 | #define snd_intel8x0m_proc_init(chip) | 1098 | #define snd_intel8x0m_proc_init(chip) |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index e39fad1a4200..6e97932de34f 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
@@ -2085,7 +2085,7 @@ static void __devinit snd_korg1212_proc_init(struct snd_korg1212 *korg1212) | |||
2085 | struct snd_info_entry *entry; | 2085 | struct snd_info_entry *entry; |
2086 | 2086 | ||
2087 | if (! snd_card_proc_new(korg1212->card, "korg1212", &entry)) | 2087 | if (! snd_card_proc_new(korg1212->card, "korg1212", &entry)) |
2088 | snd_info_set_text_ops(entry, korg1212, 1024, snd_korg1212_proc_read); | 2088 | snd_info_set_text_ops(entry, korg1212, snd_korg1212_proc_read); |
2089 | } | 2089 | } |
2090 | 2090 | ||
2091 | static int | 2091 | static int |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index 1928e06b6d82..1c344fbd964d 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
@@ -2861,7 +2861,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
2861 | #if 0 /* TODO: not supported yet */ | 2861 | #if 0 /* TODO: not supported yet */ |
2862 | /* TODO enable MIDI IRQ and I/O */ | 2862 | /* TODO enable MIDI IRQ and I/O */ |
2863 | err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, | 2863 | err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401, |
2864 | chip->iobase + MPU401_DATA_PORT, 1, | 2864 | chip->iobase + MPU401_DATA_PORT, |
2865 | MPU401_INFO_INTEGRATED, | ||
2865 | chip->irq, 0, &chip->rmidi); | 2866 | chip->irq, 0, &chip->rmidi); |
2866 | if (err < 0) | 2867 | if (err < 0) |
2867 | printk(KERN_WARNING "maestro3: no MIDI support.\n"); | 2868 | printk(KERN_WARNING "maestro3: no MIDI support.\n"); |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index 09cc0786495a..366c4a7e65c6 100644 --- a/sound/pci/mixart/mixart.c +++ b/sound/pci/mixart/mixart.c | |||
@@ -1244,7 +1244,6 @@ static void __devinit snd_mixart_proc_init(struct snd_mixart *chip) | |||
1244 | /* text interface to read perf and temp meters */ | 1244 | /* text interface to read perf and temp meters */ |
1245 | if (! snd_card_proc_new(chip->card, "board_info", &entry)) { | 1245 | if (! snd_card_proc_new(chip->card, "board_info", &entry)) { |
1246 | entry->private_data = chip; | 1246 | entry->private_data = chip; |
1247 | entry->c.text.read_size = 1024; | ||
1248 | entry->c.text.read = snd_mixart_proc_read; | 1247 | entry->c.text.read = snd_mixart_proc_read; |
1249 | } | 1248 | } |
1250 | 1249 | ||
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index dafa2235abaa..8198884b51ee 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1150,9 +1150,9 @@ static void __devinit pcxhr_proc_init(struct snd_pcxhr *chip) | |||
1150 | struct snd_info_entry *entry; | 1150 | struct snd_info_entry *entry; |
1151 | 1151 | ||
1152 | if (! snd_card_proc_new(chip->card, "info", &entry)) | 1152 | if (! snd_card_proc_new(chip->card, "info", &entry)) |
1153 | snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_info); | 1153 | snd_info_set_text_ops(entry, chip, pcxhr_proc_info); |
1154 | if (! snd_card_proc_new(chip->card, "sync", &entry)) | 1154 | if (! snd_card_proc_new(chip->card, "sync", &entry)) |
1155 | snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_sync); | 1155 | snd_info_set_text_ops(entry, chip, pcxhr_proc_sync); |
1156 | } | 1156 | } |
1157 | /* end of proc interface */ | 1157 | /* end of proc interface */ |
1158 | 1158 | ||
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index d8cc985d7241..5618ec9740bd 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
@@ -1836,11 +1836,11 @@ static int snd_riptide_free(struct snd_riptide *chip) | |||
1836 | UNSET_GRESET(cif->hwport); | 1836 | UNSET_GRESET(cif->hwport); |
1837 | kfree(chip->cif); | 1837 | kfree(chip->cif); |
1838 | } | 1838 | } |
1839 | if (chip->irq >= 0) | ||
1840 | free_irq(chip->irq, chip); | ||
1839 | if (chip->fw_entry) | 1841 | if (chip->fw_entry) |
1840 | release_firmware(chip->fw_entry); | 1842 | release_firmware(chip->fw_entry); |
1841 | release_and_free_resource(chip->res_port); | 1843 | release_and_free_resource(chip->res_port); |
1842 | if (chip->irq >= 0) | ||
1843 | free_irq(chip->irq, chip); | ||
1844 | kfree(chip); | 1844 | kfree(chip); |
1845 | return 0; | 1845 | return 0; |
1846 | } | 1846 | } |
@@ -1992,7 +1992,7 @@ static void __devinit snd_riptide_proc_init(struct snd_riptide *chip) | |||
1992 | struct snd_info_entry *entry; | 1992 | struct snd_info_entry *entry; |
1993 | 1993 | ||
1994 | if (!snd_card_proc_new(chip->card, "riptide", &entry)) | 1994 | if (!snd_card_proc_new(chip->card, "riptide", &entry)) |
1995 | snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read); | 1995 | snd_info_set_text_ops(entry, chip, snd_riptide_proc_read); |
1996 | } | 1996 | } |
1997 | 1997 | ||
1998 | static int __devinit snd_riptide_mixer(struct snd_riptide *chip) | 1998 | static int __devinit snd_riptide_mixer(struct snd_riptide *chip) |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 55b1d4838d97..2cb9fe98db2f 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -1368,18 +1368,18 @@ static int __devinit snd_rme32_create(struct rme32 * rme32) | |||
1368 | return err; | 1368 | return err; |
1369 | rme32->port = pci_resource_start(rme32->pci, 0); | 1369 | rme32->port = pci_resource_start(rme32->pci, 0); |
1370 | 1370 | ||
1371 | if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) { | ||
1372 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | ||
1373 | return -EBUSY; | ||
1374 | } | ||
1375 | rme32->irq = pci->irq; | ||
1376 | |||
1377 | if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) { | 1371 | if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) { |
1378 | snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", | 1372 | snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", |
1379 | rme32->port, rme32->port + RME32_IO_SIZE - 1); | 1373 | rme32->port, rme32->port + RME32_IO_SIZE - 1); |
1380 | return -ENOMEM; | 1374 | return -ENOMEM; |
1381 | } | 1375 | } |
1382 | 1376 | ||
1377 | if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) { | ||
1378 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | ||
1379 | return -EBUSY; | ||
1380 | } | ||
1381 | rme32->irq = pci->irq; | ||
1382 | |||
1383 | /* read the card's revision number */ | 1383 | /* read the card's revision number */ |
1384 | pci_read_config_byte(pci, 8, &rme32->rev); | 1384 | pci_read_config_byte(pci, 8, &rme32->rev); |
1385 | 1385 | ||
@@ -1578,7 +1578,7 @@ static void __devinit snd_rme32_proc_init(struct rme32 * rme32) | |||
1578 | struct snd_info_entry *entry; | 1578 | struct snd_info_entry *entry; |
1579 | 1579 | ||
1580 | if (! snd_card_proc_new(rme32->card, "rme32", &entry)) | 1580 | if (! snd_card_proc_new(rme32->card, "rme32", &entry)) |
1581 | snd_info_set_text_ops(entry, rme32, 1024, snd_rme32_proc_read); | 1581 | snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read); |
1582 | } | 1582 | } |
1583 | 1583 | ||
1584 | /* | 1584 | /* |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 3c1bc533d511..991cb18c14f3 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -1151,6 +1151,25 @@ static struct snd_pcm_hw_constraint_list hw_constraints_period_bytes = { | |||
1151 | .mask = 0 | 1151 | .mask = 0 |
1152 | }; | 1152 | }; |
1153 | 1153 | ||
1154 | static void | ||
1155 | rme96_set_buffer_size_constraint(struct rme96 *rme96, | ||
1156 | struct snd_pcm_runtime *runtime) | ||
1157 | { | ||
1158 | unsigned int size; | ||
1159 | |||
1160 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | ||
1161 | RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); | ||
1162 | if ((size = rme96->playback_periodsize) != 0 || | ||
1163 | (size = rme96->capture_periodsize) != 0) | ||
1164 | snd_pcm_hw_constraint_minmax(runtime, | ||
1165 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | ||
1166 | size, size); | ||
1167 | else | ||
1168 | snd_pcm_hw_constraint_list(runtime, 0, | ||
1169 | SNDRV_PCM_HW_PARAM_PERIOD_BYTES, | ||
1170 | &hw_constraints_period_bytes); | ||
1171 | } | ||
1172 | |||
1154 | static int | 1173 | static int |
1155 | snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) | 1174 | snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) |
1156 | { | 1175 | { |
@@ -1180,8 +1199,7 @@ snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream) | |||
1180 | runtime->hw.rate_min = rate; | 1199 | runtime->hw.rate_min = rate; |
1181 | runtime->hw.rate_max = rate; | 1200 | runtime->hw.rate_max = rate; |
1182 | } | 1201 | } |
1183 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); | 1202 | rme96_set_buffer_size_constraint(rme96, runtime); |
1184 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); | ||
1185 | 1203 | ||
1186 | rme96->wcreg_spdif_stream = rme96->wcreg_spdif; | 1204 | rme96->wcreg_spdif_stream = rme96->wcreg_spdif; |
1187 | rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | 1205 | rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; |
@@ -1219,9 +1237,7 @@ snd_rme96_capture_spdif_open(struct snd_pcm_substream *substream) | |||
1219 | rme96->capture_substream = substream; | 1237 | rme96->capture_substream = substream; |
1220 | spin_unlock_irq(&rme96->lock); | 1238 | spin_unlock_irq(&rme96->lock); |
1221 | 1239 | ||
1222 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); | 1240 | rme96_set_buffer_size_constraint(rme96, runtime); |
1223 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); | ||
1224 | |||
1225 | return 0; | 1241 | return 0; |
1226 | } | 1242 | } |
1227 | 1243 | ||
@@ -1254,8 +1270,7 @@ snd_rme96_playback_adat_open(struct snd_pcm_substream *substream) | |||
1254 | runtime->hw.rate_min = rate; | 1270 | runtime->hw.rate_min = rate; |
1255 | runtime->hw.rate_max = rate; | 1271 | runtime->hw.rate_max = rate; |
1256 | } | 1272 | } |
1257 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); | 1273 | rme96_set_buffer_size_constraint(rme96, runtime); |
1258 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); | ||
1259 | return 0; | 1274 | return 0; |
1260 | } | 1275 | } |
1261 | 1276 | ||
@@ -1291,8 +1306,7 @@ snd_rme96_capture_adat_open(struct snd_pcm_substream *substream) | |||
1291 | rme96->capture_substream = substream; | 1306 | rme96->capture_substream = substream; |
1292 | spin_unlock_irq(&rme96->lock); | 1307 | spin_unlock_irq(&rme96->lock); |
1293 | 1308 | ||
1294 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE); | 1309 | rme96_set_buffer_size_constraint(rme96, runtime); |
1295 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes); | ||
1296 | return 0; | 1310 | return 0; |
1297 | } | 1311 | } |
1298 | 1312 | ||
@@ -1569,17 +1583,17 @@ snd_rme96_create(struct rme96 *rme96) | |||
1569 | return err; | 1583 | return err; |
1570 | rme96->port = pci_resource_start(rme96->pci, 0); | 1584 | rme96->port = pci_resource_start(rme96->pci, 0); |
1571 | 1585 | ||
1586 | if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) { | ||
1587 | snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); | ||
1588 | return -ENOMEM; | ||
1589 | } | ||
1590 | |||
1572 | if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) { | 1591 | if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) { |
1573 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1592 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1574 | return -EBUSY; | 1593 | return -EBUSY; |
1575 | } | 1594 | } |
1576 | rme96->irq = pci->irq; | 1595 | rme96->irq = pci->irq; |
1577 | 1596 | ||
1578 | if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) { | ||
1579 | snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1); | ||
1580 | return -ENOMEM; | ||
1581 | } | ||
1582 | |||
1583 | /* read the card's revision number */ | 1597 | /* read the card's revision number */ |
1584 | pci_read_config_byte(pci, 8, &rme96->rev); | 1598 | pci_read_config_byte(pci, 8, &rme96->rev); |
1585 | 1599 | ||
@@ -1805,7 +1819,7 @@ snd_rme96_proc_init(struct rme96 *rme96) | |||
1805 | struct snd_info_entry *entry; | 1819 | struct snd_info_entry *entry; |
1806 | 1820 | ||
1807 | if (! snd_card_proc_new(rme96->card, "rme96", &entry)) | 1821 | if (! snd_card_proc_new(rme96->card, "rme96", &entry)) |
1808 | snd_info_set_text_ops(entry, rme96, 1024, snd_rme96_proc_read); | 1822 | snd_info_set_text_ops(entry, rme96, snd_rme96_proc_read); |
1809 | } | 1823 | } |
1810 | 1824 | ||
1811 | /* | 1825 | /* |
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c index 61f82f0d5cc6..eaf3c22449ad 100644 --- a/sound/pci/rme9652/hdsp.c +++ b/sound/pci/rme9652/hdsp.c | |||
@@ -389,7 +389,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP}," | |||
389 | 389 | ||
390 | /* use hotplug firmeare loader? */ | 390 | /* use hotplug firmeare loader? */ |
391 | #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) | 391 | #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE) |
392 | #ifndef HDSP_USE_HWDEP_LOADER | 392 | #if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP) |
393 | #define HDSP_FW_LOADER | 393 | #define HDSP_FW_LOADER |
394 | #endif | 394 | #endif |
395 | #endif | 395 | #endif |
@@ -3169,9 +3169,10 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | |||
3169 | char *clock_source; | 3169 | char *clock_source; |
3170 | int x; | 3170 | int x; |
3171 | 3171 | ||
3172 | if (hdsp_check_for_iobox (hdsp)) | 3172 | if (hdsp_check_for_iobox (hdsp)) { |
3173 | snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); | 3173 | snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n"); |
3174 | return; | 3174 | return; |
3175 | } | ||
3175 | 3176 | ||
3176 | if (hdsp_check_for_firmware(hdsp, 0)) { | 3177 | if (hdsp_check_for_firmware(hdsp, 0)) { |
3177 | if (hdsp->state & HDSP_FirmwareCached) { | 3178 | if (hdsp->state & HDSP_FirmwareCached) { |
@@ -3470,7 +3471,7 @@ static void __devinit snd_hdsp_proc_init(struct hdsp *hdsp) | |||
3470 | struct snd_info_entry *entry; | 3471 | struct snd_info_entry *entry; |
3471 | 3472 | ||
3472 | if (! snd_card_proc_new(hdsp->card, "hdsp", &entry)) | 3473 | if (! snd_card_proc_new(hdsp->card, "hdsp", &entry)) |
3473 | snd_info_set_text_ops(entry, hdsp, 1024, snd_hdsp_proc_read); | 3474 | snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read); |
3474 | } | 3475 | } |
3475 | 3476 | ||
3476 | static void snd_hdsp_free_buffers(struct hdsp *hdsp) | 3477 | static void snd_hdsp_free_buffers(struct hdsp *hdsp) |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index 722b9e6ce54a..bba1615504d3 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -2489,7 +2489,7 @@ static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) | |||
2489 | struct snd_info_entry *entry; | 2489 | struct snd_info_entry *entry; |
2490 | 2490 | ||
2491 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) | 2491 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) |
2492 | snd_info_set_text_ops(entry, hdspm, 1024, | 2492 | snd_info_set_text_ops(entry, hdspm, |
2493 | snd_hdspm_proc_read); | 2493 | snd_hdspm_proc_read); |
2494 | } | 2494 | } |
2495 | 2495 | ||
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index 75d6406303d3..3b945e8c1b15 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -41,7 +41,7 @@ | |||
41 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 41 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
42 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 42 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
43 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 43 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
44 | static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */ | 44 | static int precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */ |
45 | 45 | ||
46 | module_param_array(index, int, NULL, 0444); | 46 | module_param_array(index, int, NULL, 0444); |
47 | MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard."); | 47 | MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard."); |
@@ -1787,7 +1787,7 @@ static void __devinit snd_rme9652_proc_init(struct snd_rme9652 *rme9652) | |||
1787 | struct snd_info_entry *entry; | 1787 | struct snd_info_entry *entry; |
1788 | 1788 | ||
1789 | if (! snd_card_proc_new(rme9652->card, "rme9652", &entry)) | 1789 | if (! snd_card_proc_new(rme9652->card, "rme9652", &entry)) |
1790 | snd_info_set_text_ops(entry, rme9652, 1024, snd_rme9652_proc_read); | 1790 | snd_info_set_text_ops(entry, rme9652, snd_rme9652_proc_read); |
1791 | } | 1791 | } |
1792 | 1792 | ||
1793 | static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652) | 1793 | static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652) |
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c index 91f8bf3ae9fa..dcf402948347 100644 --- a/sound/pci/sonicvibes.c +++ b/sound/pci/sonicvibes.c | |||
@@ -54,8 +54,8 @@ MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}"); | |||
54 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 54 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
55 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 55 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
56 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ | 56 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ |
57 | static int reverb[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 57 | static int reverb[SNDRV_CARDS]; |
58 | static int mge[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; | 58 | static int mge[SNDRV_CARDS]; |
59 | static unsigned int dmaio = 0x7a00; /* DDMA i/o address */ | 59 | static unsigned int dmaio = 0x7a00; /* DDMA i/o address */ |
60 | 60 | ||
61 | module_param_array(index, int, NULL, 0444); | 61 | module_param_array(index, int, NULL, 0444); |
@@ -1144,7 +1144,7 @@ static void __devinit snd_sonicvibes_proc_init(struct sonicvibes * sonic) | |||
1144 | struct snd_info_entry *entry; | 1144 | struct snd_info_entry *entry; |
1145 | 1145 | ||
1146 | if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry)) | 1146 | if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry)) |
1147 | snd_info_set_text_ops(entry, sonic, 1024, snd_sonicvibes_proc_read); | 1147 | snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read); |
1148 | } | 1148 | } |
1149 | 1149 | ||
1150 | /* | 1150 | /* |
@@ -1456,7 +1456,7 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci, | |||
1456 | return err; | 1456 | return err; |
1457 | } | 1457 | } |
1458 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, | 1458 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES, |
1459 | sonic->midi_port, 1, | 1459 | sonic->midi_port, MPU401_INFO_INTEGRATED, |
1460 | sonic->irq, 0, | 1460 | sonic->irq, 0, |
1461 | &midi_uart)) < 0) { | 1461 | &midi_uart)) < 0) { |
1462 | snd_card_free(card); | 1462 | snd_card_free(card); |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index 9624a5f2b875..5629b7eba96d 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
@@ -148,7 +148,8 @@ static int __devinit snd_trident_probe(struct pci_dev *pci, | |||
148 | } | 148 | } |
149 | if (trident->device != TRIDENT_DEVICE_ID_SI7018 && | 149 | if (trident->device != TRIDENT_DEVICE_ID_SI7018 && |
150 | (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, | 150 | (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE, |
151 | trident->midi_port, 1, | 151 | trident->midi_port, |
152 | MPU401_INFO_INTEGRATED, | ||
152 | trident->irq, 0, &trident->rmidi)) < 0) { | 153 | trident->irq, 0, &trident->rmidi)) < 0) { |
153 | snd_card_free(card); | 154 | snd_card_free(card); |
154 | return err; | 155 | return err; |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 52178b8ad49d..d99ed7237750 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
@@ -306,6 +306,8 @@ void snd_trident_start_voice(struct snd_trident * trident, unsigned int voice) | |||
306 | outl(mask, TRID_REG(trident, reg)); | 306 | outl(mask, TRID_REG(trident, reg)); |
307 | } | 307 | } |
308 | 308 | ||
309 | EXPORT_SYMBOL(snd_trident_start_voice); | ||
310 | |||
309 | /*--------------------------------------------------------------------------- | 311 | /*--------------------------------------------------------------------------- |
310 | void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) | 312 | void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) |
311 | 313 | ||
@@ -328,6 +330,8 @@ void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice) | |||
328 | outl(mask, TRID_REG(trident, reg)); | 330 | outl(mask, TRID_REG(trident, reg)); |
329 | } | 331 | } |
330 | 332 | ||
333 | EXPORT_SYMBOL(snd_trident_stop_voice); | ||
334 | |||
331 | /*--------------------------------------------------------------------------- | 335 | /*--------------------------------------------------------------------------- |
332 | int snd_trident_allocate_pcm_channel(struct snd_trident *trident) | 336 | int snd_trident_allocate_pcm_channel(struct snd_trident *trident) |
333 | 337 | ||
@@ -502,6 +506,8 @@ void snd_trident_write_voice_regs(struct snd_trident * trident, | |||
502 | #endif | 506 | #endif |
503 | } | 507 | } |
504 | 508 | ||
509 | EXPORT_SYMBOL(snd_trident_write_voice_regs); | ||
510 | |||
505 | /*--------------------------------------------------------------------------- | 511 | /*--------------------------------------------------------------------------- |
506 | snd_trident_write_cso_reg | 512 | snd_trident_write_cso_reg |
507 | 513 | ||
@@ -3332,7 +3338,7 @@ static void __devinit snd_trident_proc_init(struct snd_trident * trident) | |||
3332 | if (trident->device == TRIDENT_DEVICE_ID_SI7018) | 3338 | if (trident->device == TRIDENT_DEVICE_ID_SI7018) |
3333 | s = "sis7018"; | 3339 | s = "sis7018"; |
3334 | if (! snd_card_proc_new(trident->card, s, &entry)) | 3340 | if (! snd_card_proc_new(trident->card, s, &entry)) |
3335 | snd_info_set_text_ops(entry, trident, 1024, snd_trident_proc_read); | 3341 | snd_info_set_text_ops(entry, trident, snd_trident_proc_read); |
3336 | } | 3342 | } |
3337 | 3343 | ||
3338 | static int snd_trident_dev_free(struct snd_device *device) | 3344 | static int snd_trident_dev_free(struct snd_device *device) |
@@ -3884,6 +3890,8 @@ struct snd_trident_voice *snd_trident_alloc_voice(struct snd_trident * trident, | |||
3884 | return NULL; | 3890 | return NULL; |
3885 | } | 3891 | } |
3886 | 3892 | ||
3893 | EXPORT_SYMBOL(snd_trident_alloc_voice); | ||
3894 | |||
3887 | void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice) | 3895 | void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice) |
3888 | { | 3896 | { |
3889 | unsigned long flags; | 3897 | unsigned long flags; |
@@ -3912,6 +3920,8 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi | |||
3912 | private_free(voice); | 3920 | private_free(voice); |
3913 | } | 3921 | } |
3914 | 3922 | ||
3923 | EXPORT_SYMBOL(snd_trident_free_voice); | ||
3924 | |||
3915 | static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max) | 3925 | static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max) |
3916 | { | 3926 | { |
3917 | unsigned int i, val, mask[2] = { 0, 0 }; | 3927 | unsigned int i, val, mask[2] = { 0, 0 }; |
@@ -3993,13 +4003,3 @@ int snd_trident_resume(struct pci_dev *pci) | |||
3993 | return 0; | 4003 | return 0; |
3994 | } | 4004 | } |
3995 | #endif /* CONFIG_PM */ | 4005 | #endif /* CONFIG_PM */ |
3996 | |||
3997 | EXPORT_SYMBOL(snd_trident_alloc_voice); | ||
3998 | EXPORT_SYMBOL(snd_trident_free_voice); | ||
3999 | EXPORT_SYMBOL(snd_trident_start_voice); | ||
4000 | EXPORT_SYMBOL(snd_trident_stop_voice); | ||
4001 | EXPORT_SYMBOL(snd_trident_write_voice_regs); | ||
4002 | /* trident_memory.c symbols */ | ||
4003 | EXPORT_SYMBOL(snd_trident_synth_alloc); | ||
4004 | EXPORT_SYMBOL(snd_trident_synth_free); | ||
4005 | EXPORT_SYMBOL(snd_trident_synth_copy_from_user); | ||
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c index 46c6982c9e88..aff3f874131c 100644 --- a/sound/pci/trident/trident_memory.c +++ b/sound/pci/trident/trident_memory.c | |||
@@ -349,6 +349,7 @@ snd_trident_synth_alloc(struct snd_trident *hw, unsigned int size) | |||
349 | return blk; | 349 | return blk; |
350 | } | 350 | } |
351 | 351 | ||
352 | EXPORT_SYMBOL(snd_trident_synth_alloc); | ||
352 | 353 | ||
353 | /* | 354 | /* |
354 | * free a synth sample area | 355 | * free a synth sample area |
@@ -365,6 +366,7 @@ snd_trident_synth_free(struct snd_trident *hw, struct snd_util_memblk *blk) | |||
365 | return 0; | 366 | return 0; |
366 | } | 367 | } |
367 | 368 | ||
369 | EXPORT_SYMBOL(snd_trident_synth_free); | ||
368 | 370 | ||
369 | /* | 371 | /* |
370 | * reset TLB entry and free kernel page | 372 | * reset TLB entry and free kernel page |
@@ -486,3 +488,4 @@ int snd_trident_synth_copy_from_user(struct snd_trident *trident, | |||
486 | return 0; | 488 | return 0; |
487 | } | 489 | } |
488 | 490 | ||
491 | EXPORT_SYMBOL(snd_trident_synth_copy_from_user); | ||
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c index cc7af8bc55a0..9b7dee84743b 100644 --- a/sound/pci/trident/trident_synth.c +++ b/sound/pci/trident/trident_synth.c | |||
@@ -914,7 +914,9 @@ static int snd_trident_synth_create_port(struct snd_trident * trident, int idx) | |||
914 | &callbacks, | 914 | &callbacks, |
915 | SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, | 915 | SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE, |
916 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | | 916 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE | |
917 | SNDRV_SEQ_PORT_TYPE_SYNTH, | 917 | SNDRV_SEQ_PORT_TYPE_SYNTH | |
918 | SNDRV_SEQ_PORT_TYPE_HARDWARE | | ||
919 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER, | ||
918 | 16, 0, | 920 | 16, 0, |
919 | name); | 921 | name); |
920 | if (p->chset->port < 0) { | 922 | if (p->chset->port < 0) { |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 39daf62d2bad..2527bbd958c5 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -1775,6 +1775,12 @@ static struct ac97_quirk ac97_quirks[] = { | |||
1775 | .name = "Targa Traveller 811", | 1775 | .name = "Targa Traveller 811", |
1776 | .type = AC97_TUNE_HP_ONLY, | 1776 | .type = AC97_TUNE_HP_ONLY, |
1777 | }, | 1777 | }, |
1778 | { | ||
1779 | .subvendor = 0x161f, | ||
1780 | .subdevice = 0x2032, | ||
1781 | .name = "m680x", | ||
1782 | .type = AC97_TUNE_HP_ONLY, /* http://launchpad.net/bugs/38546 */ | ||
1783 | }, | ||
1778 | { } /* terminator */ | 1784 | { } /* terminator */ |
1779 | }; | 1785 | }; |
1780 | 1786 | ||
@@ -1973,7 +1979,7 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip) | |||
1973 | pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); | 1979 | pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg); |
1974 | if (chip->mpu_res) { | 1980 | if (chip->mpu_res) { |
1975 | if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, | 1981 | if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A, |
1976 | mpu_port, 1, | 1982 | mpu_port, MPU401_INFO_INTEGRATED, |
1977 | chip->irq, 0, &chip->rmidi) < 0) { | 1983 | chip->irq, 0, &chip->rmidi) < 0) { |
1978 | printk(KERN_WARNING "unable to initialize MPU-401" | 1984 | printk(KERN_WARNING "unable to initialize MPU-401" |
1979 | " at 0x%lx, skipping\n", mpu_port); | 1985 | " at 0x%lx, skipping\n", mpu_port); |
@@ -2015,7 +2021,7 @@ static void __devinit snd_via82xx_proc_init(struct via82xx *chip) | |||
2015 | struct snd_info_entry *entry; | 2021 | struct snd_info_entry *entry; |
2016 | 2022 | ||
2017 | if (! snd_card_proc_new(chip->card, "via82xx", &entry)) | 2023 | if (! snd_card_proc_new(chip->card, "via82xx", &entry)) |
2018 | snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read); | 2024 | snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read); |
2019 | } | 2025 | } |
2020 | 2026 | ||
2021 | /* | 2027 | /* |
@@ -2365,7 +2371,7 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision) | |||
2365 | { .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */ | 2371 | { .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */ |
2366 | { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ | 2372 | { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */ |
2367 | { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ | 2373 | { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */ |
2368 | { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */ | 2374 | { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_SRC }, /* MSI K8T Neo2-FI */ |
2369 | { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ | 2375 | { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */ |
2370 | { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */ | 2376 | { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */ |
2371 | { .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */ | 2377 | { .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */ |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index ef97e50cd6c2..577a2b03759f 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -929,7 +929,7 @@ static void __devinit snd_via82xx_proc_init(struct via82xx_modem *chip) | |||
929 | struct snd_info_entry *entry; | 929 | struct snd_info_entry *entry; |
930 | 930 | ||
931 | if (! snd_card_proc_new(chip->card, "via82xx", &entry)) | 931 | if (! snd_card_proc_new(chip->card, "via82xx", &entry)) |
932 | snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read); | 932 | snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read); |
933 | } | 933 | } |
934 | 934 | ||
935 | /* | 935 | /* |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 65ebf5f1933a..26aa775b7b69 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
@@ -308,7 +308,8 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, | |||
308 | } | 308 | } |
309 | if (chip->mpu_res) { | 309 | if (chip->mpu_res) { |
310 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, | 310 | if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, |
311 | mpu_port[dev], 1, | 311 | mpu_port[dev], |
312 | MPU401_INFO_INTEGRATED, | ||
312 | pci->irq, 0, &chip->rawmidi)) < 0) { | 313 | pci->irq, 0, &chip->rawmidi)) < 0) { |
313 | printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); | 314 | printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); |
314 | legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ | 315 | legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 8ac5ab50b5c7..f894752523bb 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
@@ -1919,7 +1919,7 @@ static int __devinit snd_ymfpci_proc_init(struct snd_card *card, struct snd_ymfp | |||
1919 | struct snd_info_entry *entry; | 1919 | struct snd_info_entry *entry; |
1920 | 1920 | ||
1921 | if (! snd_card_proc_new(card, "ymfpci", &entry)) | 1921 | if (! snd_card_proc_new(card, "ymfpci", &entry)) |
1922 | snd_info_set_text_ops(entry, chip, 1024, snd_ymfpci_proc_read); | 1922 | snd_info_set_text_ops(entry, chip, snd_ymfpci_proc_read); |
1923 | return 0; | 1923 | return 0; |
1924 | } | 1924 | } |
1925 | 1925 | ||
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c index bd0d70ff3019..1dfe29b863d3 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c | |||
@@ -144,7 +144,7 @@ static void pdacf_proc_init(struct snd_pdacf *chip) | |||
144 | struct snd_info_entry *entry; | 144 | struct snd_info_entry *entry; |
145 | 145 | ||
146 | if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry)) | 146 | if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry)) |
147 | snd_info_set_text_ops(entry, chip, 1024, pdacf_proc_read); | 147 | snd_info_set_text_ops(entry, chip, pdacf_proc_read); |
148 | } | 148 | } |
149 | 149 | ||
150 | struct snd_pdacf *snd_pdacf_create(struct snd_card *card) | 150 | struct snd_pdacf *snd_pdacf_create(struct snd_card *card) |
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 7f82f619f9f4..1ee0918c3b9f 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c | |||
@@ -202,7 +202,7 @@ static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware * | |||
202 | c |= (int)vx_inb(chip, RXM) << 8; | 202 | c |= (int)vx_inb(chip, RXM) << 8; |
203 | c |= vx_inb(chip, RXL); | 203 | c |= vx_inb(chip, RXL); |
204 | 204 | ||
205 | snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%x\n", c, fw->size); | 205 | snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%Zx\n", c, fw->size); |
206 | 206 | ||
207 | vx_outb(chip, ICR, ICR_HF0); | 207 | vx_outb(chip, ICR, ICR_HF0); |
208 | 208 | ||
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 7e0cda2b6ef9..cafe6640cc1a 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
@@ -261,7 +261,7 @@ static int vxpocket_config(struct pcmcia_device *link) | |||
261 | 261 | ||
262 | link->dev_node = &vxp->node; | 262 | link->dev_node = &vxp->node; |
263 | kfree(parse); | 263 | kfree(parse); |
264 | return 9; | 264 | return 0; |
265 | 265 | ||
266 | cs_failed: | 266 | cs_failed: |
267 | cs_error(link, last_fn, last_ret); | 267 | cs_error(link, last_fn, last_ret); |
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile index d6ba9959097b..4d95c652c8ca 100644 --- a/sound/ppc/Makefile +++ b/sound/ppc/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> | 3 | # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> |
4 | # | 4 | # |
5 | 5 | ||
6 | snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o toonie.o keywest.o beep.o | 6 | snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o |
7 | 7 | ||
8 | # Toplevel Module Dependency | 8 | # Toplevel Module Dependency |
9 | obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o | 9 | obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index f0794ef9d1ac..b678814975c9 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -867,8 +867,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) | |||
867 | unsigned int *prop, l; | 867 | unsigned int *prop, l; |
868 | struct macio_chip* macio; | 868 | struct macio_chip* macio; |
869 | 869 | ||
870 | u32 layout_id = 0; | ||
871 | |||
872 | if (!machine_is(powermac)) | 870 | if (!machine_is(powermac)) |
873 | return -ENODEV; | 871 | return -ENODEV; |
874 | 872 | ||
@@ -929,8 +927,14 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) | |||
929 | if (prop && *prop < 16) | 927 | if (prop && *prop < 16) |
930 | chip->subframe = *prop; | 928 | chip->subframe = *prop; |
931 | prop = (unsigned int *) get_property(sound, "layout-id", NULL); | 929 | prop = (unsigned int *) get_property(sound, "layout-id", NULL); |
932 | if (prop) | 930 | if (prop) { |
933 | layout_id = *prop; | 931 | /* partly deprecate snd-powermac, for those machines |
932 | * that have a layout-id property for now */ | ||
933 | printk(KERN_INFO "snd-powermac no longer handles any " | ||
934 | "machines with a layout-id property " | ||
935 | "in the device-tree, use snd-aoa.\n"); | ||
936 | return -ENODEV; | ||
937 | } | ||
934 | /* This should be verified on older screamers */ | 938 | /* This should be verified on older screamers */ |
935 | if (device_is_compatible(sound, "screamer")) { | 939 | if (device_is_compatible(sound, "screamer")) { |
936 | chip->model = PMAC_SCREAMER; | 940 | chip->model = PMAC_SCREAMER; |
@@ -963,38 +967,6 @@ static int __init snd_pmac_detect(struct snd_pmac *chip) | |||
963 | chip->freq_table = tumbler_freqs; | 967 | chip->freq_table = tumbler_freqs; |
964 | chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ | 968 | chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ |
965 | } | 969 | } |
966 | if (device_is_compatible(sound, "AOAKeylargo") || | ||
967 | device_is_compatible(sound, "AOAbase") || | ||
968 | device_is_compatible(sound, "AOAK2")) { | ||
969 | /* For now, only support very basic TAS3004 based machines with | ||
970 | * single frequency until proper i2s control is implemented | ||
971 | */ | ||
972 | switch(layout_id) { | ||
973 | case 0x24: | ||
974 | case 0x29: | ||
975 | case 0x33: | ||
976 | case 0x46: | ||
977 | case 0x48: | ||
978 | case 0x50: | ||
979 | case 0x5c: | ||
980 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); | ||
981 | chip->model = PMAC_SNAPPER; | ||
982 | chip->can_byte_swap = 0; /* FIXME: check this */ | ||
983 | chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */ | ||
984 | break; | ||
985 | case 0x3a: | ||
986 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); | ||
987 | chip->model = PMAC_TOONIE; | ||
988 | chip->can_byte_swap = 0; /* FIXME: check this */ | ||
989 | chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */ | ||
990 | break; | ||
991 | default: | ||
992 | printk(KERN_ERR "snd: Unknown layout ID 0x%x\n", | ||
993 | layout_id); | ||
994 | return -ENODEV; | ||
995 | |||
996 | } | ||
997 | } | ||
998 | prop = (unsigned int *)get_property(sound, "device-id", NULL); | 970 | prop = (unsigned int *)get_property(sound, "device-id", NULL); |
999 | if (prop) | 971 | if (prop) |
1000 | chip->device_id = *prop; | 972 | chip->device_id = *prop; |
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index 3a9bd4dbb9a6..8394e66ceb00 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h | |||
@@ -85,7 +85,7 @@ struct pmac_stream { | |||
85 | 85 | ||
86 | enum snd_pmac_model { | 86 | enum snd_pmac_model { |
87 | PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, | 87 | PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER, |
88 | PMAC_SNAPPER, PMAC_TOONIE | 88 | PMAC_SNAPPER |
89 | }; | 89 | }; |
90 | 90 | ||
91 | struct snd_pmac { | 91 | struct snd_pmac { |
@@ -188,7 +188,6 @@ int snd_pmac_burgundy_init(struct snd_pmac *chip); | |||
188 | int snd_pmac_daca_init(struct snd_pmac *chip); | 188 | int snd_pmac_daca_init(struct snd_pmac *chip); |
189 | int snd_pmac_tumbler_init(struct snd_pmac *chip); | 189 | int snd_pmac_tumbler_init(struct snd_pmac *chip); |
190 | int snd_pmac_tumbler_post_init(void); | 190 | int snd_pmac_tumbler_post_init(void); |
191 | int snd_pmac_toonie_init(struct snd_pmac *chip); | ||
192 | 191 | ||
193 | /* i2c functions */ | 192 | /* i2c functions */ |
194 | struct pmac_keywest { | 193 | struct pmac_keywest { |
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index f4902a219e50..fa9a44ab487e 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c | |||
@@ -94,13 +94,6 @@ static int __init snd_pmac_probe(struct platform_device *devptr) | |||
94 | if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) | 94 | if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) |
95 | goto __error; | 95 | goto __error; |
96 | break; | 96 | break; |
97 | case PMAC_TOONIE: | ||
98 | strcpy(card->driver, "PMac Toonie"); | ||
99 | strcpy(card->shortname, "PowerMac Toonie"); | ||
100 | strcpy(card->longname, card->shortname); | ||
101 | if ((err = snd_pmac_toonie_init(chip)) < 0) | ||
102 | goto __error; | ||
103 | break; | ||
104 | case PMAC_AWACS: | 97 | case PMAC_AWACS: |
105 | case PMAC_SCREAMER: | 98 | case PMAC_SCREAMER: |
106 | name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; | 99 | name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS"; |
@@ -188,11 +181,15 @@ static int __init alsa_card_pmac_init(void) | |||
188 | if ((err = platform_driver_register(&snd_pmac_driver)) < 0) | 181 | if ((err = platform_driver_register(&snd_pmac_driver)) < 0) |
189 | return err; | 182 | return err; |
190 | device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); | 183 | device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); |
191 | if (IS_ERR(device)) { | 184 | if (!IS_ERR(device)) { |
192 | platform_driver_unregister(&snd_pmac_driver); | 185 | if (platform_get_drvdata(device)) |
193 | return PTR_ERR(device); | 186 | return 0; |
194 | } | 187 | platform_device_unregister(device); |
195 | return 0; | 188 | err = -ENODEV; |
189 | } else | ||
190 | err = PTR_ERR(device); | ||
191 | platform_driver_unregister(&snd_pmac_driver); | ||
192 | return err; | ||
196 | 193 | ||
197 | } | 194 | } |
198 | 195 | ||
diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c index 1ac7c8552f50..e69de29bb2d1 100644 --- a/sound/ppc/toonie.c +++ b/sound/ppc/toonie.c | |||
@@ -1,378 +0,0 @@ | |||
1 | /* | ||
2 | * Mac Mini "toonie" mixer control | ||
3 | * | ||
4 | * Copyright (c) 2005 by Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <sound/driver.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/kmod.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <sound/core.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/irq.h> | ||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/pmac_feature.h> | ||
33 | #include "pmac.h" | ||
34 | |||
35 | #undef DEBUG | ||
36 | |||
37 | #ifdef DEBUG | ||
38 | #define DBG(fmt...) printk(fmt) | ||
39 | #else | ||
40 | #define DBG(fmt...) | ||
41 | #endif | ||
42 | |||
43 | struct pmac_gpio { | ||
44 | unsigned int addr; | ||
45 | u8 active_val; | ||
46 | u8 inactive_val; | ||
47 | u8 active_state; | ||
48 | }; | ||
49 | |||
50 | struct pmac_toonie | ||
51 | { | ||
52 | struct pmac_gpio hp_detect_gpio; | ||
53 | struct pmac_gpio hp_mute_gpio; | ||
54 | struct pmac_gpio amp_mute_gpio; | ||
55 | int hp_detect_irq; | ||
56 | int auto_mute_notify; | ||
57 | struct work_struct detect_work; | ||
58 | }; | ||
59 | |||
60 | |||
61 | /* | ||
62 | * gpio access | ||
63 | */ | ||
64 | #define do_gpio_write(gp, val) \ | ||
65 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) | ||
66 | #define do_gpio_read(gp) \ | ||
67 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) | ||
68 | #define tumbler_gpio_free(gp) /* NOP */ | ||
69 | |||
70 | static void write_audio_gpio(struct pmac_gpio *gp, int active) | ||
71 | { | ||
72 | if (! gp->addr) | ||
73 | return; | ||
74 | active = active ? gp->active_val : gp->inactive_val; | ||
75 | do_gpio_write(gp, active); | ||
76 | DBG("(I) gpio %x write %d\n", gp->addr, active); | ||
77 | } | ||
78 | |||
79 | static int check_audio_gpio(struct pmac_gpio *gp) | ||
80 | { | ||
81 | int ret; | ||
82 | |||
83 | if (! gp->addr) | ||
84 | return 0; | ||
85 | |||
86 | ret = do_gpio_read(gp); | ||
87 | |||
88 | return (ret & 0xd) == (gp->active_val & 0xd); | ||
89 | } | ||
90 | |||
91 | static int read_audio_gpio(struct pmac_gpio *gp) | ||
92 | { | ||
93 | int ret; | ||
94 | if (! gp->addr) | ||
95 | return 0; | ||
96 | ret = ((do_gpio_read(gp) & 0x02) !=0); | ||
97 | return ret == gp->active_state; | ||
98 | } | ||
99 | |||
100 | |||
101 | enum { TOONIE_MUTE_HP, TOONIE_MUTE_AMP }; | ||
102 | |||
103 | static int toonie_get_mute_switch(struct snd_kcontrol *kcontrol, | ||
104 | struct snd_ctl_elem_value *ucontrol) | ||
105 | { | ||
106 | struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); | ||
107 | struct pmac_toonie *mix = chip->mixer_data; | ||
108 | struct pmac_gpio *gp; | ||
109 | |||
110 | if (mix == NULL) | ||
111 | return -ENODEV; | ||
112 | switch(kcontrol->private_value) { | ||
113 | case TOONIE_MUTE_HP: | ||
114 | gp = &mix->hp_mute_gpio; | ||
115 | break; | ||
116 | case TOONIE_MUTE_AMP: | ||
117 | gp = &mix->amp_mute_gpio; | ||
118 | break; | ||
119 | default: | ||
120 | return -EINVAL; | ||
121 | } | ||
122 | ucontrol->value.integer.value[0] = !check_audio_gpio(gp); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static int toonie_put_mute_switch(struct snd_kcontrol *kcontrol, | ||
127 | struct snd_ctl_elem_value *ucontrol) | ||
128 | { | ||
129 | struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); | ||
130 | struct pmac_toonie *mix = chip->mixer_data; | ||
131 | struct pmac_gpio *gp; | ||
132 | int val; | ||
133 | |||
134 | if (chip->update_automute && chip->auto_mute) | ||
135 | return 0; /* don't touch in the auto-mute mode */ | ||
136 | |||
137 | if (mix == NULL) | ||
138 | return -ENODEV; | ||
139 | |||
140 | switch(kcontrol->private_value) { | ||
141 | case TOONIE_MUTE_HP: | ||
142 | gp = &mix->hp_mute_gpio; | ||
143 | break; | ||
144 | case TOONIE_MUTE_AMP: | ||
145 | gp = &mix->amp_mute_gpio; | ||
146 | break; | ||
147 | default: | ||
148 | return -EINVAL; | ||
149 | } | ||
150 | val = ! check_audio_gpio(gp); | ||
151 | if (val != ucontrol->value.integer.value[0]) { | ||
152 | write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); | ||
153 | return 1; | ||
154 | } | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static struct snd_kcontrol_new toonie_hp_sw __initdata = { | ||
159 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
160 | .name = "Headphone Playback Switch", | ||
161 | .info = snd_pmac_boolean_mono_info, | ||
162 | .get = toonie_get_mute_switch, | ||
163 | .put = toonie_put_mute_switch, | ||
164 | .private_value = TOONIE_MUTE_HP, | ||
165 | }; | ||
166 | static struct snd_kcontrol_new toonie_speaker_sw __initdata = { | ||
167 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
168 | .name = "PC Speaker Playback Switch", | ||
169 | .info = snd_pmac_boolean_mono_info, | ||
170 | .get = toonie_get_mute_switch, | ||
171 | .put = toonie_put_mute_switch, | ||
172 | .private_value = TOONIE_MUTE_AMP, | ||
173 | }; | ||
174 | |||
175 | /* | ||
176 | * auto-mute stuffs | ||
177 | */ | ||
178 | static int toonie_detect_headphone(struct snd_pmac *chip) | ||
179 | { | ||
180 | struct pmac_toonie *mix = chip->mixer_data; | ||
181 | int detect = 0; | ||
182 | |||
183 | if (mix->hp_detect_gpio.addr) | ||
184 | detect |= read_audio_gpio(&mix->hp_detect_gpio); | ||
185 | return detect; | ||
186 | } | ||
187 | |||
188 | static void toonie_check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val, | ||
189 | int do_notify, struct snd_kcontrol *sw) | ||
190 | { | ||
191 | if (check_audio_gpio(gp) != val) { | ||
192 | write_audio_gpio(gp, val); | ||
193 | if (do_notify) | ||
194 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
195 | &sw->id); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | static void toonie_detect_handler(void *self) | ||
200 | { | ||
201 | struct snd_pmac *chip = (struct snd_pmac *) self; | ||
202 | struct pmac_toonie *mix; | ||
203 | int headphone; | ||
204 | |||
205 | if (!chip) | ||
206 | return; | ||
207 | |||
208 | mix = chip->mixer_data; | ||
209 | snd_assert(mix, return); | ||
210 | |||
211 | headphone = toonie_detect_headphone(chip); | ||
212 | |||
213 | DBG("headphone: %d, lineout: %d\n", headphone, lineout); | ||
214 | |||
215 | if (headphone) { | ||
216 | /* unmute headphone/lineout & mute speaker */ | ||
217 | toonie_check_mute(chip, &mix->hp_mute_gpio, 0, | ||
218 | mix->auto_mute_notify, chip->master_sw_ctl); | ||
219 | toonie_check_mute(chip, &mix->amp_mute_gpio, 1, | ||
220 | mix->auto_mute_notify, chip->speaker_sw_ctl); | ||
221 | } else { | ||
222 | /* unmute speaker, mute others */ | ||
223 | toonie_check_mute(chip, &mix->amp_mute_gpio, 0, | ||
224 | mix->auto_mute_notify, chip->speaker_sw_ctl); | ||
225 | toonie_check_mute(chip, &mix->hp_mute_gpio, 1, | ||
226 | mix->auto_mute_notify, chip->master_sw_ctl); | ||
227 | } | ||
228 | if (mix->auto_mute_notify) { | ||
229 | snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, | ||
230 | &chip->hp_detect_ctl->id); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static void toonie_update_automute(struct snd_pmac *chip, int do_notify) | ||
235 | { | ||
236 | if (chip->auto_mute) { | ||
237 | struct pmac_toonie *mix; | ||
238 | mix = chip->mixer_data; | ||
239 | snd_assert(mix, return); | ||
240 | mix->auto_mute_notify = do_notify; | ||
241 | schedule_work(&mix->detect_work); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | /* interrupt - headphone plug changed */ | ||
246 | static irqreturn_t toonie_hp_intr(int irq, void *devid, struct pt_regs *regs) | ||
247 | { | ||
248 | struct snd_pmac *chip = devid; | ||
249 | |||
250 | if (chip->update_automute && chip->initialized) { | ||
251 | chip->update_automute(chip, 1); | ||
252 | return IRQ_HANDLED; | ||
253 | } | ||
254 | return IRQ_NONE; | ||
255 | } | ||
256 | |||
257 | /* look for audio gpio device */ | ||
258 | static int find_audio_gpio(const char *name, const char *platform, | ||
259 | struct pmac_gpio *gp) | ||
260 | { | ||
261 | struct device_node *np; | ||
262 | u32 *base, addr; | ||
263 | |||
264 | if (! (np = find_devices("gpio"))) | ||
265 | return -ENODEV; | ||
266 | |||
267 | for (np = np->child; np; np = np->sibling) { | ||
268 | char *property = get_property(np, "audio-gpio", NULL); | ||
269 | if (property && strcmp(property, name) == 0) | ||
270 | break; | ||
271 | if (device_is_compatible(np, name)) | ||
272 | break; | ||
273 | } | ||
274 | if (np == NULL) | ||
275 | return -ENODEV; | ||
276 | |||
277 | base = (u32 *)get_property(np, "AAPL,address", NULL); | ||
278 | if (! base) { | ||
279 | base = (u32 *)get_property(np, "reg", NULL); | ||
280 | if (!base) { | ||
281 | DBG("(E) cannot find address for device %s !\n", name); | ||
282 | return -ENODEV; | ||
283 | } | ||
284 | addr = *base; | ||
285 | if (addr < 0x50) | ||
286 | addr += 0x50; | ||
287 | } else | ||
288 | addr = *base; | ||
289 | |||
290 | gp->addr = addr & 0x0000ffff; | ||
291 | |||
292 | /* Try to find the active state, default to 0 ! */ | ||
293 | base = (u32 *)get_property(np, "audio-gpio-active-state", NULL); | ||
294 | if (base) { | ||
295 | gp->active_state = *base; | ||
296 | gp->active_val = (*base) ? 0x5 : 0x4; | ||
297 | gp->inactive_val = (*base) ? 0x4 : 0x5; | ||
298 | } else { | ||
299 | u32 *prop = NULL; | ||
300 | gp->active_state = 0; | ||
301 | gp->active_val = 0x4; | ||
302 | gp->inactive_val = 0x5; | ||
303 | /* Here are some crude hacks to extract the GPIO polarity and | ||
304 | * open collector informations out of the do-platform script | ||
305 | * as we don't yet have an interpreter for these things | ||
306 | */ | ||
307 | if (platform) | ||
308 | prop = (u32 *)get_property(np, platform, NULL); | ||
309 | if (prop) { | ||
310 | if (prop[3] == 0x9 && prop[4] == 0x9) { | ||
311 | gp->active_val = 0xd; | ||
312 | gp->inactive_val = 0xc; | ||
313 | } | ||
314 | if (prop[3] == 0x1 && prop[4] == 0x1) { | ||
315 | gp->active_val = 0x5; | ||
316 | gp->inactive_val = 0x4; | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | |||
321 | DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", | ||
322 | name, gp->addr, gp->active_state); | ||
323 | |||
324 | return (np->n_intrs > 0) ? np->intrs[0].line : 0; | ||
325 | } | ||
326 | |||
327 | static void toonie_cleanup(struct snd_pmac *chip) | ||
328 | { | ||
329 | struct pmac_toonie *mix = chip->mixer_data; | ||
330 | if (! mix) | ||
331 | return; | ||
332 | if (mix->hp_detect_irq >= 0) | ||
333 | free_irq(mix->hp_detect_irq, chip); | ||
334 | kfree(mix); | ||
335 | chip->mixer_data = NULL; | ||
336 | } | ||
337 | |||
338 | int __init snd_pmac_toonie_init(struct snd_pmac *chip) | ||
339 | { | ||
340 | struct pmac_toonie *mix; | ||
341 | |||
342 | mix = kmalloc(sizeof(*mix), GFP_KERNEL); | ||
343 | if (! mix) | ||
344 | return -ENOMEM; | ||
345 | |||
346 | chip->mixer_data = mix; | ||
347 | chip->mixer_free = toonie_cleanup; | ||
348 | |||
349 | find_audio_gpio("headphone-mute", NULL, &mix->hp_mute_gpio); | ||
350 | find_audio_gpio("amp-mute", NULL, &mix->amp_mute_gpio); | ||
351 | mix->hp_detect_irq = find_audio_gpio("headphone-detect", | ||
352 | NULL, &mix->hp_detect_gpio); | ||
353 | |||
354 | strcpy(chip->card->mixername, "PowerMac Toonie"); | ||
355 | |||
356 | chip->master_sw_ctl = snd_ctl_new1(&toonie_hp_sw, chip); | ||
357 | snd_ctl_add(chip->card, chip->master_sw_ctl); | ||
358 | |||
359 | chip->speaker_sw_ctl = snd_ctl_new1(&toonie_speaker_sw, chip); | ||
360 | snd_ctl_add(chip->card, chip->speaker_sw_ctl); | ||
361 | |||
362 | INIT_WORK(&mix->detect_work, toonie_detect_handler, (void *)chip); | ||
363 | |||
364 | if (mix->hp_detect_irq >= 0) { | ||
365 | snd_pmac_add_automute(chip); | ||
366 | |||
367 | chip->detect_headphone = toonie_detect_headphone; | ||
368 | chip->update_automute = toonie_update_automute; | ||
369 | toonie_update_automute(chip, 0); | ||
370 | |||
371 | if (request_irq(mix->hp_detect_irq, toonie_hp_intr, 0, | ||
372 | "Sound Headphone Detection", chip) < 0) | ||
373 | mix->hp_detect_irq = -1; | ||
374 | } | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index e622d08215c9..5eecdd09a79d 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -92,7 +92,7 @@ MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard."); | |||
92 | #define D_USR (1<<4) | 92 | #define D_USR (1<<4) |
93 | #define D_DESC (1<<5) | 93 | #define D_DESC (1<<5) |
94 | 94 | ||
95 | static int dbri_debug = 0; | 95 | static int dbri_debug; |
96 | module_param(dbri_debug, int, 0644); | 96 | module_param(dbri_debug, int, 0644); |
97 | MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard."); | 97 | MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard."); |
98 | 98 | ||
@@ -593,7 +593,7 @@ struct snd_dbri { | |||
593 | /* Return a pointer to dbri_streaminfo */ | 593 | /* Return a pointer to dbri_streaminfo */ |
594 | #define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] | 594 | #define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] |
595 | 595 | ||
596 | static struct snd_dbri *dbri_list = NULL; /* All DBRI devices */ | 596 | static struct snd_dbri *dbri_list; /* All DBRI devices */ |
597 | 597 | ||
598 | /* | 598 | /* |
599 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. | 599 | * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. |
@@ -2521,11 +2521,11 @@ void snd_dbri_proc(struct snd_dbri * dbri) | |||
2521 | struct snd_info_entry *entry; | 2521 | struct snd_info_entry *entry; |
2522 | 2522 | ||
2523 | if (! snd_card_proc_new(dbri->card, "regs", &entry)) | 2523 | if (! snd_card_proc_new(dbri->card, "regs", &entry)) |
2524 | snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read); | 2524 | snd_info_set_text_ops(entry, dbri, dbri_regs_read); |
2525 | 2525 | ||
2526 | #ifdef DBRI_DEBUG | 2526 | #ifdef DBRI_DEBUG |
2527 | if (! snd_card_proc_new(dbri->card, "debug", &entry)) { | 2527 | if (! snd_card_proc_new(dbri->card, "debug", &entry)) { |
2528 | snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read); | 2528 | snd_info_set_text_ops(entry, dbri, dbri_debug_read); |
2529 | entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ | 2529 | entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ |
2530 | } | 2530 | } |
2531 | #endif | 2531 | #endif |
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c index fc733bbf4487..573e3701c14f 100644 --- a/sound/synth/emux/emux.c +++ b/sound/synth/emux/emux.c | |||
@@ -63,6 +63,7 @@ int snd_emux_new(struct snd_emux **remu) | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | EXPORT_SYMBOL(snd_emux_new); | ||
66 | 67 | ||
67 | /* | 68 | /* |
68 | */ | 69 | */ |
@@ -136,6 +137,7 @@ int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, ch | |||
136 | return 0; | 137 | return 0; |
137 | } | 138 | } |
138 | 139 | ||
140 | EXPORT_SYMBOL(snd_emux_register); | ||
139 | 141 | ||
140 | /* | 142 | /* |
141 | */ | 143 | */ |
@@ -171,18 +173,8 @@ int snd_emux_free(struct snd_emux *emu) | |||
171 | return 0; | 173 | return 0; |
172 | } | 174 | } |
173 | 175 | ||
174 | |||
175 | EXPORT_SYMBOL(snd_emux_new); | ||
176 | EXPORT_SYMBOL(snd_emux_register); | ||
177 | EXPORT_SYMBOL(snd_emux_free); | 176 | EXPORT_SYMBOL(snd_emux_free); |
178 | 177 | ||
179 | EXPORT_SYMBOL(snd_emux_terminate_all); | ||
180 | EXPORT_SYMBOL(snd_emux_lock_voice); | ||
181 | EXPORT_SYMBOL(snd_emux_unlock_voice); | ||
182 | |||
183 | /* soundfont.c */ | ||
184 | EXPORT_SYMBOL(snd_sf_linear_to_log); | ||
185 | |||
186 | 178 | ||
187 | /* | 179 | /* |
188 | * INIT part | 180 | * INIT part |
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c index 1ba68ce30279..58b9601f3ad0 100644 --- a/sound/synth/emux/emux_proc.c +++ b/sound/synth/emux/emux_proc.c | |||
@@ -119,7 +119,6 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device) | |||
119 | 119 | ||
120 | entry->content = SNDRV_INFO_CONTENT_TEXT; | 120 | entry->content = SNDRV_INFO_CONTENT_TEXT; |
121 | entry->private_data = emu; | 121 | entry->private_data = emu; |
122 | entry->c.text.read_size = 1024; | ||
123 | entry->c.text.read = snd_emux_proc_info_read; | 122 | entry->c.text.read = snd_emux_proc_info_read; |
124 | if (snd_info_register(entry) < 0) | 123 | if (snd_info_register(entry) < 0) |
125 | snd_info_free_entry(entry); | 124 | snd_info_free_entry(entry); |
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c index 8f00f07701c4..d176cc01742d 100644 --- a/sound/synth/emux/emux_seq.c +++ b/sound/synth/emux/emux_seq.c | |||
@@ -55,7 +55,8 @@ static struct snd_midi_op emux_ops = { | |||
55 | SNDRV_SEQ_PORT_TYPE_MIDI_GM |\ | 55 | SNDRV_SEQ_PORT_TYPE_MIDI_GM |\ |
56 | SNDRV_SEQ_PORT_TYPE_MIDI_GS |\ | 56 | SNDRV_SEQ_PORT_TYPE_MIDI_GS |\ |
57 | SNDRV_SEQ_PORT_TYPE_MIDI_XG |\ | 57 | SNDRV_SEQ_PORT_TYPE_MIDI_XG |\ |
58 | SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE) | 58 | SNDRV_SEQ_PORT_TYPE_HARDWARE |\ |
59 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) | ||
59 | 60 | ||
60 | /* | 61 | /* |
61 | * Initialise the EMUX Synth by creating a client and registering | 62 | * Initialise the EMUX Synth by creating a client and registering |
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 24705d15ebd8..3733118d39bb 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c | |||
@@ -434,6 +434,7 @@ snd_emux_terminate_all(struct snd_emux *emu) | |||
434 | spin_unlock_irqrestore(&emu->voice_lock, flags); | 434 | spin_unlock_irqrestore(&emu->voice_lock, flags); |
435 | } | 435 | } |
436 | 436 | ||
437 | EXPORT_SYMBOL(snd_emux_terminate_all); | ||
437 | 438 | ||
438 | /* | 439 | /* |
439 | * Terminate all voices associated with the given port | 440 | * Terminate all voices associated with the given port |
@@ -951,6 +952,8 @@ void snd_emux_lock_voice(struct snd_emux *emu, int voice) | |||
951 | spin_unlock_irqrestore(&emu->voice_lock, flags); | 952 | spin_unlock_irqrestore(&emu->voice_lock, flags); |
952 | } | 953 | } |
953 | 954 | ||
955 | EXPORT_SYMBOL(snd_emux_lock_voice); | ||
956 | |||
954 | /* | 957 | /* |
955 | */ | 958 | */ |
956 | void snd_emux_unlock_voice(struct snd_emux *emu, int voice) | 959 | void snd_emux_unlock_voice(struct snd_emux *emu, int voice) |
@@ -965,3 +968,5 @@ void snd_emux_unlock_voice(struct snd_emux *emu, int voice) | |||
965 | voice, emu->voices[voice].state); | 968 | voice, emu->voices[voice].state); |
966 | spin_unlock_irqrestore(&emu->voice_lock, flags); | 969 | spin_unlock_irqrestore(&emu->voice_lock, flags); |
967 | } | 970 | } |
971 | |||
972 | EXPORT_SYMBOL(snd_emux_unlock_voice); | ||
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 32c27162dfb6..455e535933ec 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c | |||
@@ -195,7 +195,7 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, | |||
195 | break; | 195 | break; |
196 | case SNDRV_SFNT_REMOVE_INFO: | 196 | case SNDRV_SFNT_REMOVE_INFO: |
197 | /* patch must be opened */ | 197 | /* patch must be opened */ |
198 | if (sflist->currsf) { | 198 | if (!sflist->currsf) { |
199 | snd_printk("soundfont: remove_info: patch not opened\n"); | 199 | snd_printk("soundfont: remove_info: patch not opened\n"); |
200 | rc = -EINVAL; | 200 | rc = -EINVAL; |
201 | } else { | 201 | } else { |
@@ -810,6 +810,9 @@ snd_sf_linear_to_log(unsigned int amount, int offset, int ratio) | |||
810 | return v; | 810 | return v; |
811 | } | 811 | } |
812 | 812 | ||
813 | EXPORT_SYMBOL(snd_sf_linear_to_log); | ||
814 | |||
815 | |||
813 | #define OFFSET_MSEC 653117 /* base = 1000 */ | 816 | #define OFFSET_MSEC 653117 /* base = 1000 */ |
814 | #define OFFSET_ABSCENT 851781 /* base = 8176 */ | 817 | #define OFFSET_ABSCENT 851781 /* base = 8176 */ |
815 | #define OFFSET_SAMPLERATE 1011119 /* base = 44100 */ | 818 | #define OFFSET_SAMPLERATE 1011119 /* base = 44100 */ |
@@ -1485,4 +1488,3 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) | |||
1485 | unlock_preset(sflist); | 1488 | unlock_preset(sflist); |
1486 | return 0; | 1489 | return 0; |
1487 | } | 1490 | } |
1488 | |||
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 4e614ac39f21..627de9525a32 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -2138,7 +2138,7 @@ static void proc_pcm_format_add(struct snd_usb_stream *stream) | |||
2138 | 2138 | ||
2139 | sprintf(name, "stream%d", stream->pcm_index); | 2139 | sprintf(name, "stream%d", stream->pcm_index); |
2140 | if (! snd_card_proc_new(card, name, &entry)) | 2140 | if (! snd_card_proc_new(card, name, &entry)) |
2141 | snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read); | 2141 | snd_info_set_text_ops(entry, stream, proc_pcm_format_read); |
2142 | } | 2142 | } |
2143 | 2143 | ||
2144 | #else | 2144 | #else |
@@ -2627,9 +2627,10 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2627 | if (!csep && altsd->bNumEndpoints >= 2) | 2627 | if (!csep && altsd->bNumEndpoints >= 2) |
2628 | csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); | 2628 | csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); |
2629 | if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { | 2629 | if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) { |
2630 | snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n", | 2630 | snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" |
2631 | " class specific endpoint descriptor\n", | ||
2631 | dev->devnum, iface_no, altno); | 2632 | dev->devnum, iface_no, altno); |
2632 | continue; | 2633 | csep = NULL; |
2633 | } | 2634 | } |
2634 | 2635 | ||
2635 | fp = kmalloc(sizeof(*fp), GFP_KERNEL); | 2636 | fp = kmalloc(sizeof(*fp), GFP_KERNEL); |
@@ -2648,7 +2649,7 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) | |||
2648 | if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) | 2649 | if (snd_usb_get_speed(dev) == USB_SPEED_HIGH) |
2649 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) | 2650 | fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1) |
2650 | * (fp->maxpacksize & 0x7ff); | 2651 | * (fp->maxpacksize & 0x7ff); |
2651 | fp->attributes = csep[3]; | 2652 | fp->attributes = csep ? csep[3] : 0; |
2652 | 2653 | ||
2653 | /* some quirks for attributes here */ | 2654 | /* some quirks for attributes here */ |
2654 | 2655 | ||
@@ -2980,7 +2981,7 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip, | |||
2980 | return -ENXIO; | 2981 | return -ENXIO; |
2981 | alts = &iface->altsetting[1]; | 2982 | alts = &iface->altsetting[1]; |
2982 | altsd = get_iface_desc(alts); | 2983 | altsd = get_iface_desc(alts); |
2983 | if (alts->extralen != 11 || alts->extra[1] != CS_AUDIO_INTERFACE || | 2984 | if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE || |
2984 | altsd->bNumEndpoints != 1) | 2985 | altsd->bNumEndpoints != 1) |
2985 | return -ENXIO; | 2986 | return -ENXIO; |
2986 | 2987 | ||
@@ -3197,9 +3198,9 @@ static void snd_usb_audio_create_proc(struct snd_usb_audio *chip) | |||
3197 | { | 3198 | { |
3198 | struct snd_info_entry *entry; | 3199 | struct snd_info_entry *entry; |
3199 | if (! snd_card_proc_new(chip->card, "usbbus", &entry)) | 3200 | if (! snd_card_proc_new(chip->card, "usbbus", &entry)) |
3200 | snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbbus_read); | 3201 | snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read); |
3201 | if (! snd_card_proc_new(chip->card, "usbid", &entry)) | 3202 | if (! snd_card_proc_new(chip->card, "usbid", &entry)) |
3202 | snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbid_read); | 3203 | snd_info_set_text_ops(entry, chip, proc_audio_usbid_read); |
3203 | } | 3204 | } |
3204 | 3205 | ||
3205 | /* | 3206 | /* |
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 88733524d0fb..0f4b2b8541d6 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -30,13 +30,6 @@ | |||
30 | #define USB_SUBCLASS_MIDI_STREAMING 0x03 | 30 | #define USB_SUBCLASS_MIDI_STREAMING 0x03 |
31 | #define USB_SUBCLASS_VENDOR_SPEC 0xff | 31 | #define USB_SUBCLASS_VENDOR_SPEC 0xff |
32 | 32 | ||
33 | #define CS_AUDIO_UNDEFINED 0x20 | ||
34 | #define CS_AUDIO_DEVICE 0x21 | ||
35 | #define CS_AUDIO_CONFIGURATION 0x22 | ||
36 | #define CS_AUDIO_STRING 0x23 | ||
37 | #define CS_AUDIO_INTERFACE 0x24 | ||
38 | #define CS_AUDIO_ENDPOINT 0x25 | ||
39 | |||
40 | #define HEADER 0x01 | 33 | #define HEADER 0x01 |
41 | #define INPUT_TERMINAL 0x02 | 34 | #define INPUT_TERMINAL 0x02 |
42 | #define OUTPUT_TERMINAL 0x03 | 35 | #define OUTPUT_TERMINAL 0x03 |
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c index 2b9d940c8064..5105b6b05748 100644 --- a/sound/usb/usbmidi.c +++ b/sound/usb/usbmidi.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/usb.h> | 48 | #include <linux/usb.h> |
49 | #include <sound/core.h> | 49 | #include <sound/core.h> |
50 | #include <sound/rawmidi.h> | 50 | #include <sound/rawmidi.h> |
51 | #include <sound/asequencer.h> | ||
51 | #include "usbaudio.h" | 52 | #include "usbaudio.h" |
52 | 53 | ||
53 | 54 | ||
@@ -1010,97 +1011,157 @@ static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_m | |||
1010 | * "(product) MIDI (n)" schema because they aren't external MIDI ports, | 1011 | * "(product) MIDI (n)" schema because they aren't external MIDI ports, |
1011 | * such as internal control or synthesizer ports. | 1012 | * such as internal control or synthesizer ports. |
1012 | */ | 1013 | */ |
1013 | static struct { | 1014 | static struct port_info { |
1014 | u32 id; | 1015 | u32 id; |
1015 | int port; | 1016 | short int port; |
1016 | const char *name_format; | 1017 | short int voices; |
1017 | } snd_usbmidi_port_names[] = { | 1018 | const char *name; |
1019 | unsigned int seq_flags; | ||
1020 | } snd_usbmidi_port_info[] = { | ||
1021 | #define PORT_INFO(vendor, product, num, name_, voices_, flags) \ | ||
1022 | { .id = USB_ID(vendor, product), \ | ||
1023 | .port = num, .voices = voices_, \ | ||
1024 | .name = name_, .seq_flags = flags } | ||
1025 | #define EXTERNAL_PORT(vendor, product, num, name) \ | ||
1026 | PORT_INFO(vendor, product, num, name, 0, \ | ||
1027 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ | ||
1028 | SNDRV_SEQ_PORT_TYPE_HARDWARE | \ | ||
1029 | SNDRV_SEQ_PORT_TYPE_PORT) | ||
1030 | #define CONTROL_PORT(vendor, product, num, name) \ | ||
1031 | PORT_INFO(vendor, product, num, name, 0, \ | ||
1032 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ | ||
1033 | SNDRV_SEQ_PORT_TYPE_HARDWARE) | ||
1034 | #define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \ | ||
1035 | PORT_INFO(vendor, product, num, name, voices, \ | ||
1036 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ | ||
1037 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | \ | ||
1038 | SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \ | ||
1039 | SNDRV_SEQ_PORT_TYPE_MIDI_GS | \ | ||
1040 | SNDRV_SEQ_PORT_TYPE_MIDI_XG | \ | ||
1041 | SNDRV_SEQ_PORT_TYPE_HARDWARE | \ | ||
1042 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) | ||
1043 | #define SOUNDCANVAS_PORT(vendor, product, num, name, voices) \ | ||
1044 | PORT_INFO(vendor, product, num, name, voices, \ | ||
1045 | SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \ | ||
1046 | SNDRV_SEQ_PORT_TYPE_MIDI_GM | \ | ||
1047 | SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \ | ||
1048 | SNDRV_SEQ_PORT_TYPE_MIDI_GS | \ | ||
1049 | SNDRV_SEQ_PORT_TYPE_MIDI_XG | \ | ||
1050 | SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \ | ||
1051 | SNDRV_SEQ_PORT_TYPE_HARDWARE | \ | ||
1052 | SNDRV_SEQ_PORT_TYPE_SYNTHESIZER) | ||
1018 | /* Roland UA-100 */ | 1053 | /* Roland UA-100 */ |
1019 | { USB_ID(0x0582, 0x0000), 2, "%s Control" }, | 1054 | CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"), |
1020 | /* Roland SC-8850 */ | 1055 | /* Roland SC-8850 */ |
1021 | { USB_ID(0x0582, 0x0003), 0, "%s Part A" }, | 1056 | SOUNDCANVAS_PORT(0x0582, 0x0003, 0, "%s Part A", 128), |
1022 | { USB_ID(0x0582, 0x0003), 1, "%s Part B" }, | 1057 | SOUNDCANVAS_PORT(0x0582, 0x0003, 1, "%s Part B", 128), |
1023 | { USB_ID(0x0582, 0x0003), 2, "%s Part C" }, | 1058 | SOUNDCANVAS_PORT(0x0582, 0x0003, 2, "%s Part C", 128), |
1024 | { USB_ID(0x0582, 0x0003), 3, "%s Part D" }, | 1059 | SOUNDCANVAS_PORT(0x0582, 0x0003, 3, "%s Part D", 128), |
1025 | { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" }, | 1060 | EXTERNAL_PORT(0x0582, 0x0003, 4, "%s MIDI 1"), |
1026 | { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" }, | 1061 | EXTERNAL_PORT(0x0582, 0x0003, 5, "%s MIDI 2"), |
1027 | /* Roland U-8 */ | 1062 | /* Roland U-8 */ |
1028 | { USB_ID(0x0582, 0x0004), 0, "%s MIDI" }, | 1063 | EXTERNAL_PORT(0x0582, 0x0004, 0, "%s MIDI"), |
1029 | { USB_ID(0x0582, 0x0004), 1, "%s Control" }, | 1064 | CONTROL_PORT(0x0582, 0x0004, 1, "%s Control"), |
1030 | /* Roland SC-8820 */ | 1065 | /* Roland SC-8820 */ |
1031 | { USB_ID(0x0582, 0x0007), 0, "%s Part A" }, | 1066 | SOUNDCANVAS_PORT(0x0582, 0x0007, 0, "%s Part A", 64), |
1032 | { USB_ID(0x0582, 0x0007), 1, "%s Part B" }, | 1067 | SOUNDCANVAS_PORT(0x0582, 0x0007, 1, "%s Part B", 64), |
1033 | { USB_ID(0x0582, 0x0007), 2, "%s MIDI" }, | 1068 | EXTERNAL_PORT(0x0582, 0x0007, 2, "%s MIDI"), |
1034 | /* Roland SK-500 */ | 1069 | /* Roland SK-500 */ |
1035 | { USB_ID(0x0582, 0x000b), 0, "%s Part A" }, | 1070 | SOUNDCANVAS_PORT(0x0582, 0x000b, 0, "%s Part A", 64), |
1036 | { USB_ID(0x0582, 0x000b), 1, "%s Part B" }, | 1071 | SOUNDCANVAS_PORT(0x0582, 0x000b, 1, "%s Part B", 64), |
1037 | { USB_ID(0x0582, 0x000b), 2, "%s MIDI" }, | 1072 | EXTERNAL_PORT(0x0582, 0x000b, 2, "%s MIDI"), |
1038 | /* Roland SC-D70 */ | 1073 | /* Roland SC-D70 */ |
1039 | { USB_ID(0x0582, 0x000c), 0, "%s Part A" }, | 1074 | SOUNDCANVAS_PORT(0x0582, 0x000c, 0, "%s Part A", 64), |
1040 | { USB_ID(0x0582, 0x000c), 1, "%s Part B" }, | 1075 | SOUNDCANVAS_PORT(0x0582, 0x000c, 1, "%s Part B", 64), |
1041 | { USB_ID(0x0582, 0x000c), 2, "%s MIDI" }, | 1076 | EXTERNAL_PORT(0x0582, 0x000c, 2, "%s MIDI"), |
1042 | /* Edirol UM-880 */ | 1077 | /* Edirol UM-880 */ |
1043 | { USB_ID(0x0582, 0x0014), 8, "%s Control" }, | 1078 | CONTROL_PORT(0x0582, 0x0014, 8, "%s Control"), |
1044 | /* Edirol SD-90 */ | 1079 | /* Edirol SD-90 */ |
1045 | { USB_ID(0x0582, 0x0016), 0, "%s Part A" }, | 1080 | ROLAND_SYNTH_PORT(0x0582, 0x0016, 0, "%s Part A", 128), |
1046 | { USB_ID(0x0582, 0x0016), 1, "%s Part B" }, | 1081 | ROLAND_SYNTH_PORT(0x0582, 0x0016, 1, "%s Part B", 128), |
1047 | { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" }, | 1082 | EXTERNAL_PORT(0x0582, 0x0016, 2, "%s MIDI 1"), |
1048 | { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" }, | 1083 | EXTERNAL_PORT(0x0582, 0x0016, 3, "%s MIDI 2"), |
1049 | /* Edirol UM-550 */ | 1084 | /* Edirol UM-550 */ |
1050 | { USB_ID(0x0582, 0x0023), 5, "%s Control" }, | 1085 | CONTROL_PORT(0x0582, 0x0023, 5, "%s Control"), |
1051 | /* Edirol SD-20 */ | 1086 | /* Edirol SD-20 */ |
1052 | { USB_ID(0x0582, 0x0027), 0, "%s Part A" }, | 1087 | ROLAND_SYNTH_PORT(0x0582, 0x0027, 0, "%s Part A", 64), |
1053 | { USB_ID(0x0582, 0x0027), 1, "%s Part B" }, | 1088 | ROLAND_SYNTH_PORT(0x0582, 0x0027, 1, "%s Part B", 64), |
1054 | { USB_ID(0x0582, 0x0027), 2, "%s MIDI" }, | 1089 | EXTERNAL_PORT(0x0582, 0x0027, 2, "%s MIDI"), |
1055 | /* Edirol SD-80 */ | 1090 | /* Edirol SD-80 */ |
1056 | { USB_ID(0x0582, 0x0029), 0, "%s Part A" }, | 1091 | ROLAND_SYNTH_PORT(0x0582, 0x0029, 0, "%s Part A", 128), |
1057 | { USB_ID(0x0582, 0x0029), 1, "%s Part B" }, | 1092 | ROLAND_SYNTH_PORT(0x0582, 0x0029, 1, "%s Part B", 128), |
1058 | { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" }, | 1093 | EXTERNAL_PORT(0x0582, 0x0029, 2, "%s MIDI 1"), |
1059 | { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" }, | 1094 | EXTERNAL_PORT(0x0582, 0x0029, 3, "%s MIDI 2"), |
1060 | /* Edirol UA-700 */ | 1095 | /* Edirol UA-700 */ |
1061 | { USB_ID(0x0582, 0x002b), 0, "%s MIDI" }, | 1096 | EXTERNAL_PORT(0x0582, 0x002b, 0, "%s MIDI"), |
1062 | { USB_ID(0x0582, 0x002b), 1, "%s Control" }, | 1097 | CONTROL_PORT(0x0582, 0x002b, 1, "%s Control"), |
1063 | /* Roland VariOS */ | 1098 | /* Roland VariOS */ |
1064 | { USB_ID(0x0582, 0x002f), 0, "%s MIDI" }, | 1099 | EXTERNAL_PORT(0x0582, 0x002f, 0, "%s MIDI"), |
1065 | { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" }, | 1100 | EXTERNAL_PORT(0x0582, 0x002f, 1, "%s External MIDI"), |
1066 | { USB_ID(0x0582, 0x002f), 2, "%s Sync" }, | 1101 | EXTERNAL_PORT(0x0582, 0x002f, 2, "%s Sync"), |
1067 | /* Edirol PCR */ | 1102 | /* Edirol PCR */ |
1068 | { USB_ID(0x0582, 0x0033), 0, "%s MIDI" }, | 1103 | EXTERNAL_PORT(0x0582, 0x0033, 0, "%s MIDI"), |
1069 | { USB_ID(0x0582, 0x0033), 1, "%s 1" }, | 1104 | EXTERNAL_PORT(0x0582, 0x0033, 1, "%s 1"), |
1070 | { USB_ID(0x0582, 0x0033), 2, "%s 2" }, | 1105 | EXTERNAL_PORT(0x0582, 0x0033, 2, "%s 2"), |
1071 | /* BOSS GS-10 */ | 1106 | /* BOSS GS-10 */ |
1072 | { USB_ID(0x0582, 0x003b), 0, "%s MIDI" }, | 1107 | EXTERNAL_PORT(0x0582, 0x003b, 0, "%s MIDI"), |
1073 | { USB_ID(0x0582, 0x003b), 1, "%s Control" }, | 1108 | CONTROL_PORT(0x0582, 0x003b, 1, "%s Control"), |
1074 | /* Edirol UA-1000 */ | 1109 | /* Edirol UA-1000 */ |
1075 | { USB_ID(0x0582, 0x0044), 0, "%s MIDI" }, | 1110 | EXTERNAL_PORT(0x0582, 0x0044, 0, "%s MIDI"), |
1076 | { USB_ID(0x0582, 0x0044), 1, "%s Control" }, | 1111 | CONTROL_PORT(0x0582, 0x0044, 1, "%s Control"), |
1077 | /* Edirol UR-80 */ | 1112 | /* Edirol UR-80 */ |
1078 | { USB_ID(0x0582, 0x0048), 0, "%s MIDI" }, | 1113 | EXTERNAL_PORT(0x0582, 0x0048, 0, "%s MIDI"), |
1079 | { USB_ID(0x0582, 0x0048), 1, "%s 1" }, | 1114 | EXTERNAL_PORT(0x0582, 0x0048, 1, "%s 1"), |
1080 | { USB_ID(0x0582, 0x0048), 2, "%s 2" }, | 1115 | EXTERNAL_PORT(0x0582, 0x0048, 2, "%s 2"), |
1081 | /* Edirol PCR-A */ | 1116 | /* Edirol PCR-A */ |
1082 | { USB_ID(0x0582, 0x004d), 0, "%s MIDI" }, | 1117 | EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"), |
1083 | { USB_ID(0x0582, 0x004d), 1, "%s 1" }, | 1118 | EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"), |
1084 | { USB_ID(0x0582, 0x004d), 2, "%s 2" }, | 1119 | EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"), |
1085 | /* Edirol UM-3EX */ | 1120 | /* Edirol UM-3EX */ |
1086 | { USB_ID(0x0582, 0x009a), 3, "%s Control" }, | 1121 | CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"), |
1087 | /* M-Audio MidiSport 8x8 */ | 1122 | /* M-Audio MidiSport 8x8 */ |
1088 | { USB_ID(0x0763, 0x1031), 8, "%s Control" }, | 1123 | CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"), |
1089 | { USB_ID(0x0763, 0x1033), 8, "%s Control" }, | 1124 | CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"), |
1090 | /* MOTU Fastlane */ | 1125 | /* MOTU Fastlane */ |
1091 | { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" }, | 1126 | EXTERNAL_PORT(0x07fd, 0x0001, 0, "%s MIDI A"), |
1092 | { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" }, | 1127 | EXTERNAL_PORT(0x07fd, 0x0001, 1, "%s MIDI B"), |
1093 | /* Emagic Unitor8/AMT8/MT4 */ | 1128 | /* Emagic Unitor8/AMT8/MT4 */ |
1094 | { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" }, | 1129 | EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"), |
1095 | { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" }, | 1130 | EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"), |
1096 | { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" }, | 1131 | EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"), |
1097 | }; | 1132 | }; |
1098 | 1133 | ||
1134 | static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number) | ||
1135 | { | ||
1136 | int i; | ||
1137 | |||
1138 | for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) { | ||
1139 | if (snd_usbmidi_port_info[i].id == umidi->chip->usb_id && | ||
1140 | snd_usbmidi_port_info[i].port == number) | ||
1141 | return &snd_usbmidi_port_info[i]; | ||
1142 | } | ||
1143 | return NULL; | ||
1144 | } | ||
1145 | |||
1146 | static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number, | ||
1147 | struct snd_seq_port_info *seq_port_info) | ||
1148 | { | ||
1149 | struct snd_usb_midi *umidi = rmidi->private_data; | ||
1150 | struct port_info *port_info; | ||
1151 | |||
1152 | /* TODO: read port flags from descriptors */ | ||
1153 | port_info = find_port_info(umidi, number); | ||
1154 | if (port_info) { | ||
1155 | seq_port_info->type = port_info->seq_flags; | ||
1156 | seq_port_info->midi_voices = port_info->voices; | ||
1157 | } | ||
1158 | } | ||
1159 | |||
1099 | static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, | 1160 | static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, |
1100 | int stream, int number, | 1161 | int stream, int number, |
1101 | struct snd_rawmidi_substream ** rsubstream) | 1162 | struct snd_rawmidi_substream ** rsubstream) |
1102 | { | 1163 | { |
1103 | int i; | 1164 | struct port_info *port_info; |
1104 | const char *name_format; | 1165 | const char *name_format; |
1105 | 1166 | ||
1106 | struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); | 1167 | struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number); |
@@ -1110,14 +1171,8 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi, | |||
1110 | } | 1171 | } |
1111 | 1172 | ||
1112 | /* TODO: read port name from jack descriptor */ | 1173 | /* TODO: read port name from jack descriptor */ |
1113 | name_format = "%s MIDI %d"; | 1174 | port_info = find_port_info(umidi, number); |
1114 | for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) { | 1175 | name_format = port_info ? port_info->name : "%s MIDI %d"; |
1115 | if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id && | ||
1116 | snd_usbmidi_port_names[i].port == number) { | ||
1117 | name_format = snd_usbmidi_port_names[i].name_format; | ||
1118 | break; | ||
1119 | } | ||
1120 | } | ||
1121 | snprintf(substream->name, sizeof(substream->name), | 1176 | snprintf(substream->name, sizeof(substream->name), |
1122 | name_format, umidi->chip->card->shortname, number + 1); | 1177 | name_format, umidi->chip->card->shortname, number + 1); |
1123 | 1178 | ||
@@ -1358,7 +1413,7 @@ static int snd_usbmidi_detect_yamaha(struct snd_usb_midi* umidi, | |||
1358 | for (cs_desc = hostif->extra; | 1413 | for (cs_desc = hostif->extra; |
1359 | cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2; | 1414 | cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2; |
1360 | cs_desc += cs_desc[0]) { | 1415 | cs_desc += cs_desc[0]) { |
1361 | if (cs_desc[1] == CS_AUDIO_INTERFACE) { | 1416 | if (cs_desc[1] == USB_DT_CS_INTERFACE) { |
1362 | if (cs_desc[2] == MIDI_IN_JACK) | 1417 | if (cs_desc[2] == MIDI_IN_JACK) |
1363 | endpoint->in_cables = (endpoint->in_cables << 1) | 1; | 1418 | endpoint->in_cables = (endpoint->in_cables << 1) | 1; |
1364 | else if (cs_desc[2] == MIDI_OUT_JACK) | 1419 | else if (cs_desc[2] == MIDI_OUT_JACK) |
@@ -1457,6 +1512,10 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi, | |||
1457 | return 0; | 1512 | return 0; |
1458 | } | 1513 | } |
1459 | 1514 | ||
1515 | static struct snd_rawmidi_global_ops snd_usbmidi_ops = { | ||
1516 | .get_port_info = snd_usbmidi_get_port_info, | ||
1517 | }; | ||
1518 | |||
1460 | static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, | 1519 | static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, |
1461 | int out_ports, int in_ports) | 1520 | int out_ports, int in_ports) |
1462 | { | 1521 | { |
@@ -1472,6 +1531,7 @@ static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi, | |||
1472 | rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | | 1531 | rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | |
1473 | SNDRV_RAWMIDI_INFO_INPUT | | 1532 | SNDRV_RAWMIDI_INFO_INPUT | |
1474 | SNDRV_RAWMIDI_INFO_DUPLEX; | 1533 | SNDRV_RAWMIDI_INFO_DUPLEX; |
1534 | rmidi->ops = &snd_usbmidi_ops; | ||
1475 | rmidi->private_data = umidi; | 1535 | rmidi->private_data = umidi; |
1476 | rmidi->private_free = snd_usbmidi_rawmidi_free; | 1536 | rmidi->private_free = snd_usbmidi_rawmidi_free; |
1477 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops); | 1537 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops); |
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c index ce86283ee0fa..491e975a0c87 100644 --- a/sound/usb/usbmixer.c +++ b/sound/usb/usbmixer.c | |||
@@ -46,6 +46,27 @@ | |||
46 | /* ignore error from controls - for debugging */ | 46 | /* ignore error from controls - for debugging */ |
47 | /* #define IGNORE_CTL_ERROR */ | 47 | /* #define IGNORE_CTL_ERROR */ |
48 | 48 | ||
49 | /* | ||
50 | * Sound Blaster remote control configuration | ||
51 | * | ||
52 | * format of remote control data: | ||
53 | * Extigy: xx 00 | ||
54 | * Audigy 2 NX: 06 80 xx 00 00 00 | ||
55 | * Live! 24-bit: 06 80 xx yy 22 83 | ||
56 | */ | ||
57 | static const struct rc_config { | ||
58 | u32 usb_id; | ||
59 | u8 offset; | ||
60 | u8 length; | ||
61 | u8 packet_length; | ||
62 | u8 mute_mixer_id; | ||
63 | u32 mute_code; | ||
64 | } rc_configs[] = { | ||
65 | { USB_ID(0x041e, 0x3000), 0, 1, 2, 18, 0x0013 }, /* Extigy */ | ||
66 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 18, 0x0013 }, /* Audigy 2 NX */ | ||
67 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 2, 0x6e91 }, /* Live! 24-bit */ | ||
68 | }; | ||
69 | |||
49 | struct usb_mixer_interface { | 70 | struct usb_mixer_interface { |
50 | struct snd_usb_audio *chip; | 71 | struct snd_usb_audio *chip; |
51 | unsigned int ctrlif; | 72 | unsigned int ctrlif; |
@@ -55,11 +76,7 @@ struct usb_mixer_interface { | |||
55 | struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ | 76 | struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */ |
56 | 77 | ||
57 | /* Sound Blaster remote control stuff */ | 78 | /* Sound Blaster remote control stuff */ |
58 | enum { | 79 | const struct rc_config *rc_cfg; |
59 | RC_NONE, | ||
60 | RC_EXTIGY, | ||
61 | RC_AUDIGY2NX, | ||
62 | } rc_type; | ||
63 | unsigned long rc_hwdep_open; | 80 | unsigned long rc_hwdep_open; |
64 | u32 rc_code; | 81 | u32 rc_code; |
65 | wait_queue_head_t rc_waitq; | 82 | wait_queue_head_t rc_waitq; |
@@ -1647,7 +1664,7 @@ static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, | |||
1647 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, | 1664 | static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer, |
1648 | int unitid) | 1665 | int unitid) |
1649 | { | 1666 | { |
1650 | if (mixer->rc_type == RC_NONE) | 1667 | if (!mixer->rc_cfg) |
1651 | return; | 1668 | return; |
1652 | /* unit ids specific to Extigy/Audigy 2 NX: */ | 1669 | /* unit ids specific to Extigy/Audigy 2 NX: */ |
1653 | switch (unitid) { | 1670 | switch (unitid) { |
@@ -1732,20 +1749,19 @@ static void snd_usb_soundblaster_remote_complete(struct urb *urb, | |||
1732 | struct pt_regs *regs) | 1749 | struct pt_regs *regs) |
1733 | { | 1750 | { |
1734 | struct usb_mixer_interface *mixer = urb->context; | 1751 | struct usb_mixer_interface *mixer = urb->context; |
1735 | /* | 1752 | const struct rc_config *rc = mixer->rc_cfg; |
1736 | * format of remote control data: | ||
1737 | * Extigy: xx 00 | ||
1738 | * Audigy 2 NX: 06 80 xx 00 00 00 | ||
1739 | */ | ||
1740 | int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2; | ||
1741 | u32 code; | 1753 | u32 code; |
1742 | 1754 | ||
1743 | if (urb->status < 0 || urb->actual_length <= offset) | 1755 | if (urb->status < 0 || urb->actual_length < rc->packet_length) |
1744 | return; | 1756 | return; |
1745 | code = mixer->rc_buffer[offset]; | 1757 | |
1758 | code = mixer->rc_buffer[rc->offset]; | ||
1759 | if (rc->length == 2) | ||
1760 | code |= mixer->rc_buffer[rc->offset + 1] << 8; | ||
1761 | |||
1746 | /* the Mute button actually changes the mixer control */ | 1762 | /* the Mute button actually changes the mixer control */ |
1747 | if (code == 13) | 1763 | if (code == rc->mute_code) |
1748 | snd_usb_mixer_notify_id(mixer, 18); | 1764 | snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id); |
1749 | mixer->rc_code = code; | 1765 | mixer->rc_code = code; |
1750 | wmb(); | 1766 | wmb(); |
1751 | wake_up(&mixer->rc_waitq); | 1767 | wake_up(&mixer->rc_waitq); |
@@ -1801,21 +1817,17 @@ static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *f | |||
1801 | static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) | 1817 | static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) |
1802 | { | 1818 | { |
1803 | struct snd_hwdep *hwdep; | 1819 | struct snd_hwdep *hwdep; |
1804 | int err, len; | 1820 | int err, len, i; |
1805 | 1821 | ||
1806 | switch (mixer->chip->usb_id) { | 1822 | for (i = 0; i < ARRAY_SIZE(rc_configs); ++i) |
1807 | case USB_ID(0x041e, 0x3000): | 1823 | if (rc_configs[i].usb_id == mixer->chip->usb_id) |
1808 | mixer->rc_type = RC_EXTIGY; | 1824 | break; |
1809 | len = 2; | 1825 | if (i >= ARRAY_SIZE(rc_configs)) |
1810 | break; | ||
1811 | case USB_ID(0x041e, 0x3020): | ||
1812 | mixer->rc_type = RC_AUDIGY2NX; | ||
1813 | len = 6; | ||
1814 | break; | ||
1815 | default: | ||
1816 | return 0; | 1826 | return 0; |
1817 | } | 1827 | mixer->rc_cfg = &rc_configs[i]; |
1818 | 1828 | ||
1829 | len = mixer->rc_cfg->packet_length; | ||
1830 | |||
1819 | init_waitqueue_head(&mixer->rc_waitq); | 1831 | init_waitqueue_head(&mixer->rc_waitq); |
1820 | err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); | 1832 | err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep); |
1821 | if (err < 0) | 1833 | if (err < 0) |
@@ -1998,7 +2010,7 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif) | |||
1998 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 2010 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) |
1999 | goto _error; | 2011 | goto _error; |
2000 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) | 2012 | if (!snd_card_proc_new(chip->card, "audigy2nx", &entry)) |
2001 | snd_info_set_text_ops(entry, mixer, 1024, | 2013 | snd_info_set_text_ops(entry, mixer, |
2002 | snd_audigy2nx_proc_read); | 2014 | snd_audigy2nx_proc_read); |
2003 | } | 2015 | } |
2004 | 2016 | ||
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index fe67a92e2a1a..88b72b52590f 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c | |||
@@ -632,7 +632,7 @@ static int usX2Y_pcms_lock_check(struct snd_card *card) | |||
632 | for (s = 0; s < 2; ++s) { | 632 | for (s = 0; s < 2; ++s) { |
633 | struct snd_pcm_substream *substream; | 633 | struct snd_pcm_substream *substream; |
634 | substream = pcm->streams[s].substream; | 634 | substream = pcm->streams[s].substream; |
635 | if (substream && substream->ffile != NULL) | 635 | if (SUBSTREAM_BUSY(substream)) |
636 | err = -EBUSY; | 636 | err = -EBUSY; |
637 | } | 637 | } |
638 | } | 638 | } |