diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:46:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:46:37 -0400 |
commit | d3e458d78167102cc961237cfceef6fffc80c0b3 (patch) | |
tree | e9195c1294daf053614e63ac52b0b44a28479017 | |
parent | f2e1fbb5f2177227f71c4fc0491e531dd7acd385 (diff) | |
parent | d351cf4603edb2a5bfa9a48d06c425511c63f2a3 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (308 commits)
ALSA: sound/pci/asihpi: check adapter index in hpi_ioctl
ALSA: aloop - Fix possible IRQ lock inversion
ALSA: sound/core: merge list_del()/list_add_tail() to list_move_tail()
ALSA: ctxfi - use list_move() instead of list_del()/list_add() combination
ALSA: firewire - msleep needs delay.h
ALSA: firewire-lib, firewire-speakers: handle packet queueing errors
ALSA: firewire-lib: allocate DMA buffer separately
ALSA: firewire-lib: use no-info SYT for packets without SYT sample
ALSA: add LaCie FireWire Speakers/Griffin FireWave Surround driver
ALSA: hda - Remove an unused variable in patch_realtek.c
ALSA: hda - pin-adc-mux-dmic auto-configuration of 92HD8X codecs
ALSA: hda - fix digital mic selection in mixer on 92HD8X codecs
ALSA: hda - Move default input-src selection to init part
ALSA: hda - Initialize special cases for input src in init phase
ALSA: ctxfi - Clear input settings before initialization
ALSA: ctxfi - Fix SPDIF status retrieval
ALSA: ctxfi - Fix incorrect SPDIF status bit mask
ALSA: ctxfi - Fix microphone boost codes/comments
ALSA: atiixp - Fix wrong time-out checks during ac-link reset
ALSA: intel8x0m: append 'm' to "r_intel8x0"
...
254 files changed, 27080 insertions, 9623 deletions
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index 4303a86e6e38..3e6f0aab460b 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c | |||
@@ -119,13 +119,6 @@ static struct platform_device keysc_device = { | |||
119 | }; | 119 | }; |
120 | 120 | ||
121 | /* FSI A */ | 121 | /* FSI A */ |
122 | static struct sh_fsi_platform_info fsi_info = { | ||
123 | .porta_flags = SH_FSI_OUT_SLAVE_MODE | | ||
124 | SH_FSI_IN_SLAVE_MODE | | ||
125 | SH_FSI_OFMT(I2S) | | ||
126 | SH_FSI_IFMT(I2S), | ||
127 | }; | ||
128 | |||
129 | static struct resource fsi_resources[] = { | 122 | static struct resource fsi_resources[] = { |
130 | [0] = { | 123 | [0] = { |
131 | .name = "FSI", | 124 | .name = "FSI", |
@@ -144,9 +137,6 @@ static struct platform_device fsi_device = { | |||
144 | .id = -1, | 137 | .id = -1, |
145 | .num_resources = ARRAY_SIZE(fsi_resources), | 138 | .num_resources = ARRAY_SIZE(fsi_resources), |
146 | .resource = fsi_resources, | 139 | .resource = fsi_resources, |
147 | .dev = { | ||
148 | .platform_data = &fsi_info, | ||
149 | }, | ||
150 | }; | 140 | }; |
151 | 141 | ||
152 | static struct resource sh_mmcif_resources[] = { | 142 | static struct resource sh_mmcif_resources[] = { |
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index 81d6536552a9..1a8118c929be 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c | |||
@@ -673,16 +673,12 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable) | |||
673 | } | 673 | } |
674 | 674 | ||
675 | static struct sh_fsi_platform_info fsi_info = { | 675 | static struct sh_fsi_platform_info fsi_info = { |
676 | .porta_flags = SH_FSI_BRS_INV | | 676 | .porta_flags = SH_FSI_BRS_INV, |
677 | SH_FSI_OUT_SLAVE_MODE | | ||
678 | SH_FSI_IN_SLAVE_MODE | | ||
679 | SH_FSI_OFMT(PCM) | | ||
680 | SH_FSI_IFMT(PCM), | ||
681 | 677 | ||
682 | .portb_flags = SH_FSI_BRS_INV | | 678 | .portb_flags = SH_FSI_BRS_INV | |
683 | SH_FSI_BRM_INV | | 679 | SH_FSI_BRM_INV | |
684 | SH_FSI_LRS_INV | | 680 | SH_FSI_LRS_INV | |
685 | SH_FSI_OFMT(SPDIF), | 681 | SH_FSI_FMT_SPDIF, |
686 | .set_rate = fsi_set_rate, | 682 | .set_rate = fsi_set_rate, |
687 | }; | 683 | }; |
688 | 684 | ||
@@ -783,6 +779,10 @@ static struct platform_device hdmi_device = { | |||
783 | }, | 779 | }, |
784 | }; | 780 | }; |
785 | 781 | ||
782 | static struct platform_device fsi_hdmi_device = { | ||
783 | .name = "sh_fsi2_b_hdmi", | ||
784 | }; | ||
785 | |||
786 | static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq, | 786 | static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq, |
787 | unsigned long *parent_freq) | 787 | unsigned long *parent_freq) |
788 | { | 788 | { |
@@ -936,6 +936,7 @@ static struct platform_device *ap4evb_devices[] __initdata = { | |||
936 | &usb1_host_device, | 936 | &usb1_host_device, |
937 | &fsi_device, | 937 | &fsi_device, |
938 | &fsi_ak4643_device, | 938 | &fsi_ak4643_device, |
939 | &fsi_hdmi_device, | ||
939 | &sh_mmcif_device, | 940 | &sh_mmcif_device, |
940 | &lcdc1_device, | 941 | &lcdc1_device, |
941 | &lcdc_device, | 942 | &lcdc_device, |
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 1657eac5dde2..1a63c213e45d 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c | |||
@@ -399,6 +399,10 @@ static struct platform_device hdmi_device = { | |||
399 | }, | 399 | }, |
400 | }; | 400 | }; |
401 | 401 | ||
402 | static struct platform_device fsi_hdmi_device = { | ||
403 | .name = "sh_fsi2_b_hdmi", | ||
404 | }; | ||
405 | |||
402 | static int __init hdmi_init_pm_clock(void) | 406 | static int __init hdmi_init_pm_clock(void) |
403 | { | 407 | { |
404 | struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick"); | 408 | struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick"); |
@@ -609,16 +613,12 @@ fsi_set_rate_end: | |||
609 | } | 613 | } |
610 | 614 | ||
611 | static struct sh_fsi_platform_info fsi_info = { | 615 | static struct sh_fsi_platform_info fsi_info = { |
612 | .porta_flags = SH_FSI_BRS_INV | | 616 | .porta_flags = SH_FSI_BRS_INV, |
613 | SH_FSI_OUT_SLAVE_MODE | | ||
614 | SH_FSI_IN_SLAVE_MODE | | ||
615 | SH_FSI_OFMT(PCM) | | ||
616 | SH_FSI_IFMT(PCM), | ||
617 | 617 | ||
618 | .portb_flags = SH_FSI_BRS_INV | | 618 | .portb_flags = SH_FSI_BRS_INV | |
619 | SH_FSI_BRM_INV | | 619 | SH_FSI_BRM_INV | |
620 | SH_FSI_LRS_INV | | 620 | SH_FSI_LRS_INV | |
621 | SH_FSI_OFMT(SPDIF), | 621 | SH_FSI_FMT_SPDIF, |
622 | 622 | ||
623 | .set_rate = fsi_set_rate, | 623 | .set_rate = fsi_set_rate, |
624 | }; | 624 | }; |
@@ -921,6 +921,7 @@ static struct platform_device *mackerel_devices[] __initdata = { | |||
921 | &leds_device, | 921 | &leds_device, |
922 | &fsi_device, | 922 | &fsi_device, |
923 | &fsi_ak4643_device, | 923 | &fsi_ak4643_device, |
924 | &fsi_hdmi_device, | ||
924 | &sdhi0_device, | 925 | &sdhi0_device, |
925 | #if !defined(CONFIG_MMC_SH_MMCIF) | 926 | #if !defined(CONFIG_MMC_SH_MMCIF) |
926 | &sdhi1_device, | 927 | &sdhi1_device, |
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 3b71d2190de1..e44480ce2ea8 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c | |||
@@ -725,11 +725,7 @@ static struct platform_device camera_devices[] = { | |||
725 | 725 | ||
726 | /* FSI */ | 726 | /* FSI */ |
727 | static struct sh_fsi_platform_info fsi_info = { | 727 | static struct sh_fsi_platform_info fsi_info = { |
728 | .portb_flags = SH_FSI_BRS_INV | | 728 | .portb_flags = SH_FSI_BRS_INV, |
729 | SH_FSI_OUT_SLAVE_MODE | | ||
730 | SH_FSI_IN_SLAVE_MODE | | ||
731 | SH_FSI_OFMT(I2S) | | ||
732 | SH_FSI_IFMT(I2S), | ||
733 | }; | 729 | }; |
734 | 730 | ||
735 | static struct resource fsi_resources[] = { | 731 | static struct resource fsi_resources[] = { |
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 527679394a25..c8bcf6a19b55 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c | |||
@@ -286,11 +286,7 @@ static struct platform_device ceu1_device = { | |||
286 | /* FSI */ | 286 | /* FSI */ |
287 | /* change J20, J21, J22 pin to 1-2 connection to use slave mode */ | 287 | /* change J20, J21, J22 pin to 1-2 connection to use slave mode */ |
288 | static struct sh_fsi_platform_info fsi_info = { | 288 | static struct sh_fsi_platform_info fsi_info = { |
289 | .porta_flags = SH_FSI_BRS_INV | | 289 | .porta_flags = SH_FSI_BRS_INV, |
290 | SH_FSI_OUT_SLAVE_MODE | | ||
291 | SH_FSI_IN_SLAVE_MODE | | ||
292 | SH_FSI_OFMT(PCM) | | ||
293 | SH_FSI_IFMT(PCM), | ||
294 | }; | 290 | }; |
295 | 291 | ||
296 | static struct resource fsi_resources[] = { | 292 | static struct resource fsi_resources[] = { |
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index c003fa4e2db1..c8658888e67b 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c | |||
@@ -362,3 +362,4 @@ void fw_iso_resource_manage(struct fw_card *card, int generation, | |||
362 | *channel = ret; | 362 | *channel = ret; |
363 | } | 363 | } |
364 | } | 364 | } |
365 | EXPORT_SYMBOL(fw_iso_resource_manage); | ||
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index f8dfcf1c6cbe..25e729cde2f7 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
@@ -147,9 +147,6 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event); | |||
147 | /* -iso */ | 147 | /* -iso */ |
148 | 148 | ||
149 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); | 149 | int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma); |
150 | void fw_iso_resource_manage(struct fw_card *card, int generation, | ||
151 | u64 channels_mask, int *channel, int *bandwidth, | ||
152 | bool allocate, __be32 buffer[2]); | ||
153 | 150 | ||
154 | 151 | ||
155 | /* -topology */ | 152 | /* -topology */ |
diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 9a3f5f9383f6..fc023d67676f 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h | |||
@@ -42,6 +42,10 @@ | |||
42 | #define CSR_BROADCAST_CHANNEL 0x234 | 42 | #define CSR_BROADCAST_CHANNEL 0x234 |
43 | #define CSR_CONFIG_ROM 0x400 | 43 | #define CSR_CONFIG_ROM 0x400 |
44 | #define CSR_CONFIG_ROM_END 0x800 | 44 | #define CSR_CONFIG_ROM_END 0x800 |
45 | #define CSR_OMPR 0x900 | ||
46 | #define CSR_OPCR(i) (0x904 + (i) * 4) | ||
47 | #define CSR_IMPR 0x980 | ||
48 | #define CSR_IPCR(i) (0x984 + (i) * 4) | ||
45 | #define CSR_FCP_COMMAND 0xB00 | 49 | #define CSR_FCP_COMMAND 0xB00 |
46 | #define CSR_FCP_RESPONSE 0xD00 | 50 | #define CSR_FCP_RESPONSE 0xD00 |
47 | #define CSR_FCP_END 0xF00 | 51 | #define CSR_FCP_END 0xF00 |
@@ -441,5 +445,8 @@ int fw_iso_context_start(struct fw_iso_context *ctx, | |||
441 | int cycle, int sync, int tags); | 445 | int cycle, int sync, int tags); |
442 | int fw_iso_context_stop(struct fw_iso_context *ctx); | 446 | int fw_iso_context_stop(struct fw_iso_context *ctx); |
443 | void fw_iso_context_destroy(struct fw_iso_context *ctx); | 447 | void fw_iso_context_destroy(struct fw_iso_context *ctx); |
448 | void fw_iso_resource_manage(struct fw_card *card, int generation, | ||
449 | u64 channels_mask, int *channel, int *bandwidth, | ||
450 | bool allocate, __be32 buffer[2]); | ||
444 | 451 | ||
445 | #endif /* _LINUX_FIREWIRE_H */ | 452 | #endif /* _LINUX_FIREWIRE_H */ |
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index 9eab263658be..466b1c777aff 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h | |||
@@ -103,13 +103,21 @@ struct wm8994_pdata { | |||
103 | unsigned int lineout1fb:1; | 103 | unsigned int lineout1fb:1; |
104 | unsigned int lineout2fb:1; | 104 | unsigned int lineout2fb:1; |
105 | 105 | ||
106 | /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ | 106 | /* IRQ for microphone detection if brought out directly as a |
107 | * signal. | ||
108 | */ | ||
109 | int micdet_irq; | ||
110 | |||
111 | /* WM8994 microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ | ||
107 | unsigned int micbias1_lvl:1; | 112 | unsigned int micbias1_lvl:1; |
108 | unsigned int micbias2_lvl:1; | 113 | unsigned int micbias2_lvl:1; |
109 | 114 | ||
110 | /* Jack detect threashold levels, see datasheet for values */ | 115 | /* WM8994 jack detect threashold levels, see datasheet for values */ |
111 | unsigned int jd_scthr:2; | 116 | unsigned int jd_scthr:2; |
112 | unsigned int jd_thr:2; | 117 | unsigned int jd_thr:2; |
118 | |||
119 | /* WM8958 microphone bias configuration */ | ||
120 | int micbias[2]; | ||
113 | }; | 121 | }; |
114 | 122 | ||
115 | #endif | 123 | #endif |
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h index be072faec6f0..f3ee84284670 100644 --- a/include/linux/mfd/wm8994/registers.h +++ b/include/linux/mfd/wm8994/registers.h | |||
@@ -63,6 +63,8 @@ | |||
63 | #define WM8994_MICBIAS 0x3A | 63 | #define WM8994_MICBIAS 0x3A |
64 | #define WM8994_LDO_1 0x3B | 64 | #define WM8994_LDO_1 0x3B |
65 | #define WM8994_LDO_2 0x3C | 65 | #define WM8994_LDO_2 0x3C |
66 | #define WM8958_MICBIAS1 0x3D | ||
67 | #define WM8958_MICBIAS2 0x3E | ||
66 | #define WM8994_CHARGE_PUMP_1 0x4C | 68 | #define WM8994_CHARGE_PUMP_1 0x4C |
67 | #define WM8958_CHARGE_PUMP_2 0x4D | 69 | #define WM8958_CHARGE_PUMP_2 0x4D |
68 | #define WM8994_CLASS_W_1 0x51 | 70 | #define WM8994_CLASS_W_1 0x51 |
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index b602f475cdbb..f1dcefe4532b 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h | |||
@@ -96,6 +96,10 @@ | |||
96 | #define AC97_FUNC_INFO 0x68 /* Function Information */ | 96 | #define AC97_FUNC_INFO 0x68 /* Function Information */ |
97 | #define AC97_SENSE_INFO 0x6a /* Sense Details */ | 97 | #define AC97_SENSE_INFO 0x6a /* Sense Details */ |
98 | 98 | ||
99 | /* volume controls */ | ||
100 | #define AC97_MUTE_MASK_MONO 0x8000 | ||
101 | #define AC97_MUTE_MASK_STEREO 0x8080 | ||
102 | |||
99 | /* slot allocation */ | 103 | /* slot allocation */ |
100 | #define AC97_SLOT_TAG 0 | 104 | #define AC97_SLOT_TAG 0 |
101 | #define AC97_SLOT_CMD_ADDR 1 | 105 | #define AC97_SLOT_CMD_ADDR 1 |
@@ -138,6 +142,7 @@ | |||
138 | #define AC97_BC_18BIT_ADC 0x0100 /* 18-bit ADC resolution */ | 142 | #define AC97_BC_18BIT_ADC 0x0100 /* 18-bit ADC resolution */ |
139 | #define AC97_BC_20BIT_ADC 0x0200 /* 20-bit ADC resolution */ | 143 | #define AC97_BC_20BIT_ADC 0x0200 /* 20-bit ADC resolution */ |
140 | #define AC97_BC_ADC_MASK 0x0300 | 144 | #define AC97_BC_ADC_MASK 0x0300 |
145 | #define AC97_BC_3D_TECH_ID_MASK 0x7c00 /* Per-vendor ID of 3D enhancement */ | ||
141 | 146 | ||
142 | /* general purpose */ | 147 | /* general purpose */ |
143 | #define AC97_GP_DRSS_MASK 0x0c00 /* double rate slot select */ | 148 | #define AC97_GP_DRSS_MASK 0x0c00 /* double rate slot select */ |
diff --git a/include/sound/control.h b/include/sound/control.h index 7715e6f00d38..e67db2869360 100644 --- a/include/sound/control.h +++ b/include/sound/control.h | |||
@@ -115,6 +115,8 @@ int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol); | |||
115 | int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol); | 115 | int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol); |
116 | int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); | 116 | int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); |
117 | int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); | 117 | int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); |
118 | int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, | ||
119 | int active); | ||
118 | struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid); | 120 | struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid); |
119 | struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id); | 121 | struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id); |
120 | 122 | ||
diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h new file mode 100644 index 000000000000..50a059e7d116 --- /dev/null +++ b/include/sound/cs4271.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Definitions for CS4271 ASoC codec driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (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 | |||
17 | #ifndef __CS4271_H | ||
18 | #define __CS4271_H | ||
19 | |||
20 | struct cs4271_platform_data { | ||
21 | int gpio_nreset; /* GPIO driving Reset pin, if any */ | ||
22 | }; | ||
23 | |||
24 | #endif /* __CS4271_H */ | ||
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h index 81990b2bcc98..1774ff5ff632 100644 --- a/include/sound/hdspm.h +++ b/include/sound/hdspm.h | |||
@@ -3,8 +3,8 @@ | |||
3 | /* | 3 | /* |
4 | * Copyright (C) 2003 Winfried Ritsch (IEM) | 4 | * Copyright (C) 2003 Winfried Ritsch (IEM) |
5 | * based on hdsp.h from Thomas Charbonnel (thomas@undata.org) | 5 | * based on hdsp.h from Thomas Charbonnel (thomas@undata.org) |
6 | * | 6 | * |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 10 | * the Free Software Foundation; either version 2 of the License, or |
@@ -23,50 +23,41 @@ | |||
23 | /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ | 23 | /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */ |
24 | #define HDSPM_MAX_CHANNELS 64 | 24 | #define HDSPM_MAX_CHANNELS 64 |
25 | 25 | ||
26 | /* -------------------- IOCTL Peak/RMS Meters -------------------- */ | 26 | enum hdspm_io_type { |
27 | 27 | MADI, | |
28 | /* peam rms level structure like we get from hardware | 28 | MADIface, |
29 | 29 | AIO, | |
30 | maybe in future we can memory map it so I just copy it | 30 | AES32, |
31 | to user on ioctl call now an dont change anything | 31 | RayDAT |
32 | rms are made out of low and high values | 32 | }; |
33 | where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24) | ||
34 | (i asume so from the code) | ||
35 | */ | ||
36 | |||
37 | struct hdspm_peak_rms { | ||
38 | |||
39 | unsigned int level_offset[1024]; | ||
40 | 33 | ||
41 | unsigned int input_peak[64]; | 34 | enum hdspm_speed { |
42 | unsigned int playback_peak[64]; | 35 | ss, |
43 | unsigned int output_peak[64]; | 36 | ds, |
44 | unsigned int xxx_peak[64]; /* not used */ | 37 | qs |
38 | }; | ||
45 | 39 | ||
46 | unsigned int reserved[256]; /* not used */ | 40 | /* -------------------- IOCTL Peak/RMS Meters -------------------- */ |
47 | 41 | ||
48 | unsigned int input_rms_l[64]; | 42 | struct hdspm_peak_rms { |
49 | unsigned int playback_rms_l[64]; | 43 | uint32_t input_peaks[64]; |
50 | unsigned int output_rms_l[64]; | 44 | uint32_t playback_peaks[64]; |
51 | unsigned int xxx_rms_l[64]; /* not used */ | 45 | uint32_t output_peaks[64]; |
52 | 46 | ||
53 | unsigned int input_rms_h[64]; | 47 | uint64_t input_rms[64]; |
54 | unsigned int playback_rms_h[64]; | 48 | uint64_t playback_rms[64]; |
55 | unsigned int output_rms_h[64]; | 49 | uint64_t output_rms[64]; |
56 | unsigned int xxx_rms_h[64]; /* not used */ | ||
57 | }; | ||
58 | 50 | ||
59 | struct hdspm_peak_rms_ioctl { | 51 | uint8_t speed; /* enum {ss, ds, qs} */ |
60 | struct hdspm_peak_rms *peak; | 52 | int status2; |
61 | }; | 53 | }; |
62 | 54 | ||
63 | /* use indirect access due to the limit of ioctl bit size */ | ||
64 | #define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \ | 55 | #define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \ |
65 | _IOR('H', 0x40, struct hdspm_peak_rms_ioctl) | 56 | _IOR('H', 0x42, struct hdspm_peak_rms) |
66 | 57 | ||
67 | /* ------------ CONFIG block IOCTL ---------------------- */ | 58 | /* ------------ CONFIG block IOCTL ---------------------- */ |
68 | 59 | ||
69 | struct hdspm_config_info { | 60 | struct hdspm_config { |
70 | unsigned char pref_sync_ref; | 61 | unsigned char pref_sync_ref; |
71 | unsigned char wordclock_sync_check; | 62 | unsigned char wordclock_sync_check; |
72 | unsigned char madi_sync_check; | 63 | unsigned char madi_sync_check; |
@@ -80,18 +71,121 @@ struct hdspm_config_info { | |||
80 | unsigned int analog_out; | 71 | unsigned int analog_out; |
81 | }; | 72 | }; |
82 | 73 | ||
83 | #define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO \ | 74 | #define SNDRV_HDSPM_IOCTL_GET_CONFIG \ |
84 | _IOR('H', 0x41, struct hdspm_config_info) | 75 | _IOR('H', 0x41, struct hdspm_config) |
76 | |||
77 | /** | ||
78 | * If there's a TCO (TimeCode Option) board installed, | ||
79 | * there are further options and status data available. | ||
80 | * The hdspm_ltc structure contains the current SMPTE | ||
81 | * timecode and some status information and can be | ||
82 | * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the | ||
83 | * hdspm_status struct. | ||
84 | **/ | ||
85 | |||
86 | enum hdspm_ltc_format { | ||
87 | format_invalid, | ||
88 | fps_24, | ||
89 | fps_25, | ||
90 | fps_2997, | ||
91 | fps_30 | ||
92 | }; | ||
93 | |||
94 | enum hdspm_ltc_frame { | ||
95 | frame_invalid, | ||
96 | drop_frame, | ||
97 | full_frame | ||
98 | }; | ||
99 | |||
100 | enum hdspm_ltc_input_format { | ||
101 | ntsc, | ||
102 | pal, | ||
103 | no_video | ||
104 | }; | ||
105 | |||
106 | struct hdspm_ltc { | ||
107 | unsigned int ltc; | ||
85 | 108 | ||
109 | enum hdspm_ltc_format format; | ||
110 | enum hdspm_ltc_frame frame; | ||
111 | enum hdspm_ltc_input_format input_format; | ||
112 | }; | ||
113 | |||
114 | #define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl) | ||
115 | |||
116 | /** | ||
117 | * The status data reflects the device's current state | ||
118 | * as determined by the card's configuration and | ||
119 | * connection status. | ||
120 | **/ | ||
121 | |||
122 | enum hdspm_sync { | ||
123 | hdspm_sync_no_lock = 0, | ||
124 | hdspm_sync_lock = 1, | ||
125 | hdspm_sync_sync = 2 | ||
126 | }; | ||
86 | 127 | ||
87 | /* get Soundcard Version */ | 128 | enum hdspm_madi_input { |
129 | hdspm_input_optical = 0, | ||
130 | hdspm_input_coax = 1 | ||
131 | }; | ||
132 | |||
133 | enum hdspm_madi_channel_format { | ||
134 | hdspm_format_ch_64 = 0, | ||
135 | hdspm_format_ch_56 = 1 | ||
136 | }; | ||
137 | |||
138 | enum hdspm_madi_frame_format { | ||
139 | hdspm_frame_48 = 0, | ||
140 | hdspm_frame_96 = 1 | ||
141 | }; | ||
142 | |||
143 | enum hdspm_syncsource { | ||
144 | syncsource_wc = 0, | ||
145 | syncsource_madi = 1, | ||
146 | syncsource_tco = 2, | ||
147 | syncsource_sync = 3, | ||
148 | syncsource_none = 4 | ||
149 | }; | ||
150 | |||
151 | struct hdspm_status { | ||
152 | uint8_t card_type; /* enum hdspm_io_type */ | ||
153 | enum hdspm_syncsource autosync_source; | ||
154 | |||
155 | uint64_t card_clock; | ||
156 | uint32_t master_period; | ||
157 | |||
158 | union { | ||
159 | struct { | ||
160 | uint8_t sync_wc; /* enum hdspm_sync */ | ||
161 | uint8_t sync_madi; /* enum hdspm_sync */ | ||
162 | uint8_t sync_tco; /* enum hdspm_sync */ | ||
163 | uint8_t sync_in; /* enum hdspm_sync */ | ||
164 | uint8_t madi_input; /* enum hdspm_madi_input */ | ||
165 | uint8_t channel_format; /* enum hdspm_madi_channel_format */ | ||
166 | uint8_t frame_format; /* enum hdspm_madi_frame_format */ | ||
167 | } madi; | ||
168 | } card_specific; | ||
169 | }; | ||
170 | |||
171 | #define SNDRV_HDSPM_IOCTL_GET_STATUS \ | ||
172 | _IOR('H', 0x47, struct hdspm_status) | ||
173 | |||
174 | /** | ||
175 | * Get information about the card and its add-ons. | ||
176 | **/ | ||
177 | |||
178 | #define HDSPM_ADDON_TCO 1 | ||
88 | 179 | ||
89 | struct hdspm_version { | 180 | struct hdspm_version { |
181 | uint8_t card_type; /* enum hdspm_io_type */ | ||
182 | char cardname[20]; | ||
183 | unsigned int serial; | ||
90 | unsigned short firmware_rev; | 184 | unsigned short firmware_rev; |
185 | int addons; | ||
91 | }; | 186 | }; |
92 | 187 | ||
93 | #define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdspm_version) | 188 | #define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version) |
94 | |||
95 | 189 | ||
96 | /* ------------- get Matrix Mixer IOCTL --------------- */ | 190 | /* ------------- get Matrix Mixer IOCTL --------------- */ |
97 | 191 | ||
@@ -103,7 +197,7 @@ struct hdspm_version { | |||
103 | /* equivalent to hardware definition, maybe for future feature of mmap of | 197 | /* equivalent to hardware definition, maybe for future feature of mmap of |
104 | * them | 198 | * them |
105 | */ | 199 | */ |
106 | /* each of 64 outputs has 64 infader and 64 outfader: | 200 | /* each of 64 outputs has 64 infader and 64 outfader: |
107 | Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */ | 201 | Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */ |
108 | 202 | ||
109 | #define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS | 203 | #define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS |
@@ -131,4 +225,5 @@ typedef struct hdspm_version hdspm_version_t; | |||
131 | typedef struct hdspm_channelfader snd_hdspm_channelfader_t; | 225 | typedef struct hdspm_channelfader snd_hdspm_channelfader_t; |
132 | typedef struct hdspm_mixer hdspm_mixer_t; | 226 | typedef struct hdspm_mixer hdspm_mixer_t; |
133 | 227 | ||
134 | #endif /* __SOUND_HDSPM_H */ | 228 | |
229 | #endif | ||
diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h index 51fbcb4a277a..13cb0b430a1b 100644 --- a/include/sound/mixer_oss.h +++ b/include/sound/mixer_oss.h | |||
@@ -73,6 +73,9 @@ struct snd_mixer_oss_file { | |||
73 | struct snd_mixer_oss *mixer; | 73 | struct snd_mixer_oss *mixer; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | int snd_mixer_oss_ioctl_card(struct snd_card *card, | ||
77 | unsigned int cmd, unsigned long arg); | ||
78 | |||
76 | #endif /* CONFIG_SND_MIXER_OSS */ | 79 | #endif /* CONFIG_SND_MIXER_OSS */ |
77 | 80 | ||
78 | #endif /* __SOUND_MIXER_OSS_H */ | 81 | #endif /* __SOUND_MIXER_OSS_H */ |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index e731f8d71934..430a9cc045e2 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -136,48 +136,49 @@ struct snd_pcm_ops { | |||
136 | SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) | 136 | SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000) |
137 | #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ | 137 | #define SNDRV_PCM_RATE_8000_192000 (SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\ |
138 | SNDRV_PCM_RATE_192000) | 138 | SNDRV_PCM_RATE_192000) |
139 | #define SNDRV_PCM_FMTBIT_S8 (1ULL << SNDRV_PCM_FORMAT_S8) | 139 | #define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt) |
140 | #define SNDRV_PCM_FMTBIT_U8 (1ULL << SNDRV_PCM_FORMAT_U8) | 140 | #define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8) |
141 | #define SNDRV_PCM_FMTBIT_S16_LE (1ULL << SNDRV_PCM_FORMAT_S16_LE) | 141 | #define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8) |
142 | #define SNDRV_PCM_FMTBIT_S16_BE (1ULL << SNDRV_PCM_FORMAT_S16_BE) | 142 | #define SNDRV_PCM_FMTBIT_S16_LE _SNDRV_PCM_FMTBIT(S16_LE) |
143 | #define SNDRV_PCM_FMTBIT_U16_LE (1ULL << SNDRV_PCM_FORMAT_U16_LE) | 143 | #define SNDRV_PCM_FMTBIT_S16_BE _SNDRV_PCM_FMTBIT(S16_BE) |
144 | #define SNDRV_PCM_FMTBIT_U16_BE (1ULL << SNDRV_PCM_FORMAT_U16_BE) | 144 | #define SNDRV_PCM_FMTBIT_U16_LE _SNDRV_PCM_FMTBIT(U16_LE) |
145 | #define SNDRV_PCM_FMTBIT_S24_LE (1ULL << SNDRV_PCM_FORMAT_S24_LE) | 145 | #define SNDRV_PCM_FMTBIT_U16_BE _SNDRV_PCM_FMTBIT(U16_BE) |
146 | #define SNDRV_PCM_FMTBIT_S24_BE (1ULL << SNDRV_PCM_FORMAT_S24_BE) | 146 | #define SNDRV_PCM_FMTBIT_S24_LE _SNDRV_PCM_FMTBIT(S24_LE) |
147 | #define SNDRV_PCM_FMTBIT_U24_LE (1ULL << SNDRV_PCM_FORMAT_U24_LE) | 147 | #define SNDRV_PCM_FMTBIT_S24_BE _SNDRV_PCM_FMTBIT(S24_BE) |
148 | #define SNDRV_PCM_FMTBIT_U24_BE (1ULL << SNDRV_PCM_FORMAT_U24_BE) | 148 | #define SNDRV_PCM_FMTBIT_U24_LE _SNDRV_PCM_FMTBIT(U24_LE) |
149 | #define SNDRV_PCM_FMTBIT_S32_LE (1ULL << SNDRV_PCM_FORMAT_S32_LE) | 149 | #define SNDRV_PCM_FMTBIT_U24_BE _SNDRV_PCM_FMTBIT(U24_BE) |
150 | #define SNDRV_PCM_FMTBIT_S32_BE (1ULL << SNDRV_PCM_FORMAT_S32_BE) | 150 | #define SNDRV_PCM_FMTBIT_S32_LE _SNDRV_PCM_FMTBIT(S32_LE) |
151 | #define SNDRV_PCM_FMTBIT_U32_LE (1ULL << SNDRV_PCM_FORMAT_U32_LE) | 151 | #define SNDRV_PCM_FMTBIT_S32_BE _SNDRV_PCM_FMTBIT(S32_BE) |
152 | #define SNDRV_PCM_FMTBIT_U32_BE (1ULL << SNDRV_PCM_FORMAT_U32_BE) | 152 | #define SNDRV_PCM_FMTBIT_U32_LE _SNDRV_PCM_FMTBIT(U32_LE) |
153 | #define SNDRV_PCM_FMTBIT_FLOAT_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT_LE) | 153 | #define SNDRV_PCM_FMTBIT_U32_BE _SNDRV_PCM_FMTBIT(U32_BE) |
154 | #define SNDRV_PCM_FMTBIT_FLOAT_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT_BE) | 154 | #define SNDRV_PCM_FMTBIT_FLOAT_LE _SNDRV_PCM_FMTBIT(FLOAT_LE) |
155 | #define SNDRV_PCM_FMTBIT_FLOAT64_LE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE) | 155 | #define SNDRV_PCM_FMTBIT_FLOAT_BE _SNDRV_PCM_FMTBIT(FLOAT_BE) |
156 | #define SNDRV_PCM_FMTBIT_FLOAT64_BE (1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE) | 156 | #define SNDRV_PCM_FMTBIT_FLOAT64_LE _SNDRV_PCM_FMTBIT(FLOAT64_LE) |
157 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE) | 157 | #define SNDRV_PCM_FMTBIT_FLOAT64_BE _SNDRV_PCM_FMTBIT(FLOAT64_BE) |
158 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE) | 158 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_LE) |
159 | #define SNDRV_PCM_FMTBIT_MU_LAW (1ULL << SNDRV_PCM_FORMAT_MU_LAW) | 159 | #define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_BE) |
160 | #define SNDRV_PCM_FMTBIT_A_LAW (1ULL << SNDRV_PCM_FORMAT_A_LAW) | 160 | #define SNDRV_PCM_FMTBIT_MU_LAW _SNDRV_PCM_FMTBIT(MU_LAW) |
161 | #define SNDRV_PCM_FMTBIT_IMA_ADPCM (1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM) | 161 | #define SNDRV_PCM_FMTBIT_A_LAW _SNDRV_PCM_FMTBIT(A_LAW) |
162 | #define SNDRV_PCM_FMTBIT_MPEG (1ULL << SNDRV_PCM_FORMAT_MPEG) | 162 | #define SNDRV_PCM_FMTBIT_IMA_ADPCM _SNDRV_PCM_FMTBIT(IMA_ADPCM) |
163 | #define SNDRV_PCM_FMTBIT_GSM (1ULL << SNDRV_PCM_FORMAT_GSM) | 163 | #define SNDRV_PCM_FMTBIT_MPEG _SNDRV_PCM_FMTBIT(MPEG) |
164 | #define SNDRV_PCM_FMTBIT_SPECIAL (1ULL << SNDRV_PCM_FORMAT_SPECIAL) | 164 | #define SNDRV_PCM_FMTBIT_GSM _SNDRV_PCM_FMTBIT(GSM) |
165 | #define SNDRV_PCM_FMTBIT_S24_3LE (1ULL << SNDRV_PCM_FORMAT_S24_3LE) | 165 | #define SNDRV_PCM_FMTBIT_SPECIAL _SNDRV_PCM_FMTBIT(SPECIAL) |
166 | #define SNDRV_PCM_FMTBIT_U24_3LE (1ULL << SNDRV_PCM_FORMAT_U24_3LE) | 166 | #define SNDRV_PCM_FMTBIT_S24_3LE _SNDRV_PCM_FMTBIT(S24_3LE) |
167 | #define SNDRV_PCM_FMTBIT_S24_3BE (1ULL << SNDRV_PCM_FORMAT_S24_3BE) | 167 | #define SNDRV_PCM_FMTBIT_U24_3LE _SNDRV_PCM_FMTBIT(U24_3LE) |
168 | #define SNDRV_PCM_FMTBIT_U24_3BE (1ULL << SNDRV_PCM_FORMAT_U24_3BE) | 168 | #define SNDRV_PCM_FMTBIT_S24_3BE _SNDRV_PCM_FMTBIT(S24_3BE) |
169 | #define SNDRV_PCM_FMTBIT_S20_3LE (1ULL << SNDRV_PCM_FORMAT_S20_3LE) | 169 | #define SNDRV_PCM_FMTBIT_U24_3BE _SNDRV_PCM_FMTBIT(U24_3BE) |
170 | #define SNDRV_PCM_FMTBIT_U20_3LE (1ULL << SNDRV_PCM_FORMAT_U20_3LE) | 170 | #define SNDRV_PCM_FMTBIT_S20_3LE _SNDRV_PCM_FMTBIT(S20_3LE) |
171 | #define SNDRV_PCM_FMTBIT_S20_3BE (1ULL << SNDRV_PCM_FORMAT_S20_3BE) | 171 | #define SNDRV_PCM_FMTBIT_U20_3LE _SNDRV_PCM_FMTBIT(U20_3LE) |
172 | #define SNDRV_PCM_FMTBIT_U20_3BE (1ULL << SNDRV_PCM_FORMAT_U20_3BE) | 172 | #define SNDRV_PCM_FMTBIT_S20_3BE _SNDRV_PCM_FMTBIT(S20_3BE) |
173 | #define SNDRV_PCM_FMTBIT_S18_3LE (1ULL << SNDRV_PCM_FORMAT_S18_3LE) | 173 | #define SNDRV_PCM_FMTBIT_U20_3BE _SNDRV_PCM_FMTBIT(U20_3BE) |
174 | #define SNDRV_PCM_FMTBIT_U18_3LE (1ULL << SNDRV_PCM_FORMAT_U18_3LE) | 174 | #define SNDRV_PCM_FMTBIT_S18_3LE _SNDRV_PCM_FMTBIT(S18_3LE) |
175 | #define SNDRV_PCM_FMTBIT_S18_3BE (1ULL << SNDRV_PCM_FORMAT_S18_3BE) | 175 | #define SNDRV_PCM_FMTBIT_U18_3LE _SNDRV_PCM_FMTBIT(U18_3LE) |
176 | #define SNDRV_PCM_FMTBIT_U18_3BE (1ULL << SNDRV_PCM_FORMAT_U18_3BE) | 176 | #define SNDRV_PCM_FMTBIT_S18_3BE _SNDRV_PCM_FMTBIT(S18_3BE) |
177 | #define SNDRV_PCM_FMTBIT_G723_24 (1ULL << SNDRV_PCM_FORMAT_G723_24) | 177 | #define SNDRV_PCM_FMTBIT_U18_3BE _SNDRV_PCM_FMTBIT(U18_3BE) |
178 | #define SNDRV_PCM_FMTBIT_G723_24_1B (1ULL << SNDRV_PCM_FORMAT_G723_24_1B) | 178 | #define SNDRV_PCM_FMTBIT_G723_24 _SNDRV_PCM_FMTBIT(G723_24) |
179 | #define SNDRV_PCM_FMTBIT_G723_40 (1ULL << SNDRV_PCM_FORMAT_G723_40) | 179 | #define SNDRV_PCM_FMTBIT_G723_24_1B _SNDRV_PCM_FMTBIT(G723_24_1B) |
180 | #define SNDRV_PCM_FMTBIT_G723_40_1B (1ULL << SNDRV_PCM_FORMAT_G723_40_1B) | 180 | #define SNDRV_PCM_FMTBIT_G723_40 _SNDRV_PCM_FMTBIT(G723_40) |
181 | #define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B) | ||
181 | 182 | ||
182 | #ifdef SNDRV_LITTLE_ENDIAN | 183 | #ifdef SNDRV_LITTLE_ENDIAN |
183 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE | 184 | #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE |
@@ -490,7 +491,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream, | |||
490 | int snd_pcm_status(struct snd_pcm_substream *substream, | 491 | int snd_pcm_status(struct snd_pcm_substream *substream, |
491 | struct snd_pcm_status *status); | 492 | struct snd_pcm_status *status); |
492 | int snd_pcm_start(struct snd_pcm_substream *substream); | 493 | int snd_pcm_start(struct snd_pcm_substream *substream); |
493 | int snd_pcm_stop(struct snd_pcm_substream *substream, int status); | 494 | int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status); |
494 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); | 495 | int snd_pcm_drain_done(struct snd_pcm_substream *substream); |
495 | #ifdef CONFIG_PM | 496 | #ifdef CONFIG_PM |
496 | int snd_pcm_suspend(struct snd_pcm_substream *substream); | 497 | int snd_pcm_suspend(struct snd_pcm_substream *substream); |
@@ -748,8 +749,8 @@ static inline const struct snd_interval *hw_param_interval_c(const struct snd_pc | |||
748 | return ¶ms->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; | 749 | return ¶ms->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]; |
749 | } | 750 | } |
750 | 751 | ||
751 | #define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)) | 752 | #define params_access(p) ((__force snd_pcm_access_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS))) |
752 | #define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)) | 753 | #define params_format(p) ((__force snd_pcm_format_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT))) |
753 | #define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT)) | 754 | #define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT)) |
754 | #define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min | 755 | #define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min |
755 | #define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min | 756 | #define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min |
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h index d79894192ae3..9a155f9d0a12 100644 --- a/include/sound/sh_fsi.h +++ b/include/sound/sh_fsi.h | |||
@@ -15,67 +15,29 @@ | |||
15 | #define FSI_PORT_A 0 | 15 | #define FSI_PORT_A 0 |
16 | #define FSI_PORT_B 1 | 16 | #define FSI_PORT_B 1 |
17 | 17 | ||
18 | /* flags format | ||
19 | |||
20 | * 0xABCDEEFF | ||
21 | * | ||
22 | * A: channel size for TDM (input) | ||
23 | * B: channel size for TDM (ooutput) | ||
24 | * C: inversion | ||
25 | * D: mode | ||
26 | * E: input format | ||
27 | * F: output format | ||
28 | */ | ||
29 | |||
30 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
31 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
32 | 20 | ||
33 | /* TDM channel */ | 21 | /* |
34 | #define SH_FSI_SET_CH_I(x) ((x & 0xF) << 28) | 22 | * flags format |
35 | #define SH_FSI_SET_CH_O(x) ((x & 0xF) << 24) | 23 | * |
36 | 24 | * 0x000000BA | |
37 | #define SH_FSI_CH_IMASK 0xF0000000 | 25 | * |
38 | #define SH_FSI_CH_OMASK 0x0F000000 | 26 | * A: inversion |
39 | #define SH_FSI_GET_CH_I(x) ((x & SH_FSI_CH_IMASK) >> 28) | 27 | * B: format mode |
40 | #define SH_FSI_GET_CH_O(x) ((x & SH_FSI_CH_OMASK) >> 24) | 28 | */ |
41 | |||
42 | /* clock inversion */ | ||
43 | #define SH_FSI_INVERSION_MASK 0x00F00000 | ||
44 | #define SH_FSI_LRM_INV (1 << 20) | ||
45 | #define SH_FSI_BRM_INV (1 << 21) | ||
46 | #define SH_FSI_LRS_INV (1 << 22) | ||
47 | #define SH_FSI_BRS_INV (1 << 23) | ||
48 | |||
49 | /* mode */ | ||
50 | #define SH_FSI_MODE_MASK 0x000F0000 | ||
51 | #define SH_FSI_IN_SLAVE_MODE (1 << 16) /* default master mode */ | ||
52 | #define SH_FSI_OUT_SLAVE_MODE (1 << 17) /* default master mode */ | ||
53 | |||
54 | /* DI format */ | ||
55 | #define SH_FSI_FMT_MASK 0x000000FF | ||
56 | #define SH_FSI_IFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8) | ||
57 | #define SH_FSI_OFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0) | ||
58 | #define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK) | ||
59 | #define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK) | ||
60 | |||
61 | #define SH_FSI_FMT_MONO 0 | ||
62 | #define SH_FSI_FMT_MONO_DELAY 1 | ||
63 | #define SH_FSI_FMT_PCM 2 | ||
64 | #define SH_FSI_FMT_I2S 3 | ||
65 | #define SH_FSI_FMT_TDM 4 | ||
66 | #define SH_FSI_FMT_TDM_DELAY 5 | ||
67 | #define SH_FSI_FMT_SPDIF 6 | ||
68 | |||
69 | |||
70 | #define SH_FSI_IFMT_TDM_CH(x) \ | ||
71 | (SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x)) | ||
72 | #define SH_FSI_IFMT_TDM_DELAY_CH(x) \ | ||
73 | (SH_FSI_IFMT(TDM_DELAY) | SH_FSI_SET_CH_I(x)) | ||
74 | 29 | ||
75 | #define SH_FSI_OFMT_TDM_CH(x) \ | 30 | /* A: clock inversion */ |
76 | (SH_FSI_OFMT(TDM) | SH_FSI_SET_CH_O(x)) | 31 | #define SH_FSI_INVERSION_MASK 0x0000000F |
77 | #define SH_FSI_OFMT_TDM_DELAY_CH(x) \ | 32 | #define SH_FSI_LRM_INV (1 << 0) |
78 | (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x)) | 33 | #define SH_FSI_BRM_INV (1 << 1) |
34 | #define SH_FSI_LRS_INV (1 << 2) | ||
35 | #define SH_FSI_BRS_INV (1 << 3) | ||
36 | |||
37 | /* B: format mode */ | ||
38 | #define SH_FSI_FMT_MASK 0x000000F0 | ||
39 | #define SH_FSI_FMT_DAI (0 << 4) | ||
40 | #define SH_FSI_FMT_SPDIF (1 << 4) | ||
79 | 41 | ||
80 | 42 | ||
81 | /* | 43 | /* |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 8031769ac485..979ed84e07d6 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -157,6 +157,18 @@ | |||
157 | .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \ | 157 | .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \ |
158 | .event = wevent, .event_flags = wflags} | 158 | .event = wevent, .event_flags = wflags} |
159 | 159 | ||
160 | /* additional sequencing control within an event type */ | ||
161 | #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ | ||
162 | wevent, wflags) \ | ||
163 | { .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \ | ||
164 | .invert = winvert, .event = wevent, .event_flags = wflags, \ | ||
165 | .subseq = wsubseq} | ||
166 | #define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \ | ||
167 | wflags) \ | ||
168 | { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ | ||
169 | .shift = wshift, .invert = winvert, .event = wevent, \ | ||
170 | .event_flags = wflags, .subseq = wsubseq} | ||
171 | |||
160 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ | 172 | /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ |
161 | #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ | 173 | #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ |
162 | wevent, wflags) \ | 174 | wevent, wflags) \ |
@@ -450,6 +462,7 @@ struct snd_soc_dapm_widget { | |||
450 | unsigned char ext:1; /* has external widgets */ | 462 | unsigned char ext:1; /* has external widgets */ |
451 | unsigned char force:1; /* force state */ | 463 | unsigned char force:1; /* force state */ |
452 | unsigned char ignore_suspend:1; /* kept enabled over suspend */ | 464 | unsigned char ignore_suspend:1; /* kept enabled over suspend */ |
465 | int subseq; /* sort within widget type */ | ||
453 | 466 | ||
454 | int (*power_check)(struct snd_soc_dapm_widget *w); | 467 | int (*power_check)(struct snd_soc_dapm_widget *w); |
455 | 468 | ||
@@ -487,6 +500,9 @@ struct snd_soc_dapm_context { | |||
487 | 500 | ||
488 | struct snd_soc_dapm_update *update; | 501 | struct snd_soc_dapm_update *update; |
489 | 502 | ||
503 | void (*seq_notifier)(struct snd_soc_dapm_context *, | ||
504 | enum snd_soc_dapm_type, int); | ||
505 | |||
490 | struct device *dev; /* from parent - for debug */ | 506 | struct device *dev; /* from parent - for debug */ |
491 | struct snd_soc_codec *codec; /* parent codec */ | 507 | struct snd_soc_codec *codec; /* parent codec */ |
492 | struct snd_soc_card *card; /* parent card */ | 508 | struct snd_soc_card *card; /* parent card */ |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 74921f20a1d8..bfa4836ea107 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -234,6 +234,7 @@ struct snd_soc_codec; | |||
234 | struct snd_soc_codec_driver; | 234 | struct snd_soc_codec_driver; |
235 | struct soc_enum; | 235 | struct soc_enum; |
236 | struct snd_soc_jack; | 236 | struct snd_soc_jack; |
237 | struct snd_soc_jack_zone; | ||
237 | struct snd_soc_jack_pin; | 238 | struct snd_soc_jack_pin; |
238 | struct snd_soc_cache_ops; | 239 | struct snd_soc_cache_ops; |
239 | #include <sound/soc-dapm.h> | 240 | #include <sound/soc-dapm.h> |
@@ -258,6 +259,16 @@ enum snd_soc_compress_type { | |||
258 | SND_SOC_RBTREE_COMPRESSION | 259 | SND_SOC_RBTREE_COMPRESSION |
259 | }; | 260 | }; |
260 | 261 | ||
262 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
263 | unsigned int freq, int dir); | ||
264 | int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, | ||
265 | unsigned int freq_in, unsigned int freq_out); | ||
266 | |||
267 | int snd_soc_register_card(struct snd_soc_card *card); | ||
268 | int snd_soc_unregister_card(struct snd_soc_card *card); | ||
269 | int snd_soc_suspend(struct device *dev); | ||
270 | int snd_soc_resume(struct device *dev); | ||
271 | int snd_soc_poweroff(struct device *dev); | ||
261 | int snd_soc_register_platform(struct device *dev, | 272 | int snd_soc_register_platform(struct device *dev, |
262 | struct snd_soc_platform_driver *platform_drv); | 273 | struct snd_soc_platform_driver *platform_drv); |
263 | void snd_soc_unregister_platform(struct device *dev); | 274 | void snd_soc_unregister_platform(struct device *dev); |
@@ -265,7 +276,8 @@ int snd_soc_register_codec(struct device *dev, | |||
265 | const struct snd_soc_codec_driver *codec_drv, | 276 | const struct snd_soc_codec_driver *codec_drv, |
266 | struct snd_soc_dai_driver *dai_drv, int num_dai); | 277 | struct snd_soc_dai_driver *dai_drv, int num_dai); |
267 | void snd_soc_unregister_codec(struct device *dev); | 278 | void snd_soc_unregister_codec(struct device *dev); |
268 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); | 279 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, |
280 | unsigned int reg); | ||
269 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | 281 | int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, |
270 | int addr_bits, int data_bits, | 282 | int addr_bits, int data_bits, |
271 | enum snd_soc_control_type control); | 283 | enum snd_soc_control_type control); |
@@ -276,6 +288,10 @@ int snd_soc_cache_write(struct snd_soc_codec *codec, | |||
276 | unsigned int reg, unsigned int value); | 288 | unsigned int reg, unsigned int value); |
277 | int snd_soc_cache_read(struct snd_soc_codec *codec, | 289 | int snd_soc_cache_read(struct snd_soc_codec *codec, |
278 | unsigned int reg, unsigned int *value); | 290 | unsigned int reg, unsigned int *value); |
291 | int snd_soc_default_volatile_register(struct snd_soc_codec *codec, | ||
292 | unsigned int reg); | ||
293 | int snd_soc_default_readable_register(struct snd_soc_codec *codec, | ||
294 | unsigned int reg); | ||
279 | 295 | ||
280 | /* Utility functions to get clock rates from various things */ | 296 | /* Utility functions to get clock rates from various things */ |
281 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); | 297 | int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); |
@@ -297,6 +313,9 @@ void snd_soc_jack_notifier_register(struct snd_soc_jack *jack, | |||
297 | struct notifier_block *nb); | 313 | struct notifier_block *nb); |
298 | void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, | 314 | void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, |
299 | struct notifier_block *nb); | 315 | struct notifier_block *nb); |
316 | int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count, | ||
317 | struct snd_soc_jack_zone *zones); | ||
318 | int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage); | ||
300 | #ifdef CONFIG_GPIOLIB | 319 | #ifdef CONFIG_GPIOLIB |
301 | int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | 320 | int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, |
302 | struct snd_soc_jack_gpio *gpios); | 321 | struct snd_soc_jack_gpio *gpios); |
@@ -321,7 +340,8 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); | |||
321 | *Controls | 340 | *Controls |
322 | */ | 341 | */ |
323 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | 342 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, |
324 | void *data, char *long_name); | 343 | void *data, char *long_name, |
344 | const char *prefix); | ||
325 | int snd_soc_add_controls(struct snd_soc_codec *codec, | 345 | int snd_soc_add_controls(struct snd_soc_codec *codec, |
326 | const struct snd_kcontrol_new *controls, int num_controls); | 346 | const struct snd_kcontrol_new *controls, int num_controls); |
327 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, | 347 | int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, |
@@ -367,6 +387,22 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol, | |||
367 | struct snd_ctl_elem_value *ucontrol); | 387 | struct snd_ctl_elem_value *ucontrol); |
368 | 388 | ||
369 | /** | 389 | /** |
390 | * struct snd_soc_reg_access - Describes whether a given register is | ||
391 | * readable, writable or volatile. | ||
392 | * | ||
393 | * @reg: the register number | ||
394 | * @read: whether this register is readable | ||
395 | * @write: whether this register is writable | ||
396 | * @vol: whether this register is volatile | ||
397 | */ | ||
398 | struct snd_soc_reg_access { | ||
399 | u16 reg; | ||
400 | u16 read; | ||
401 | u16 write; | ||
402 | u16 vol; | ||
403 | }; | ||
404 | |||
405 | /** | ||
370 | * struct snd_soc_jack_pin - Describes a pin to update based on jack detection | 406 | * struct snd_soc_jack_pin - Describes a pin to update based on jack detection |
371 | * | 407 | * |
372 | * @pin: name of the pin to update | 408 | * @pin: name of the pin to update |
@@ -381,6 +417,24 @@ struct snd_soc_jack_pin { | |||
381 | }; | 417 | }; |
382 | 418 | ||
383 | /** | 419 | /** |
420 | * struct snd_soc_jack_zone - Describes voltage zones of jack detection | ||
421 | * | ||
422 | * @min_mv: start voltage in mv | ||
423 | * @max_mv: end voltage in mv | ||
424 | * @jack_type: type of jack that is expected for this voltage | ||
425 | * @debounce_time: debounce_time for jack, codec driver should wait for this | ||
426 | * duration before reading the adc for voltages | ||
427 | * @:list: list container | ||
428 | */ | ||
429 | struct snd_soc_jack_zone { | ||
430 | unsigned int min_mv; | ||
431 | unsigned int max_mv; | ||
432 | unsigned int jack_type; | ||
433 | unsigned int debounce_time; | ||
434 | struct list_head list; | ||
435 | }; | ||
436 | |||
437 | /** | ||
384 | * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection | 438 | * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection |
385 | * | 439 | * |
386 | * @gpio: gpio number | 440 | * @gpio: gpio number |
@@ -388,6 +442,10 @@ struct snd_soc_jack_pin { | |||
388 | * @report: value to report when jack detected | 442 | * @report: value to report when jack detected |
389 | * @invert: report presence in low state | 443 | * @invert: report presence in low state |
390 | * @debouce_time: debouce time in ms | 444 | * @debouce_time: debouce time in ms |
445 | * @wake: enable as wake source | ||
446 | * @jack_status_check: callback function which overrides the detection | ||
447 | * to provide more complex checks (eg, reading an | ||
448 | * ADC). | ||
391 | */ | 449 | */ |
392 | #ifdef CONFIG_GPIOLIB | 450 | #ifdef CONFIG_GPIOLIB |
393 | struct snd_soc_jack_gpio { | 451 | struct snd_soc_jack_gpio { |
@@ -396,6 +454,8 @@ struct snd_soc_jack_gpio { | |||
396 | int report; | 454 | int report; |
397 | int invert; | 455 | int invert; |
398 | int debounce_time; | 456 | int debounce_time; |
457 | bool wake; | ||
458 | |||
399 | struct snd_soc_jack *jack; | 459 | struct snd_soc_jack *jack; |
400 | struct delayed_work work; | 460 | struct delayed_work work; |
401 | 461 | ||
@@ -409,6 +469,7 @@ struct snd_soc_jack { | |||
409 | struct list_head pins; | 469 | struct list_head pins; |
410 | int status; | 470 | int status; |
411 | struct blocking_notifier_head notifier; | 471 | struct blocking_notifier_head notifier; |
472 | struct list_head jack_zones; | ||
412 | }; | 473 | }; |
413 | 474 | ||
414 | /* SoC PCM stream information */ | 475 | /* SoC PCM stream information */ |
@@ -459,18 +520,22 @@ struct snd_soc_codec { | |||
459 | struct list_head card_list; | 520 | struct list_head card_list; |
460 | int num_dai; | 521 | int num_dai; |
461 | enum snd_soc_compress_type compress_type; | 522 | enum snd_soc_compress_type compress_type; |
523 | size_t reg_size; /* reg_cache_size * reg_word_size */ | ||
524 | int (*volatile_register)(struct snd_soc_codec *, unsigned int); | ||
525 | int (*readable_register)(struct snd_soc_codec *, unsigned int); | ||
462 | 526 | ||
463 | /* runtime */ | 527 | /* runtime */ |
464 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ | 528 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ |
465 | unsigned int active; | 529 | unsigned int active; |
466 | unsigned int cache_only:1; /* Suppress writes to hardware */ | 530 | unsigned int cache_bypass:1; /* Suppress access to the cache */ |
467 | unsigned int cache_sync:1; /* Cache needs to be synced to hardware */ | ||
468 | unsigned int suspended:1; /* Codec is in suspend PM state */ | 531 | unsigned int suspended:1; /* Codec is in suspend PM state */ |
469 | unsigned int probed:1; /* Codec has been probed */ | 532 | unsigned int probed:1; /* Codec has been probed */ |
470 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ | 533 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ |
471 | unsigned int ac97_created:1; /* Codec has been created by SoC */ | 534 | unsigned int ac97_created:1; /* Codec has been created by SoC */ |
472 | unsigned int sysfs_registered:1; /* codec has been sysfs registered */ | 535 | unsigned int sysfs_registered:1; /* codec has been sysfs registered */ |
473 | unsigned int cache_init:1; /* codec cache has been initialized */ | 536 | unsigned int cache_init:1; /* codec cache has been initialized */ |
537 | u32 cache_only; /* Suppress writes to hardware */ | ||
538 | u32 cache_sync; /* Cache needs to be synced to hardware */ | ||
474 | 539 | ||
475 | /* codec IO */ | 540 | /* codec IO */ |
476 | void *control_data; /* codec control (i2c/3wire) data */ | 541 | void *control_data; /* codec control (i2c/3wire) data */ |
@@ -503,22 +568,39 @@ struct snd_soc_codec_driver { | |||
503 | pm_message_t state); | 568 | pm_message_t state); |
504 | int (*resume)(struct snd_soc_codec *); | 569 | int (*resume)(struct snd_soc_codec *); |
505 | 570 | ||
571 | /* Default DAPM setup, added after probe() is run */ | ||
572 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
573 | int num_dapm_widgets; | ||
574 | const struct snd_soc_dapm_route *dapm_routes; | ||
575 | int num_dapm_routes; | ||
576 | |||
577 | /* codec wide operations */ | ||
578 | int (*set_sysclk)(struct snd_soc_codec *codec, | ||
579 | int clk_id, unsigned int freq, int dir); | ||
580 | int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source, | ||
581 | unsigned int freq_in, unsigned int freq_out); | ||
582 | |||
506 | /* codec IO */ | 583 | /* codec IO */ |
507 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); | 584 | unsigned int (*read)(struct snd_soc_codec *, unsigned int); |
508 | int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); | 585 | int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); |
509 | int (*display_register)(struct snd_soc_codec *, char *, | 586 | int (*display_register)(struct snd_soc_codec *, char *, |
510 | size_t, unsigned int); | 587 | size_t, unsigned int); |
511 | int (*volatile_register)(unsigned int); | 588 | int (*volatile_register)(struct snd_soc_codec *, unsigned int); |
512 | int (*readable_register)(unsigned int); | 589 | int (*readable_register)(struct snd_soc_codec *, unsigned int); |
513 | short reg_cache_size; | 590 | short reg_cache_size; |
514 | short reg_cache_step; | 591 | short reg_cache_step; |
515 | short reg_word_size; | 592 | short reg_word_size; |
516 | const void *reg_cache_default; | 593 | const void *reg_cache_default; |
594 | short reg_access_size; | ||
595 | const struct snd_soc_reg_access *reg_access_default; | ||
517 | enum snd_soc_compress_type compress_type; | 596 | enum snd_soc_compress_type compress_type; |
518 | 597 | ||
519 | /* codec bias level */ | 598 | /* codec bias level */ |
520 | int (*set_bias_level)(struct snd_soc_codec *, | 599 | int (*set_bias_level)(struct snd_soc_codec *, |
521 | enum snd_soc_bias_level level); | 600 | enum snd_soc_bias_level level); |
601 | |||
602 | void (*seq_notifier)(struct snd_soc_dapm_context *, | ||
603 | enum snd_soc_dapm_type, int); | ||
522 | }; | 604 | }; |
523 | 605 | ||
524 | /* SoC platform interface */ | 606 | /* SoC platform interface */ |
@@ -617,15 +699,16 @@ struct snd_soc_card { | |||
617 | 699 | ||
618 | bool instantiated; | 700 | bool instantiated; |
619 | 701 | ||
620 | int (*probe)(struct platform_device *pdev); | 702 | int (*probe)(struct snd_soc_card *card); |
621 | int (*remove)(struct platform_device *pdev); | 703 | int (*late_probe)(struct snd_soc_card *card); |
704 | int (*remove)(struct snd_soc_card *card); | ||
622 | 705 | ||
623 | /* the pre and post PM functions are used to do any PM work before and | 706 | /* the pre and post PM functions are used to do any PM work before and |
624 | * after the codec and DAI's do any PM work. */ | 707 | * after the codec and DAI's do any PM work. */ |
625 | int (*suspend_pre)(struct platform_device *pdev, pm_message_t state); | 708 | int (*suspend_pre)(struct snd_soc_card *card); |
626 | int (*suspend_post)(struct platform_device *pdev, pm_message_t state); | 709 | int (*suspend_post)(struct snd_soc_card *card); |
627 | int (*resume_pre)(struct platform_device *pdev); | 710 | int (*resume_pre)(struct snd_soc_card *card); |
628 | int (*resume_post)(struct platform_device *pdev); | 711 | int (*resume_post)(struct snd_soc_card *card); |
629 | 712 | ||
630 | /* callbacks */ | 713 | /* callbacks */ |
631 | int (*set_bias_level)(struct snd_soc_card *, | 714 | int (*set_bias_level)(struct snd_soc_card *, |
@@ -654,6 +737,14 @@ struct snd_soc_card { | |||
654 | struct snd_soc_pcm_runtime *rtd_aux; | 737 | struct snd_soc_pcm_runtime *rtd_aux; |
655 | int num_aux_rtd; | 738 | int num_aux_rtd; |
656 | 739 | ||
740 | /* | ||
741 | * Card-specific routes and widgets. | ||
742 | */ | ||
743 | struct snd_soc_dapm_widget *dapm_widgets; | ||
744 | int num_dapm_widgets; | ||
745 | struct snd_soc_dapm_route *dapm_routes; | ||
746 | int num_dapm_routes; | ||
747 | |||
657 | struct work_struct deferred_resume_work; | 748 | struct work_struct deferred_resume_work; |
658 | 749 | ||
659 | /* lists of probed devices belonging to this card */ | 750 | /* lists of probed devices belonging to this card */ |
@@ -665,11 +756,16 @@ struct snd_soc_card { | |||
665 | struct list_head paths; | 756 | struct list_head paths; |
666 | struct list_head dapm_list; | 757 | struct list_head dapm_list; |
667 | 758 | ||
759 | /* Generic DAPM context for the card */ | ||
760 | struct snd_soc_dapm_context dapm; | ||
761 | |||
668 | #ifdef CONFIG_DEBUG_FS | 762 | #ifdef CONFIG_DEBUG_FS |
669 | struct dentry *debugfs_card_root; | 763 | struct dentry *debugfs_card_root; |
670 | struct dentry *debugfs_pop_time; | 764 | struct dentry *debugfs_pop_time; |
671 | #endif | 765 | #endif |
672 | u32 pop_time; | 766 | u32 pop_time; |
767 | |||
768 | void *drvdata; | ||
673 | }; | 769 | }; |
674 | 770 | ||
675 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ | 771 | /* SoC machine DAI configuration, glues a codec and cpu DAI together */ |
@@ -721,6 +817,17 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec, | |||
721 | 817 | ||
722 | /* device driver data */ | 818 | /* device driver data */ |
723 | 819 | ||
820 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, | ||
821 | void *data) | ||
822 | { | ||
823 | card->drvdata = data; | ||
824 | } | ||
825 | |||
826 | static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) | ||
827 | { | ||
828 | return card->drvdata; | ||
829 | } | ||
830 | |||
724 | static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, | 831 | static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, |
725 | void *data) | 832 | void *data) |
726 | { | 833 | { |
@@ -754,6 +861,22 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd) | |||
754 | return dev_get_drvdata(&rtd->dev); | 861 | return dev_get_drvdata(&rtd->dev); |
755 | } | 862 | } |
756 | 863 | ||
864 | static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card) | ||
865 | { | ||
866 | INIT_LIST_HEAD(&card->dai_dev_list); | ||
867 | INIT_LIST_HEAD(&card->codec_dev_list); | ||
868 | INIT_LIST_HEAD(&card->platform_dev_list); | ||
869 | INIT_LIST_HEAD(&card->widgets); | ||
870 | INIT_LIST_HEAD(&card->paths); | ||
871 | INIT_LIST_HEAD(&card->dapm_list); | ||
872 | } | ||
873 | |||
757 | #include <sound/soc-dai.h> | 874 | #include <sound/soc-dai.h> |
758 | 875 | ||
876 | #ifdef CONFIG_DEBUG_FS | ||
877 | extern struct dentry *snd_soc_debugfs_root; | ||
878 | #endif | ||
879 | |||
880 | extern const struct dev_pm_ops snd_soc_pm_ops; | ||
881 | |||
759 | #endif | 882 | #endif |
diff --git a/include/sound/tlv320aic32x4.h b/include/sound/tlv320aic32x4.h new file mode 100644 index 000000000000..c009f70b4029 --- /dev/null +++ b/include/sound/tlv320aic32x4.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * tlv320aic32x4.h -- TLV320AIC32X4 Soc Audio driver platform data | ||
3 | * | ||
4 | * Copyright 2011 Vista Silicon S.L. | ||
5 | * | ||
6 | * Author: Javier Martin <javier.martin@vista-silicon.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _AIC32X4_PDATA_H | ||
14 | #define _AIC32X4_PDATA_H | ||
15 | |||
16 | #define AIC32X4_PWR_MICBIAS_2075_LDOIN 0x00000001 | ||
17 | #define AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE 0x00000002 | ||
18 | #define AIC32X4_PWR_AIC32X4_LDO_ENABLE 0x00000004 | ||
19 | #define AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36 0x00000008 | ||
20 | #define AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED 0x00000010 | ||
21 | |||
22 | #define AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K 0x00000001 | ||
23 | #define AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K 0x00000002 | ||
24 | |||
25 | struct aic32x4_pdata { | ||
26 | u32 power_cfg; | ||
27 | u32 micpga_routing; | ||
28 | bool swapdacs; | ||
29 | }; | ||
30 | |||
31 | #endif | ||
diff --git a/include/sound/version.h b/include/sound/version.h index bf69a5b7e65f..8fc5321e1ecc 100644 --- a/include/sound/version.h +++ b/include/sound/version.h | |||
@@ -1,3 +1,3 @@ | |||
1 | /* include/version.h */ | 1 | /* include/version.h */ |
2 | #define CONFIG_SND_VERSION "1.0.23" | 2 | #define CONFIG_SND_VERSION "1.0.24" |
3 | #define CONFIG_SND_DATE "" | 3 | #define CONFIG_SND_DATE "" |
diff --git a/include/sound/wm8903.h b/include/sound/wm8903.h index 1eeebd534f7e..cf7ccb76a8de 100644 --- a/include/sound/wm8903.h +++ b/include/sound/wm8903.h | |||
@@ -33,6 +33,21 @@ | |||
33 | #define WM8903_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */ | 33 | #define WM8903_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */ |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * WM8903_GPn_FN values | ||
37 | * | ||
38 | * See datasheets for list of valid values per pin | ||
39 | */ | ||
40 | #define WM8903_GPn_FN_GPIO_OUTPUT 0 | ||
41 | #define WM8903_GPn_FN_BCLK 1 | ||
42 | #define WM8903_GPn_FN_IRQ_OUTPT 2 | ||
43 | #define WM8903_GPn_FN_GPIO_INPUT 3 | ||
44 | #define WM8903_GPn_FN_MICBIAS_CURRENT_DETECT 4 | ||
45 | #define WM8903_GPn_FN_MICBIAS_SHORT_DETECT 5 | ||
46 | #define WM8903_GPn_FN_DMIC_LR_CLK_OUTPUT 6 | ||
47 | #define WM8903_GPn_FN_FLL_LOCK_OUTPUT 8 | ||
48 | #define WM8903_GPn_FN_FLL_CLOCK_OUTPUT 9 | ||
49 | |||
50 | /* | ||
36 | * R116 (0x74) - GPIO Control 1 | 51 | * R116 (0x74) - GPIO Control 1 |
37 | */ | 52 | */ |
38 | #define WM8903_GP1_FN_MASK 0x1F00 /* GP1_FN - [12:8] */ | 53 | #define WM8903_GP1_FN_MASK 0x1F00 /* GP1_FN - [12:8] */ |
@@ -227,6 +242,8 @@ | |||
227 | #define WM8903_GP5_DB_SHIFT 0 /* GP5_DB */ | 242 | #define WM8903_GP5_DB_SHIFT 0 /* GP5_DB */ |
228 | #define WM8903_GP5_DB_WIDTH 1 /* GP5_DB */ | 243 | #define WM8903_GP5_DB_WIDTH 1 /* GP5_DB */ |
229 | 244 | ||
245 | #define WM8903_NUM_GPIO 5 | ||
246 | |||
230 | struct wm8903_platform_data { | 247 | struct wm8903_platform_data { |
231 | bool irq_active_low; /* Set if IRQ active low, default high */ | 248 | bool irq_active_low; /* Set if IRQ active low, default high */ |
232 | 249 | ||
@@ -239,7 +256,8 @@ struct wm8903_platform_data { | |||
239 | 256 | ||
240 | int micdet_delay; /* Delay after microphone detection (ms) */ | 257 | int micdet_delay; /* Delay after microphone detection (ms) */ |
241 | 258 | ||
242 | u32 gpio_cfg[5]; /* Default register values for GPIO pin mux */ | 259 | int gpio_base; |
260 | u32 gpio_cfg[WM8903_NUM_GPIO]; /* Default register values for GPIO pin mux */ | ||
243 | }; | 261 | }; |
244 | 262 | ||
245 | #endif | 263 | #endif |
diff --git a/include/sound/wm9081.h b/include/sound/wm9081.h index e173ddbf6bd4..f34b0b1716d8 100644 --- a/include/sound/wm9081.h +++ b/include/sound/wm9081.h | |||
@@ -17,9 +17,12 @@ struct wm9081_retune_mobile_setting { | |||
17 | u16 config[20]; | 17 | u16 config[20]; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | struct wm9081_retune_mobile_config { | 20 | struct wm9081_pdata { |
21 | struct wm9081_retune_mobile_setting *configs; | 21 | bool irq_high; /* IRQ is active high */ |
22 | int num_configs; | 22 | bool irq_cmos; /* IRQ is in CMOS mode */ |
23 | |||
24 | struct wm9081_retune_mobile_setting *retune_configs; | ||
25 | int num_retune_configs; | ||
23 | }; | 26 | }; |
24 | 27 | ||
25 | #endif | 28 | #endif |
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h index 186e84db4b54..ae973d2e27a1 100644 --- a/include/trace/events/asoc.h +++ b/include/trace/events/asoc.h | |||
@@ -229,6 +229,31 @@ TRACE_EVENT(snd_soc_jack_notify, | |||
229 | TP_printk("jack=%s %x", __get_str(name), (int)__entry->val) | 229 | TP_printk("jack=%s %x", __get_str(name), (int)__entry->val) |
230 | ); | 230 | ); |
231 | 231 | ||
232 | TRACE_EVENT(snd_soc_cache_sync, | ||
233 | |||
234 | TP_PROTO(struct snd_soc_codec *codec, const char *type, | ||
235 | const char *status), | ||
236 | |||
237 | TP_ARGS(codec, type, status), | ||
238 | |||
239 | TP_STRUCT__entry( | ||
240 | __string( name, codec->name ) | ||
241 | __string( status, status ) | ||
242 | __string( type, type ) | ||
243 | __field( int, id ) | ||
244 | ), | ||
245 | |||
246 | TP_fast_assign( | ||
247 | __assign_str(name, codec->name); | ||
248 | __assign_str(status, status); | ||
249 | __assign_str(type, type); | ||
250 | __entry->id = codec->id; | ||
251 | ), | ||
252 | |||
253 | TP_printk("codec=%s.%d type=%s status=%s", __get_str(name), | ||
254 | (int)__entry->id, __get_str(type), __get_str(status)) | ||
255 | ); | ||
256 | |||
232 | #endif /* _TRACE_ASOC_H */ | 257 | #endif /* _TRACE_ASOC_H */ |
233 | 258 | ||
234 | /* This part must be outside protection */ | 259 | /* This part must be outside protection */ |
diff --git a/sound/Kconfig b/sound/Kconfig index fcad760f5691..1fef141ef8e7 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -97,6 +97,8 @@ source "sound/sh/Kconfig" | |||
97 | # here assuming USB is defined before ALSA | 97 | # here assuming USB is defined before ALSA |
98 | source "sound/usb/Kconfig" | 98 | source "sound/usb/Kconfig" |
99 | 99 | ||
100 | source "sound/firewire/Kconfig" | ||
101 | |||
100 | # the following will depend on the order of config. | 102 | # the following will depend on the order of config. |
101 | # here assuming PCMCIA is defined before ALSA | 103 | # here assuming PCMCIA is defined before ALSA |
102 | source "sound/pcmcia/Kconfig" | 104 | source "sound/pcmcia/Kconfig" |
diff --git a/sound/Makefile b/sound/Makefile index ec467decfa79..ce9132b1c395 100644 --- a/sound/Makefile +++ b/sound/Makefile | |||
@@ -6,7 +6,7 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o | |||
6 | obj-$(CONFIG_SOUND_PRIME) += oss/ | 6 | obj-$(CONFIG_SOUND_PRIME) += oss/ |
7 | obj-$(CONFIG_DMASOUND) += oss/ | 7 | obj-$(CONFIG_DMASOUND) += oss/ |
8 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ | 8 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \ |
9 | sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ | 9 | firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ |
10 | obj-$(CONFIG_SND_AOA) += aoa/ | 10 | obj-$(CONFIG_SND_AOA) += aoa/ |
11 | 11 | ||
12 | # This one must be compilable even if sound is configured out | 12 | # This one must be compilable even if sound is configured out |
diff --git a/sound/core/control.c b/sound/core/control.c index 9ce00ed20fba..a08ad57c49b6 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -279,33 +279,31 @@ void snd_ctl_free_one(struct snd_kcontrol *kcontrol) | |||
279 | 279 | ||
280 | EXPORT_SYMBOL(snd_ctl_free_one); | 280 | EXPORT_SYMBOL(snd_ctl_free_one); |
281 | 281 | ||
282 | static unsigned int snd_ctl_hole_check(struct snd_card *card, | 282 | static bool snd_ctl_remove_numid_conflict(struct snd_card *card, |
283 | unsigned int count) | 283 | unsigned int count) |
284 | { | 284 | { |
285 | struct snd_kcontrol *kctl; | 285 | struct snd_kcontrol *kctl; |
286 | 286 | ||
287 | list_for_each_entry(kctl, &card->controls, list) { | 287 | list_for_each_entry(kctl, &card->controls, list) { |
288 | if ((kctl->id.numid <= card->last_numid && | 288 | if (kctl->id.numid < card->last_numid + 1 + count && |
289 | kctl->id.numid + kctl->count > card->last_numid) || | 289 | kctl->id.numid + kctl->count > card->last_numid + 1) { |
290 | (kctl->id.numid <= card->last_numid + count - 1 && | 290 | card->last_numid = kctl->id.numid + kctl->count - 1; |
291 | kctl->id.numid + kctl->count > card->last_numid + count - 1)) | 291 | return true; |
292 | return card->last_numid = kctl->id.numid + kctl->count - 1; | 292 | } |
293 | } | 293 | } |
294 | return card->last_numid; | 294 | return false; |
295 | } | 295 | } |
296 | 296 | ||
297 | static int snd_ctl_find_hole(struct snd_card *card, unsigned int count) | 297 | static int snd_ctl_find_hole(struct snd_card *card, unsigned int count) |
298 | { | 298 | { |
299 | unsigned int last_numid, iter = 100000; | 299 | unsigned int iter = 100000; |
300 | 300 | ||
301 | last_numid = card->last_numid; | 301 | while (snd_ctl_remove_numid_conflict(card, count)) { |
302 | while (last_numid != snd_ctl_hole_check(card, count)) { | ||
303 | if (--iter == 0) { | 302 | if (--iter == 0) { |
304 | /* this situation is very unlikely */ | 303 | /* this situation is very unlikely */ |
305 | snd_printk(KERN_ERR "unable to allocate new control numid\n"); | 304 | snd_printk(KERN_ERR "unable to allocate new control numid\n"); |
306 | return -ENOMEM; | 305 | return -ENOMEM; |
307 | } | 306 | } |
308 | last_numid = card->last_numid; | ||
309 | } | 307 | } |
310 | return 0; | 308 | return 0; |
311 | } | 309 | } |
@@ -466,6 +464,52 @@ error: | |||
466 | } | 464 | } |
467 | 465 | ||
468 | /** | 466 | /** |
467 | * snd_ctl_activate_id - activate/inactivate the control of the given id | ||
468 | * @card: the card instance | ||
469 | * @id: the control id to activate/inactivate | ||
470 | * @active: non-zero to activate | ||
471 | * | ||
472 | * Finds the control instance with the given id, and activate or | ||
473 | * inactivate the control together with notification, if changed. | ||
474 | * | ||
475 | * Returns 0 if unchanged, 1 if changed, or a negative error code on failure. | ||
476 | */ | ||
477 | int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, | ||
478 | int active) | ||
479 | { | ||
480 | struct snd_kcontrol *kctl; | ||
481 | struct snd_kcontrol_volatile *vd; | ||
482 | unsigned int index_offset; | ||
483 | int ret; | ||
484 | |||
485 | down_write(&card->controls_rwsem); | ||
486 | kctl = snd_ctl_find_id(card, id); | ||
487 | if (kctl == NULL) { | ||
488 | ret = -ENOENT; | ||
489 | goto unlock; | ||
490 | } | ||
491 | index_offset = snd_ctl_get_ioff(kctl, &kctl->id); | ||
492 | vd = &kctl->vd[index_offset]; | ||
493 | ret = 0; | ||
494 | if (active) { | ||
495 | if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)) | ||
496 | goto unlock; | ||
497 | vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
498 | } else { | ||
499 | if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) | ||
500 | goto unlock; | ||
501 | vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; | ||
502 | } | ||
503 | ret = 1; | ||
504 | unlock: | ||
505 | up_write(&card->controls_rwsem); | ||
506 | if (ret > 0) | ||
507 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id); | ||
508 | return ret; | ||
509 | } | ||
510 | EXPORT_SYMBOL_GPL(snd_ctl_activate_id); | ||
511 | |||
512 | /** | ||
469 | * snd_ctl_rename_id - replace the id of a control on the card | 513 | * snd_ctl_rename_id - replace the id of a control on the card |
470 | * @card: the card instance | 514 | * @card: the card instance |
471 | * @src_id: the old id | 515 | * @src_id: the old id |
diff --git a/sound/core/device.c b/sound/core/device.c index a67dfac08c03..2d1ad4b0cd65 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -225,15 +225,16 @@ int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd) | |||
225 | { | 225 | { |
226 | struct snd_device *dev; | 226 | struct snd_device *dev; |
227 | int err; | 227 | int err; |
228 | unsigned int range_low, range_high; | 228 | unsigned int range_low, range_high, type; |
229 | 229 | ||
230 | if (snd_BUG_ON(!card)) | 230 | if (snd_BUG_ON(!card)) |
231 | return -ENXIO; | 231 | return -ENXIO; |
232 | range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE; | 232 | range_low = (__force unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE; |
233 | range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1; | 233 | range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1; |
234 | __again: | 234 | __again: |
235 | list_for_each_entry(dev, &card->devices, list) { | 235 | list_for_each_entry(dev, &card->devices, list) { |
236 | if (dev->type >= range_low && dev->type <= range_high) { | 236 | type = (__force unsigned int)dev->type; |
237 | if (type >= range_low && type <= range_high) { | ||
237 | if ((err = snd_device_free(card, dev->device_data)) < 0) | 238 | if ((err = snd_device_free(card, dev->device_data)) < 0) |
238 | return err; | 239 | return err; |
239 | goto __again; | 240 | goto __again; |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 9e92441f9b78..16bd9c03679b 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -192,7 +192,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, | |||
192 | dmab->bytes = 0; | 192 | dmab->bytes = 0; |
193 | switch (type) { | 193 | switch (type) { |
194 | case SNDRV_DMA_TYPE_CONTINUOUS: | 194 | case SNDRV_DMA_TYPE_CONTINUOUS: |
195 | dmab->area = snd_malloc_pages(size, (unsigned long)device); | 195 | dmab->area = snd_malloc_pages(size, |
196 | (__force gfp_t)(unsigned long)device); | ||
196 | dmab->addr = 0; | 197 | dmab->addr = 0; |
197 | break; | 198 | break; |
198 | #ifdef CONFIG_HAS_DMA | 199 | #ifdef CONFIG_HAS_DMA |
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c index 4c1d16827199..13b3f6f49fae 100644 --- a/sound/core/oss/linear.c +++ b/sound/core/oss/linear.c | |||
@@ -114,7 +114,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin, | |||
114 | return frames; | 114 | return frames; |
115 | } | 115 | } |
116 | 116 | ||
117 | static void init_data(struct linear_priv *data, int src_format, int dst_format) | 117 | static void init_data(struct linear_priv *data, |
118 | snd_pcm_format_t src_format, snd_pcm_format_t dst_format) | ||
118 | { | 119 | { |
119 | int src_le, dst_le, src_bytes, dst_bytes; | 120 | int src_le, dst_le, src_bytes, dst_bytes; |
120 | 121 | ||
@@ -140,9 +141,9 @@ static void init_data(struct linear_priv *data, int src_format, int dst_format) | |||
140 | if (snd_pcm_format_signed(src_format) != | 141 | if (snd_pcm_format_signed(src_format) != |
141 | snd_pcm_format_signed(dst_format)) { | 142 | snd_pcm_format_signed(dst_format)) { |
142 | if (dst_le) | 143 | if (dst_le) |
143 | data->flip = cpu_to_le32(0x80000000); | 144 | data->flip = (__force u32)cpu_to_le32(0x80000000); |
144 | else | 145 | else |
145 | data->flip = cpu_to_be32(0x80000000); | 146 | data->flip = (__force u32)cpu_to_be32(0x80000000); |
146 | } | 147 | } |
147 | } | 148 | } |
148 | 149 | ||
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 822dd56993ca..d8359cfeca15 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -190,9 +190,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer) | |||
190 | return -EIO; | 190 | return -EIO; |
191 | if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ | 191 | if (mixer->put_recsrc && mixer->get_recsrc) { /* exclusive */ |
192 | int err; | 192 | int err; |
193 | if ((err = mixer->get_recsrc(fmixer, &result)) < 0) | 193 | unsigned int index; |
194 | if ((err = mixer->get_recsrc(fmixer, &index)) < 0) | ||
194 | return err; | 195 | return err; |
195 | result = 1 << result; | 196 | result = 1 << index; |
196 | } else { | 197 | } else { |
197 | struct snd_mixer_oss_slot *pslot; | 198 | struct snd_mixer_oss_slot *pslot; |
198 | int chn; | 199 | int chn; |
@@ -214,6 +215,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr | |||
214 | struct snd_mixer_oss *mixer = fmixer->mixer; | 215 | struct snd_mixer_oss *mixer = fmixer->mixer; |
215 | struct snd_mixer_oss_slot *pslot; | 216 | struct snd_mixer_oss_slot *pslot; |
216 | int chn, active; | 217 | int chn, active; |
218 | unsigned int index; | ||
217 | int result = 0; | 219 | int result = 0; |
218 | 220 | ||
219 | if (mixer == NULL) | 221 | if (mixer == NULL) |
@@ -222,8 +224,8 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr | |||
222 | if (recsrc & ~mixer->oss_recsrc) | 224 | if (recsrc & ~mixer->oss_recsrc) |
223 | recsrc &= ~mixer->oss_recsrc; | 225 | recsrc &= ~mixer->oss_recsrc; |
224 | mixer->put_recsrc(fmixer, ffz(~recsrc)); | 226 | mixer->put_recsrc(fmixer, ffz(~recsrc)); |
225 | mixer->get_recsrc(fmixer, &result); | 227 | mixer->get_recsrc(fmixer, &index); |
226 | result = 1 << result; | 228 | result = 1 << index; |
227 | } | 229 | } |
228 | for (chn = 0; chn < 31; chn++) { | 230 | for (chn = 0; chn < 31; chn++) { |
229 | pslot = &mixer->slots[chn]; | 231 | pslot = &mixer->slots[chn]; |
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c index f7649d4d950b..7915564bd394 100644 --- a/sound/core/oss/mulaw.c +++ b/sound/core/oss/mulaw.c | |||
@@ -274,7 +274,7 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin, | |||
274 | return frames; | 274 | return frames; |
275 | } | 275 | } |
276 | 276 | ||
277 | static void init_data(struct mulaw_priv *data, int format) | 277 | static void init_data(struct mulaw_priv *data, snd_pcm_format_t format) |
278 | { | 278 | { |
279 | #ifdef SNDRV_LITTLE_ENDIAN | 279 | #ifdef SNDRV_LITTLE_ENDIAN |
280 | data->cvt_endian = snd_pcm_format_big_endian(format) > 0; | 280 | data->cvt_endian = snd_pcm_format_big_endian(format) > 0; |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index a2e4eb324699..23c34a02894b 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <sound/info.h> | 41 | #include <sound/info.h> |
42 | #include <linux/soundcard.h> | 42 | #include <linux/soundcard.h> |
43 | #include <sound/initval.h> | 43 | #include <sound/initval.h> |
44 | #include <sound/mixer_oss.h> | ||
44 | 45 | ||
45 | #define OSS_ALSAEMULVER _SIOR ('M', 249, int) | 46 | #define OSS_ALSAEMULVER _SIOR ('M', 249, int) |
46 | 47 | ||
@@ -60,7 +61,6 @@ MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices."); | |||
60 | MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM); | 61 | MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM); |
61 | MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1); | 62 | MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1); |
62 | 63 | ||
63 | extern int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg); | ||
64 | static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); | 64 | static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file); |
65 | static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); | 65 | static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file); |
66 | static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); | 66 | static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file); |
@@ -656,7 +656,7 @@ snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime) | |||
656 | #define AFMT_AC3 0x00000400 | 656 | #define AFMT_AC3 0x00000400 |
657 | #define AFMT_VORBIS 0x00000800 | 657 | #define AFMT_VORBIS 0x00000800 |
658 | 658 | ||
659 | static int snd_pcm_oss_format_from(int format) | 659 | static snd_pcm_format_t snd_pcm_oss_format_from(int format) |
660 | { | 660 | { |
661 | switch (format) { | 661 | switch (format) { |
662 | case AFMT_MU_LAW: return SNDRV_PCM_FORMAT_MU_LAW; | 662 | case AFMT_MU_LAW: return SNDRV_PCM_FORMAT_MU_LAW; |
@@ -680,7 +680,7 @@ static int snd_pcm_oss_format_from(int format) | |||
680 | } | 680 | } |
681 | } | 681 | } |
682 | 682 | ||
683 | static int snd_pcm_oss_format_to(int format) | 683 | static int snd_pcm_oss_format_to(snd_pcm_format_t format) |
684 | { | 684 | { |
685 | switch (format) { | 685 | switch (format) { |
686 | case SNDRV_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; | 686 | case SNDRV_PCM_FORMAT_MU_LAW: return AFMT_MU_LAW; |
@@ -843,7 +843,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
843 | size_t oss_frame_size; | 843 | size_t oss_frame_size; |
844 | int err; | 844 | int err; |
845 | int direct; | 845 | int direct; |
846 | int format, sformat, n; | 846 | snd_pcm_format_t format, sformat; |
847 | int n; | ||
847 | struct snd_mask sformat_mask; | 848 | struct snd_mask sformat_mask; |
848 | struct snd_mask mask; | 849 | struct snd_mask mask; |
849 | 850 | ||
@@ -868,11 +869,11 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
868 | _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); | 869 | _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); |
869 | snd_mask_none(&mask); | 870 | snd_mask_none(&mask); |
870 | if (atomic_read(&substream->mmap_count)) | 871 | if (atomic_read(&substream->mmap_count)) |
871 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); | 872 | snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); |
872 | else { | 873 | else { |
873 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); | 874 | snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED); |
874 | if (!direct) | 875 | if (!direct) |
875 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); | 876 | snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED); |
876 | } | 877 | } |
877 | err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask); | 878 | err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask); |
878 | if (err < 0) { | 879 | if (err < 0) { |
@@ -891,19 +892,22 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
891 | else | 892 | else |
892 | sformat = snd_pcm_plug_slave_format(format, &sformat_mask); | 893 | sformat = snd_pcm_plug_slave_format(format, &sformat_mask); |
893 | 894 | ||
894 | if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) { | 895 | if ((__force int)sformat < 0 || |
895 | for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) { | 896 | !snd_mask_test(&sformat_mask, (__force int)sformat)) { |
896 | if (snd_mask_test(&sformat_mask, sformat) && | 897 | for (sformat = (__force snd_pcm_format_t)0; |
898 | (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST; | ||
899 | sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) { | ||
900 | if (snd_mask_test(&sformat_mask, (__force int)sformat) && | ||
897 | snd_pcm_oss_format_to(sformat) >= 0) | 901 | snd_pcm_oss_format_to(sformat) >= 0) |
898 | break; | 902 | break; |
899 | } | 903 | } |
900 | if (sformat > SNDRV_PCM_FORMAT_LAST) { | 904 | if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) { |
901 | snd_printd("Cannot find a format!!!\n"); | 905 | snd_printd("Cannot find a format!!!\n"); |
902 | err = -EINVAL; | 906 | err = -EINVAL; |
903 | goto failure; | 907 | goto failure; |
904 | } | 908 | } |
905 | } | 909 | } |
906 | err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0); | 910 | err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0); |
907 | if (err < 0) | 911 | if (err < 0) |
908 | goto failure; | 912 | goto failure; |
909 | 913 | ||
@@ -912,9 +916,9 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
912 | } else { | 916 | } else { |
913 | _snd_pcm_hw_params_any(params); | 917 | _snd_pcm_hw_params_any(params); |
914 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, | 918 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS, |
915 | SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0); | 919 | (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0); |
916 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, | 920 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT, |
917 | snd_pcm_oss_format_from(runtime->oss.format), 0); | 921 | (__force int)snd_pcm_oss_format_from(runtime->oss.format), 0); |
918 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, | 922 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS, |
919 | runtime->oss.channels, 0); | 923 | runtime->oss.channels, 0); |
920 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, | 924 | _snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE, |
@@ -1185,10 +1189,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const | |||
1185 | if (in_kernel) { | 1189 | if (in_kernel) { |
1186 | mm_segment_t fs; | 1190 | mm_segment_t fs; |
1187 | fs = snd_enter_user(); | 1191 | fs = snd_enter_user(); |
1188 | ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); | 1192 | ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); |
1189 | snd_leave_user(fs); | 1193 | snd_leave_user(fs); |
1190 | } else { | 1194 | } else { |
1191 | ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames); | 1195 | ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames); |
1192 | } | 1196 | } |
1193 | if (ret != -EPIPE && ret != -ESTRPIPE) | 1197 | if (ret != -EPIPE && ret != -ESTRPIPE) |
1194 | break; | 1198 | break; |
@@ -1230,10 +1234,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p | |||
1230 | if (in_kernel) { | 1234 | if (in_kernel) { |
1231 | mm_segment_t fs; | 1235 | mm_segment_t fs; |
1232 | fs = snd_enter_user(); | 1236 | fs = snd_enter_user(); |
1233 | ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); | 1237 | ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); |
1234 | snd_leave_user(fs); | 1238 | snd_leave_user(fs); |
1235 | } else { | 1239 | } else { |
1236 | ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames); | 1240 | ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames); |
1237 | } | 1241 | } |
1238 | if (ret == -EPIPE) { | 1242 | if (ret == -EPIPE) { |
1239 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | 1243 | if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { |
@@ -1333,7 +1337,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha | |||
1333 | struct snd_pcm_plugin_channel *channels; | 1337 | struct snd_pcm_plugin_channel *channels; |
1334 | size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; | 1338 | size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8; |
1335 | if (!in_kernel) { | 1339 | if (!in_kernel) { |
1336 | if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes)) | 1340 | if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes)) |
1337 | return -EFAULT; | 1341 | return -EFAULT; |
1338 | buf = runtime->oss.buffer; | 1342 | buf = runtime->oss.buffer; |
1339 | } | 1343 | } |
@@ -1429,7 +1433,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf, | |||
1429 | struct snd_pcm_runtime *runtime = substream->runtime; | 1433 | struct snd_pcm_runtime *runtime = substream->runtime; |
1430 | snd_pcm_sframes_t frames, frames1; | 1434 | snd_pcm_sframes_t frames, frames1; |
1431 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS | 1435 | #ifdef CONFIG_SND_PCM_OSS_PLUGINS |
1432 | char __user *final_dst = (char __user *)buf; | 1436 | char __user *final_dst = (char __force __user *)buf; |
1433 | if (runtime->oss.plugin_first) { | 1437 | if (runtime->oss.plugin_first) { |
1434 | struct snd_pcm_plugin_channel *channels; | 1438 | struct snd_pcm_plugin_channel *channels; |
1435 | size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; | 1439 | size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8; |
@@ -1549,6 +1553,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) | |||
1549 | { | 1553 | { |
1550 | struct snd_pcm_runtime *runtime; | 1554 | struct snd_pcm_runtime *runtime; |
1551 | ssize_t result = 0; | 1555 | ssize_t result = 0; |
1556 | snd_pcm_state_t state; | ||
1552 | long res; | 1557 | long res; |
1553 | wait_queue_t wait; | 1558 | wait_queue_t wait; |
1554 | 1559 | ||
@@ -1570,9 +1575,9 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) | |||
1570 | result = 0; | 1575 | result = 0; |
1571 | set_current_state(TASK_INTERRUPTIBLE); | 1576 | set_current_state(TASK_INTERRUPTIBLE); |
1572 | snd_pcm_stream_lock_irq(substream); | 1577 | snd_pcm_stream_lock_irq(substream); |
1573 | res = runtime->status->state; | 1578 | state = runtime->status->state; |
1574 | snd_pcm_stream_unlock_irq(substream); | 1579 | snd_pcm_stream_unlock_irq(substream); |
1575 | if (res != SNDRV_PCM_STATE_RUNNING) { | 1580 | if (state != SNDRV_PCM_STATE_RUNNING) { |
1576 | set_current_state(TASK_RUNNING); | 1581 | set_current_state(TASK_RUNNING); |
1577 | break; | 1582 | break; |
1578 | } | 1583 | } |
@@ -1658,7 +1663,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1658 | size1); | 1663 | size1); |
1659 | size1 /= runtime->channels; /* frames */ | 1664 | size1 /= runtime->channels; /* frames */ |
1660 | fs = snd_enter_user(); | 1665 | fs = snd_enter_user(); |
1661 | snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1); | 1666 | snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1); |
1662 | snd_leave_user(fs); | 1667 | snd_leave_user(fs); |
1663 | } | 1668 | } |
1664 | } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { | 1669 | } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) { |
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c index 6751daa3bb50..71cc3ddf5c15 100644 --- a/sound/core/oss/pcm_plugin.c +++ b/sound/core/oss/pcm_plugin.c | |||
@@ -264,7 +264,7 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc | |||
264 | return frames; | 264 | return frames; |
265 | } | 265 | } |
266 | 266 | ||
267 | static int snd_pcm_plug_formats(struct snd_mask *mask, int format) | 267 | static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format) |
268 | { | 268 | { |
269 | struct snd_mask formats = *mask; | 269 | struct snd_mask formats = *mask; |
270 | u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | | 270 | u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 | |
@@ -276,16 +276,16 @@ static int snd_pcm_plug_formats(struct snd_mask *mask, int format) | |||
276 | SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE | | 276 | SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE | |
277 | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | | 277 | SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE | |
278 | SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); | 278 | SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE); |
279 | snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW); | 279 | snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW); |
280 | 280 | ||
281 | if (formats.bits[0] & (u32)linfmts) | 281 | if (formats.bits[0] & (u32)linfmts) |
282 | formats.bits[0] |= (u32)linfmts; | 282 | formats.bits[0] |= (u32)linfmts; |
283 | if (formats.bits[1] & (u32)(linfmts >> 32)) | 283 | if (formats.bits[1] & (u32)(linfmts >> 32)) |
284 | formats.bits[1] |= (u32)(linfmts >> 32); | 284 | formats.bits[1] |= (u32)(linfmts >> 32); |
285 | return snd_mask_test(&formats, format); | 285 | return snd_mask_test(&formats, (__force int)format); |
286 | } | 286 | } |
287 | 287 | ||
288 | static int preferred_formats[] = { | 288 | static snd_pcm_format_t preferred_formats[] = { |
289 | SNDRV_PCM_FORMAT_S16_LE, | 289 | SNDRV_PCM_FORMAT_S16_LE, |
290 | SNDRV_PCM_FORMAT_S16_BE, | 290 | SNDRV_PCM_FORMAT_S16_BE, |
291 | SNDRV_PCM_FORMAT_U16_LE, | 291 | SNDRV_PCM_FORMAT_U16_LE, |
@@ -306,24 +306,25 @@ static int preferred_formats[] = { | |||
306 | SNDRV_PCM_FORMAT_U8 | 306 | SNDRV_PCM_FORMAT_U8 |
307 | }; | 307 | }; |
308 | 308 | ||
309 | int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) | 309 | snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, |
310 | struct snd_mask *format_mask) | ||
310 | { | 311 | { |
311 | int i; | 312 | int i; |
312 | 313 | ||
313 | if (snd_mask_test(format_mask, format)) | 314 | if (snd_mask_test(format_mask, (__force int)format)) |
314 | return format; | 315 | return format; |
315 | if (! snd_pcm_plug_formats(format_mask, format)) | 316 | if (!snd_pcm_plug_formats(format_mask, format)) |
316 | return -EINVAL; | 317 | return (__force snd_pcm_format_t)-EINVAL; |
317 | if (snd_pcm_format_linear(format)) { | 318 | if (snd_pcm_format_linear(format)) { |
318 | unsigned int width = snd_pcm_format_width(format); | 319 | unsigned int width = snd_pcm_format_width(format); |
319 | int unsignd = snd_pcm_format_unsigned(format) > 0; | 320 | int unsignd = snd_pcm_format_unsigned(format) > 0; |
320 | int big = snd_pcm_format_big_endian(format) > 0; | 321 | int big = snd_pcm_format_big_endian(format) > 0; |
321 | unsigned int badness, best = -1; | 322 | unsigned int badness, best = -1; |
322 | int best_format = -1; | 323 | snd_pcm_format_t best_format = (__force snd_pcm_format_t)-1; |
323 | for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) { | 324 | for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) { |
324 | int f = preferred_formats[i]; | 325 | snd_pcm_format_t f = preferred_formats[i]; |
325 | unsigned int w; | 326 | unsigned int w; |
326 | if (!snd_mask_test(format_mask, f)) | 327 | if (!snd_mask_test(format_mask, (__force int)f)) |
327 | continue; | 328 | continue; |
328 | w = snd_pcm_format_width(f); | 329 | w = snd_pcm_format_width(f); |
329 | if (w >= width) | 330 | if (w >= width) |
@@ -337,17 +338,20 @@ int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) | |||
337 | best = badness; | 338 | best = badness; |
338 | } | 339 | } |
339 | } | 340 | } |
340 | return best_format >= 0 ? best_format : -EINVAL; | 341 | if ((__force int)best_format >= 0) |
342 | return best_format; | ||
343 | else | ||
344 | return (__force snd_pcm_format_t)-EINVAL; | ||
341 | } else { | 345 | } else { |
342 | switch (format) { | 346 | switch (format) { |
343 | case SNDRV_PCM_FORMAT_MU_LAW: | 347 | case SNDRV_PCM_FORMAT_MU_LAW: |
344 | for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) { | 348 | for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) { |
345 | int format1 = preferred_formats[i]; | 349 | snd_pcm_format_t format1 = preferred_formats[i]; |
346 | if (snd_mask_test(format_mask, format1)) | 350 | if (snd_mask_test(format_mask, (__force int)format1)) |
347 | return format1; | 351 | return format1; |
348 | } | 352 | } |
349 | default: | 353 | default: |
350 | return -EINVAL; | 354 | return (__force snd_pcm_format_t)-EINVAL; |
351 | } | 355 | } |
352 | } | 356 | } |
353 | } | 357 | } |
@@ -359,7 +363,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug, | |||
359 | struct snd_pcm_plugin_format tmpformat; | 363 | struct snd_pcm_plugin_format tmpformat; |
360 | struct snd_pcm_plugin_format dstformat; | 364 | struct snd_pcm_plugin_format dstformat; |
361 | struct snd_pcm_plugin_format srcformat; | 365 | struct snd_pcm_plugin_format srcformat; |
362 | int src_access, dst_access; | 366 | snd_pcm_access_t src_access, dst_access; |
363 | struct snd_pcm_plugin *plugin = NULL; | 367 | struct snd_pcm_plugin *plugin = NULL; |
364 | int err; | 368 | int err; |
365 | int stream = snd_pcm_plug_stream(plug); | 369 | int stream = snd_pcm_plug_stream(plug); |
@@ -641,7 +645,7 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str | |||
641 | } | 645 | } |
642 | 646 | ||
643 | int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset, | 647 | int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset, |
644 | size_t samples, int format) | 648 | size_t samples, snd_pcm_format_t format) |
645 | { | 649 | { |
646 | /* FIXME: sub byte resolution and odd dst_offset */ | 650 | /* FIXME: sub byte resolution and odd dst_offset */ |
647 | unsigned char *dst; | 651 | unsigned char *dst; |
@@ -688,7 +692,7 @@ int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst | |||
688 | 692 | ||
689 | int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset, | 693 | int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset, |
690 | const struct snd_pcm_channel_area *dst_area, size_t dst_offset, | 694 | const struct snd_pcm_channel_area *dst_area, size_t dst_offset, |
691 | size_t samples, int format) | 695 | size_t samples, snd_pcm_format_t format) |
692 | { | 696 | { |
693 | /* FIXME: sub byte resolution and odd dst_offset */ | 697 | /* FIXME: sub byte resolution and odd dst_offset */ |
694 | char *src, *dst; | 698 | char *src, *dst; |
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h index b9afab603711..a5035c2369a6 100644 --- a/sound/core/oss/pcm_plugin.h +++ b/sound/core/oss/pcm_plugin.h | |||
@@ -46,7 +46,7 @@ struct snd_pcm_plugin_channel { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | struct snd_pcm_plugin_format { | 48 | struct snd_pcm_plugin_format { |
49 | int format; | 49 | snd_pcm_format_t format; |
50 | unsigned int rate; | 50 | unsigned int rate; |
51 | unsigned int channels; | 51 | unsigned int channels; |
52 | }; | 52 | }; |
@@ -58,7 +58,7 @@ struct snd_pcm_plugin { | |||
58 | struct snd_pcm_plugin_format dst_format; /* destination format */ | 58 | struct snd_pcm_plugin_format dst_format; /* destination format */ |
59 | int src_width; /* sample width in bits */ | 59 | int src_width; /* sample width in bits */ |
60 | int dst_width; /* sample width in bits */ | 60 | int dst_width; /* sample width in bits */ |
61 | int access; | 61 | snd_pcm_access_t access; |
62 | snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames); | 62 | snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames); |
63 | snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames); | 63 | snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames); |
64 | snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin, | 64 | snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin, |
@@ -125,7 +125,8 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream, | |||
125 | struct snd_pcm_hw_params *params, | 125 | struct snd_pcm_hw_params *params, |
126 | struct snd_pcm_hw_params *slave_params); | 126 | struct snd_pcm_hw_params *slave_params); |
127 | 127 | ||
128 | int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask); | 128 | snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format, |
129 | struct snd_mask *format_mask); | ||
129 | 130 | ||
130 | int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin); | 131 | int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin); |
131 | 132 | ||
@@ -146,12 +147,12 @@ snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin, | |||
146 | 147 | ||
147 | int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel, | 148 | int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel, |
148 | size_t dst_offset, | 149 | size_t dst_offset, |
149 | size_t samples, int format); | 150 | size_t samples, snd_pcm_format_t format); |
150 | int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel, | 151 | int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel, |
151 | size_t src_offset, | 152 | size_t src_offset, |
152 | const struct snd_pcm_channel_area *dst_channel, | 153 | const struct snd_pcm_channel_area *dst_channel, |
153 | size_t dst_offset, | 154 | size_t dst_offset, |
154 | size_t samples, int format); | 155 | size_t samples, snd_pcm_format_t format); |
155 | 156 | ||
156 | void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size); | 157 | void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size); |
157 | void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr); | 158 | void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr); |
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c index bbe25d8c450a..c8171f5783c8 100644 --- a/sound/core/oss/route.c +++ b/sound/core/oss/route.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include "pcm_plugin.h" | 25 | #include "pcm_plugin.h" |
26 | 26 | ||
27 | static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts, | 27 | static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts, |
28 | snd_pcm_uframes_t frames, int format) | 28 | snd_pcm_uframes_t frames, snd_pcm_format_t format) |
29 | { | 29 | { |
30 | int dst = 0; | 30 | int dst = 0; |
31 | for (; dst < ndsts; ++dst) { | 31 | for (; dst < ndsts; ++dst) { |
@@ -38,7 +38,7 @@ static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts, | |||
38 | 38 | ||
39 | static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel, | 39 | static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel, |
40 | struct snd_pcm_plugin_channel *dst_channel, | 40 | struct snd_pcm_plugin_channel *dst_channel, |
41 | snd_pcm_uframes_t frames, int format) | 41 | snd_pcm_uframes_t frames, snd_pcm_format_t format) |
42 | { | 42 | { |
43 | dst_channel->enabled = 1; | 43 | dst_channel->enabled = 1; |
44 | snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format); | 44 | snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format); |
@@ -51,7 +51,7 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin, | |||
51 | { | 51 | { |
52 | int nsrcs, ndsts, dst; | 52 | int nsrcs, ndsts, dst; |
53 | struct snd_pcm_plugin_channel *dvp; | 53 | struct snd_pcm_plugin_channel *dvp; |
54 | int format; | 54 | snd_pcm_format_t format; |
55 | 55 | ||
56 | if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) | 56 | if (snd_BUG_ON(!plugin || !src_channels || !dst_channels)) |
57 | return -ENXIO; | 57 | return -ENXIO; |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 6b4b1287b314..ee9abb2d9001 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -211,9 +211,9 @@ static char *snd_pcm_format_names[] = { | |||
211 | 211 | ||
212 | const char *snd_pcm_format_name(snd_pcm_format_t format) | 212 | const char *snd_pcm_format_name(snd_pcm_format_t format) |
213 | { | 213 | { |
214 | if (format >= ARRAY_SIZE(snd_pcm_format_names)) | 214 | if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names)) |
215 | return "Unknown"; | 215 | return "Unknown"; |
216 | return snd_pcm_format_names[format]; | 216 | return snd_pcm_format_names[(__force unsigned int)format]; |
217 | } | 217 | } |
218 | EXPORT_SYMBOL_GPL(snd_pcm_format_name); | 218 | EXPORT_SYMBOL_GPL(snd_pcm_format_name); |
219 | 219 | ||
@@ -269,12 +269,12 @@ static const char *snd_pcm_stream_name(int stream) | |||
269 | 269 | ||
270 | static const char *snd_pcm_access_name(snd_pcm_access_t access) | 270 | static const char *snd_pcm_access_name(snd_pcm_access_t access) |
271 | { | 271 | { |
272 | return snd_pcm_access_names[access]; | 272 | return snd_pcm_access_names[(__force int)access]; |
273 | } | 273 | } |
274 | 274 | ||
275 | static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat) | 275 | static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat) |
276 | { | 276 | { |
277 | return snd_pcm_subformat_names[subformat]; | 277 | return snd_pcm_subformat_names[(__force int)subformat]; |
278 | } | 278 | } |
279 | 279 | ||
280 | static const char *snd_pcm_tstamp_mode_name(int mode) | 280 | static const char *snd_pcm_tstamp_mode_name(int mode) |
@@ -284,7 +284,7 @@ static const char *snd_pcm_tstamp_mode_name(int mode) | |||
284 | 284 | ||
285 | static const char *snd_pcm_state_name(snd_pcm_state_t state) | 285 | static const char *snd_pcm_state_name(snd_pcm_state_t state) |
286 | { | 286 | { |
287 | return snd_pcm_state_names[state]; | 287 | return snd_pcm_state_names[(__force int)state]; |
288 | } | 288 | } |
289 | 289 | ||
290 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 290 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c index 434af3c56d52..88f02e3866e0 100644 --- a/sound/core/pcm_misc.c +++ b/sound/core/pcm_misc.c | |||
@@ -35,7 +35,10 @@ struct pcm_format_data { | |||
35 | unsigned char silence[8]; /* silence data to fill */ | 35 | unsigned char silence[8]; /* silence data to fill */ |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = { | 38 | /* we do lots of calculations on snd_pcm_format_t; shut up sparse */ |
39 | #define INT __force int | ||
40 | |||
41 | static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = { | ||
39 | [SNDRV_PCM_FORMAT_S8] = { | 42 | [SNDRV_PCM_FORMAT_S8] = { |
40 | .width = 8, .phys = 8, .le = -1, .signd = 1, | 43 | .width = 8, .phys = 8, .le = -1, .signd = 1, |
41 | .silence = {}, | 44 | .silence = {}, |
@@ -215,9 +218,9 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = { | |||
215 | int snd_pcm_format_signed(snd_pcm_format_t format) | 218 | int snd_pcm_format_signed(snd_pcm_format_t format) |
216 | { | 219 | { |
217 | int val; | 220 | int val; |
218 | if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) | 221 | if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) |
219 | return -EINVAL; | 222 | return -EINVAL; |
220 | if ((val = pcm_formats[format].signd) < 0) | 223 | if ((val = pcm_formats[(INT)format].signd) < 0) |
221 | return -EINVAL; | 224 | return -EINVAL; |
222 | return val; | 225 | return val; |
223 | } | 226 | } |
@@ -266,9 +269,9 @@ EXPORT_SYMBOL(snd_pcm_format_linear); | |||
266 | int snd_pcm_format_little_endian(snd_pcm_format_t format) | 269 | int snd_pcm_format_little_endian(snd_pcm_format_t format) |
267 | { | 270 | { |
268 | int val; | 271 | int val; |
269 | if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) | 272 | if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) |
270 | return -EINVAL; | 273 | return -EINVAL; |
271 | if ((val = pcm_formats[format].le) < 0) | 274 | if ((val = pcm_formats[(INT)format].le) < 0) |
272 | return -EINVAL; | 275 | return -EINVAL; |
273 | return val; | 276 | return val; |
274 | } | 277 | } |
@@ -304,9 +307,9 @@ EXPORT_SYMBOL(snd_pcm_format_big_endian); | |||
304 | int snd_pcm_format_width(snd_pcm_format_t format) | 307 | int snd_pcm_format_width(snd_pcm_format_t format) |
305 | { | 308 | { |
306 | int val; | 309 | int val; |
307 | if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) | 310 | if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) |
308 | return -EINVAL; | 311 | return -EINVAL; |
309 | if ((val = pcm_formats[format].width) == 0) | 312 | if ((val = pcm_formats[(INT)format].width) == 0) |
310 | return -EINVAL; | 313 | return -EINVAL; |
311 | return val; | 314 | return val; |
312 | } | 315 | } |
@@ -323,9 +326,9 @@ EXPORT_SYMBOL(snd_pcm_format_width); | |||
323 | int snd_pcm_format_physical_width(snd_pcm_format_t format) | 326 | int snd_pcm_format_physical_width(snd_pcm_format_t format) |
324 | { | 327 | { |
325 | int val; | 328 | int val; |
326 | if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) | 329 | if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) |
327 | return -EINVAL; | 330 | return -EINVAL; |
328 | if ((val = pcm_formats[format].phys) == 0) | 331 | if ((val = pcm_formats[(INT)format].phys) == 0) |
329 | return -EINVAL; | 332 | return -EINVAL; |
330 | return val; | 333 | return val; |
331 | } | 334 | } |
@@ -358,11 +361,11 @@ EXPORT_SYMBOL(snd_pcm_format_size); | |||
358 | */ | 361 | */ |
359 | const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) | 362 | const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format) |
360 | { | 363 | { |
361 | if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) | 364 | if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) |
362 | return NULL; | 365 | return NULL; |
363 | if (! pcm_formats[format].phys) | 366 | if (! pcm_formats[(INT)format].phys) |
364 | return NULL; | 367 | return NULL; |
365 | return pcm_formats[format].silence; | 368 | return pcm_formats[(INT)format].silence; |
366 | } | 369 | } |
367 | 370 | ||
368 | EXPORT_SYMBOL(snd_pcm_format_silence_64); | 371 | EXPORT_SYMBOL(snd_pcm_format_silence_64); |
@@ -382,16 +385,16 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int | |||
382 | int width; | 385 | int width; |
383 | unsigned char *dst, *pat; | 386 | unsigned char *dst, *pat; |
384 | 387 | ||
385 | if (format < 0 || format > SNDRV_PCM_FORMAT_LAST) | 388 | if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST) |
386 | return -EINVAL; | 389 | return -EINVAL; |
387 | if (samples == 0) | 390 | if (samples == 0) |
388 | return 0; | 391 | return 0; |
389 | width = pcm_formats[format].phys; /* physical width */ | 392 | width = pcm_formats[(INT)format].phys; /* physical width */ |
390 | pat = pcm_formats[format].silence; | 393 | pat = pcm_formats[(INT)format].silence; |
391 | if (! width) | 394 | if (! width) |
392 | return -EINVAL; | 395 | return -EINVAL; |
393 | /* signed or 1 byte data */ | 396 | /* signed or 1 byte data */ |
394 | if (pcm_formats[format].signd == 1 || width <= 8) { | 397 | if (pcm_formats[(INT)format].signd == 1 || width <= 8) { |
395 | unsigned int bytes = samples * width / 8; | 398 | unsigned int bytes = samples * width / 8; |
396 | memset(data, *pat, bytes); | 399 | memset(data, *pat, bytes); |
397 | return 0; | 400 | return 0; |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 4be45e7be8ad..ae42b6509ce4 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -941,7 +941,7 @@ static struct action_ops snd_pcm_action_stop = { | |||
941 | * | 941 | * |
942 | * The state of each stream is then changed to the given state unconditionally. | 942 | * The state of each stream is then changed to the given state unconditionally. |
943 | */ | 943 | */ |
944 | int snd_pcm_stop(struct snd_pcm_substream *substream, int state) | 944 | int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) |
945 | { | 945 | { |
946 | return snd_pcm_action(&snd_pcm_action_stop, substream, state); | 946 | return snd_pcm_action(&snd_pcm_action_stop, substream, state); |
947 | } | 947 | } |
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 99a485f13648..f2436d33fbf7 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -1052,7 +1052,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf, | |||
1052 | } else { | 1052 | } else { |
1053 | #ifdef CONFIG_COMPAT | 1053 | #ifdef CONFIG_COMPAT |
1054 | if (client->convert32 && snd_seq_ev_is_varusr(&event)) { | 1054 | if (client->convert32 && snd_seq_ev_is_varusr(&event)) { |
1055 | void *ptr = compat_ptr(event.data.raw32.d[1]); | 1055 | void *ptr = (void __force *)compat_ptr(event.data.raw32.d[1]); |
1056 | event.data.ext.ptr = ptr; | 1056 | event.data.ext.ptr = ptr; |
1057 | } | 1057 | } |
1058 | #endif | 1058 | #endif |
@@ -2407,7 +2407,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) | |||
2407 | if (client == NULL) | 2407 | if (client == NULL) |
2408 | return -ENXIO; | 2408 | return -ENXIO; |
2409 | fs = snd_enter_user(); | 2409 | fs = snd_enter_user(); |
2410 | result = snd_seq_do_ioctl(client, cmd, (void __user *)arg); | 2410 | result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg); |
2411 | snd_leave_user(fs); | 2411 | snd_leave_user(fs); |
2412 | return result; | 2412 | return result; |
2413 | } | 2413 | } |
@@ -2497,9 +2497,6 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, | |||
2497 | } | 2497 | } |
2498 | 2498 | ||
2499 | 2499 | ||
2500 | void snd_seq_info_pool(struct snd_info_buffer *buffer, | ||
2501 | struct snd_seq_pool *pool, char *space); | ||
2502 | |||
2503 | /* exported to seq_info.c */ | 2500 | /* exported to seq_info.c */ |
2504 | void snd_seq_info_clients_read(struct snd_info_entry *entry, | 2501 | void snd_seq_info_clients_read(struct snd_info_entry *entry, |
2505 | struct snd_info_buffer *buffer) | 2502 | struct snd_info_buffer *buffer) |
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c index 7fb55436287f..7f50c1437675 100644 --- a/sound/core/seq/seq_memory.c +++ b/sound/core/seq/seq_memory.c | |||
@@ -86,7 +86,7 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event, | |||
86 | 86 | ||
87 | if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { | 87 | if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { |
88 | char buf[32]; | 88 | char buf[32]; |
89 | char __user *curptr = (char __user *)event->data.ext.ptr; | 89 | char __user *curptr = (char __force __user *)event->data.ext.ptr; |
90 | while (len > 0) { | 90 | while (len > 0) { |
91 | int size = sizeof(buf); | 91 | int size = sizeof(buf); |
92 | if (len < size) | 92 | if (len < size) |
@@ -157,7 +157,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char | |||
157 | if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { | 157 | if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { |
158 | if (! in_kernel) | 158 | if (! in_kernel) |
159 | return -EINVAL; | 159 | return -EINVAL; |
160 | if (copy_from_user(buf, (void __user *)event->data.ext.ptr, len)) | 160 | if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len)) |
161 | return -EFAULT; | 161 | return -EFAULT; |
162 | return newlen; | 162 | return newlen; |
163 | } | 163 | } |
@@ -343,7 +343,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event, | |||
343 | tmp->event = src->event; | 343 | tmp->event = src->event; |
344 | src = src->next; | 344 | src = src->next; |
345 | } else if (is_usrptr) { | 345 | } else if (is_usrptr) { |
346 | if (copy_from_user(&tmp->event, (char __user *)buf, size)) { | 346 | if (copy_from_user(&tmp->event, (char __force __user *)buf, size)) { |
347 | err = -EFAULT; | 347 | err = -EFAULT; |
348 | goto __error; | 348 | goto __error; |
349 | } | 349 | } |
diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h index 63e91431a29f..4a2ec779b8a7 100644 --- a/sound/core/seq/seq_memory.h +++ b/sound/core/seq/seq_memory.h | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <sound/seq_kernel.h> | 24 | #include <sound/seq_kernel.h> |
25 | #include <linux/poll.h> | 25 | #include <linux/poll.h> |
26 | 26 | ||
27 | struct snd_info_buffer; | ||
28 | |||
27 | /* container for sequencer event (internal use) */ | 29 | /* container for sequencer event (internal use) */ |
28 | struct snd_seq_event_cell { | 30 | struct snd_seq_event_cell { |
29 | struct snd_seq_event event; | 31 | struct snd_seq_event event; |
@@ -99,5 +101,7 @@ void snd_sequencer_memory_done(void); | |||
99 | /* polling */ | 101 | /* polling */ |
100 | int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait); | 102 | int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait); |
101 | 103 | ||
104 | void snd_seq_info_pool(struct snd_info_buffer *buffer, | ||
105 | struct snd_seq_pool *pool, char *space); | ||
102 | 106 | ||
103 | #endif | 107 | #endif |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 3bf7d73ac52e..e12bcd94b6db 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -412,7 +412,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port, | |||
412 | * initialization or termination of devices (see seq_midi.c). | 412 | * initialization or termination of devices (see seq_midi.c). |
413 | * | 413 | * |
414 | * If callback_all option is set, the callback function is invoked | 414 | * If callback_all option is set, the callback function is invoked |
415 | * at each connnection/disconnection. | 415 | * at each connection/disconnection. |
416 | */ | 416 | */ |
417 | 417 | ||
418 | static int subscribe_port(struct snd_seq_client *client, | 418 | static int subscribe_port(struct snd_seq_client *client, |
diff --git a/sound/core/timer.c b/sound/core/timer.c index ed016329e911..7c1cbf0a0dc4 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -186,9 +186,8 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave) | |||
186 | list_for_each_entry(master, &timer->open_list_head, open_list) { | 186 | list_for_each_entry(master, &timer->open_list_head, open_list) { |
187 | if (slave->slave_class == master->slave_class && | 187 | if (slave->slave_class == master->slave_class && |
188 | slave->slave_id == master->slave_id) { | 188 | slave->slave_id == master->slave_id) { |
189 | list_del(&slave->open_list); | 189 | list_move_tail(&slave->open_list, |
190 | list_add_tail(&slave->open_list, | 190 | &master->slave_list_head); |
191 | &master->slave_list_head); | ||
192 | spin_lock_irq(&slave_active_lock); | 191 | spin_lock_irq(&slave_active_lock); |
193 | slave->master = master; | 192 | slave->master = master; |
194 | slave->timer = master->timer; | 193 | slave->timer = master->timer; |
@@ -414,8 +413,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) | |||
414 | static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri, | 413 | static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri, |
415 | unsigned long sticks) | 414 | unsigned long sticks) |
416 | { | 415 | { |
417 | list_del(&timeri->active_list); | 416 | list_move_tail(&timeri->active_list, &timer->active_list_head); |
418 | list_add_tail(&timeri->active_list, &timer->active_list_head); | ||
419 | if (timer->running) { | 417 | if (timer->running) { |
420 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) | 418 | if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) |
421 | goto __start_now; | 419 | goto __start_now; |
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 3b9b550109cb..a89948ae9e8d 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * a subset of information returned via ctl info callback | 18 | * a subset of information returned via ctl info callback |
19 | */ | 19 | */ |
20 | struct link_ctl_info { | 20 | struct link_ctl_info { |
21 | int type; /* value type */ | 21 | snd_ctl_elem_type_t type; /* value type */ |
22 | int count; /* item count */ | 22 | int count; /* item count */ |
23 | int min_val, max_val; /* min, max values */ | 23 | int min_val, max_val; /* min, max values */ |
24 | }; | 24 | }; |
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 12b44b0b6777..a0da7755fcea 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
@@ -482,8 +482,9 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) | |||
482 | cable->streams[SNDRV_PCM_STREAM_CAPTURE]; | 482 | cable->streams[SNDRV_PCM_STREAM_CAPTURE]; |
483 | unsigned long delta_play = 0, delta_capt = 0; | 483 | unsigned long delta_play = 0, delta_capt = 0; |
484 | unsigned int running; | 484 | unsigned int running; |
485 | unsigned long flags; | ||
485 | 486 | ||
486 | spin_lock(&cable->lock); | 487 | spin_lock_irqsave(&cable->lock, flags); |
487 | running = cable->running ^ cable->pause; | 488 | running = cable->running ^ cable->pause; |
488 | if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { | 489 | if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) { |
489 | delta_play = jiffies - dpcm_play->last_jiffies; | 490 | delta_play = jiffies - dpcm_play->last_jiffies; |
@@ -495,10 +496,8 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) | |||
495 | dpcm_capt->last_jiffies += delta_capt; | 496 | dpcm_capt->last_jiffies += delta_capt; |
496 | } | 497 | } |
497 | 498 | ||
498 | if (delta_play == 0 && delta_capt == 0) { | 499 | if (delta_play == 0 && delta_capt == 0) |
499 | spin_unlock(&cable->lock); | 500 | goto unlock; |
500 | return running; | ||
501 | } | ||
502 | 501 | ||
503 | if (delta_play > delta_capt) { | 502 | if (delta_play > delta_capt) { |
504 | loopback_bytepos_update(dpcm_play, delta_play - delta_capt, | 503 | loopback_bytepos_update(dpcm_play, delta_play - delta_capt, |
@@ -510,14 +509,14 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable) | |||
510 | delta_capt = delta_play; | 509 | delta_capt = delta_play; |
511 | } | 510 | } |
512 | 511 | ||
513 | if (delta_play == 0 && delta_capt == 0) { | 512 | if (delta_play == 0 && delta_capt == 0) |
514 | spin_unlock(&cable->lock); | 513 | goto unlock; |
515 | return running; | 514 | |
516 | } | ||
517 | /* note delta_capt == delta_play at this moment */ | 515 | /* note delta_capt == delta_play at this moment */ |
518 | loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); | 516 | loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY); |
519 | loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); | 517 | loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY); |
520 | spin_unlock(&cable->lock); | 518 | unlock: |
519 | spin_unlock_irqrestore(&cable->lock, flags); | ||
521 | return running; | 520 | return running; |
522 | } | 521 | } |
523 | 522 | ||
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig new file mode 100644 index 000000000000..e486f48660fb --- /dev/null +++ b/sound/firewire/Kconfig | |||
@@ -0,0 +1,25 @@ | |||
1 | menuconfig SND_FIREWIRE | ||
2 | bool "FireWire sound devices" | ||
3 | depends on FIREWIRE | ||
4 | default y | ||
5 | help | ||
6 | Support for IEEE-1394/FireWire/iLink sound devices. | ||
7 | |||
8 | if SND_FIREWIRE && FIREWIRE | ||
9 | |||
10 | config SND_FIREWIRE_LIB | ||
11 | tristate | ||
12 | depends on SND_PCM | ||
13 | |||
14 | config SND_FIREWIRE_SPEAKERS | ||
15 | tristate "FireWire speakers" | ||
16 | select SND_PCM | ||
17 | select SND_FIREWIRE_LIB | ||
18 | help | ||
19 | Say Y here to include support for the Griffin FireWave Surround | ||
20 | and the LaCie FireWire Speakers. | ||
21 | |||
22 | To compile this driver as a module, choose M here: the module | ||
23 | will be called snd-firewire-speakers. | ||
24 | |||
25 | endif # SND_FIREWIRE | ||
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile new file mode 100644 index 000000000000..e5b1634d9ad4 --- /dev/null +++ b/sound/firewire/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \ | ||
2 | fcp.o cmp.o amdtp.o | ||
3 | snd-firewire-speakers-objs := speakers.o | ||
4 | |||
5 | obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o | ||
6 | obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o | ||
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c new file mode 100644 index 000000000000..b18140ff2b93 --- /dev/null +++ b/sound/firewire/amdtp.c | |||
@@ -0,0 +1,562 @@ | |||
1 | /* | ||
2 | * Audio and Music Data Transmission Protocol (IEC 61883-6) streams | ||
3 | * with Common Isochronous Packet (IEC 61883-1) headers | ||
4 | * | ||
5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
6 | * Licensed under the terms of the GNU General Public License, version 2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/err.h> | ||
11 | #include <linux/firewire.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include "amdtp.h" | ||
16 | |||
17 | #define TICKS_PER_CYCLE 3072 | ||
18 | #define CYCLES_PER_SECOND 8000 | ||
19 | #define TICKS_PER_SECOND (TICKS_PER_CYCLE * CYCLES_PER_SECOND) | ||
20 | |||
21 | #define TRANSFER_DELAY_TICKS 0x2e00 /* 479.17 µs */ | ||
22 | |||
23 | #define TAG_CIP 1 | ||
24 | |||
25 | #define CIP_EOH (1u << 31) | ||
26 | #define CIP_FMT_AM (0x10 << 24) | ||
27 | #define AMDTP_FDF_AM824 (0 << 19) | ||
28 | #define AMDTP_FDF_SFC_SHIFT 16 | ||
29 | |||
30 | /* TODO: make these configurable */ | ||
31 | #define INTERRUPT_INTERVAL 16 | ||
32 | #define QUEUE_LENGTH 48 | ||
33 | |||
34 | /** | ||
35 | * amdtp_out_stream_init - initialize an AMDTP output stream structure | ||
36 | * @s: the AMDTP output stream to initialize | ||
37 | * @unit: the target of the stream | ||
38 | * @flags: the packet transmission method to use | ||
39 | */ | ||
40 | int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, | ||
41 | enum cip_out_flags flags) | ||
42 | { | ||
43 | if (flags != CIP_NONBLOCKING) | ||
44 | return -EINVAL; | ||
45 | |||
46 | s->unit = fw_unit_get(unit); | ||
47 | s->flags = flags; | ||
48 | s->context = ERR_PTR(-1); | ||
49 | mutex_init(&s->mutex); | ||
50 | s->packet_index = 0; | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | EXPORT_SYMBOL(amdtp_out_stream_init); | ||
55 | |||
56 | /** | ||
57 | * amdtp_out_stream_destroy - free stream resources | ||
58 | * @s: the AMDTP output stream to destroy | ||
59 | */ | ||
60 | void amdtp_out_stream_destroy(struct amdtp_out_stream *s) | ||
61 | { | ||
62 | WARN_ON(!IS_ERR(s->context)); | ||
63 | mutex_destroy(&s->mutex); | ||
64 | fw_unit_put(s->unit); | ||
65 | } | ||
66 | EXPORT_SYMBOL(amdtp_out_stream_destroy); | ||
67 | |||
68 | /** | ||
69 | * amdtp_out_stream_set_rate - set the sample rate | ||
70 | * @s: the AMDTP output stream to configure | ||
71 | * @rate: the sample rate | ||
72 | * | ||
73 | * The sample rate must be set before the stream is started, and must not be | ||
74 | * changed while the stream is running. | ||
75 | */ | ||
76 | void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate) | ||
77 | { | ||
78 | static const struct { | ||
79 | unsigned int rate; | ||
80 | unsigned int syt_interval; | ||
81 | } rate_info[] = { | ||
82 | [CIP_SFC_32000] = { 32000, 8, }, | ||
83 | [CIP_SFC_44100] = { 44100, 8, }, | ||
84 | [CIP_SFC_48000] = { 48000, 8, }, | ||
85 | [CIP_SFC_88200] = { 88200, 16, }, | ||
86 | [CIP_SFC_96000] = { 96000, 16, }, | ||
87 | [CIP_SFC_176400] = { 176400, 32, }, | ||
88 | [CIP_SFC_192000] = { 192000, 32, }, | ||
89 | }; | ||
90 | unsigned int sfc; | ||
91 | |||
92 | if (WARN_ON(!IS_ERR(s->context))) | ||
93 | return; | ||
94 | |||
95 | for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc) | ||
96 | if (rate_info[sfc].rate == rate) { | ||
97 | s->sfc = sfc; | ||
98 | s->syt_interval = rate_info[sfc].syt_interval; | ||
99 | return; | ||
100 | } | ||
101 | WARN_ON(1); | ||
102 | } | ||
103 | EXPORT_SYMBOL(amdtp_out_stream_set_rate); | ||
104 | |||
105 | /** | ||
106 | * amdtp_out_stream_get_max_payload - get the stream's packet size | ||
107 | * @s: the AMDTP output stream | ||
108 | * | ||
109 | * This function must not be called before the stream has been configured | ||
110 | * with amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and | ||
111 | * amdtp_out_stream_set_midi(). | ||
112 | */ | ||
113 | unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s) | ||
114 | { | ||
115 | static const unsigned int max_data_blocks[] = { | ||
116 | [CIP_SFC_32000] = 4, | ||
117 | [CIP_SFC_44100] = 6, | ||
118 | [CIP_SFC_48000] = 6, | ||
119 | [CIP_SFC_88200] = 12, | ||
120 | [CIP_SFC_96000] = 12, | ||
121 | [CIP_SFC_176400] = 23, | ||
122 | [CIP_SFC_192000] = 24, | ||
123 | }; | ||
124 | |||
125 | s->data_block_quadlets = s->pcm_channels; | ||
126 | s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8); | ||
127 | |||
128 | return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets; | ||
129 | } | ||
130 | EXPORT_SYMBOL(amdtp_out_stream_get_max_payload); | ||
131 | |||
132 | static void amdtp_write_s16(struct amdtp_out_stream *s, | ||
133 | struct snd_pcm_substream *pcm, | ||
134 | __be32 *buffer, unsigned int frames); | ||
135 | static void amdtp_write_s32(struct amdtp_out_stream *s, | ||
136 | struct snd_pcm_substream *pcm, | ||
137 | __be32 *buffer, unsigned int frames); | ||
138 | |||
139 | /** | ||
140 | * amdtp_out_stream_set_pcm_format - set the PCM format | ||
141 | * @s: the AMDTP output stream to configure | ||
142 | * @format: the format of the ALSA PCM device | ||
143 | * | ||
144 | * The sample format must be set before the stream is started, and must not be | ||
145 | * changed while the stream is running. | ||
146 | */ | ||
147 | void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, | ||
148 | snd_pcm_format_t format) | ||
149 | { | ||
150 | if (WARN_ON(!IS_ERR(s->context))) | ||
151 | return; | ||
152 | |||
153 | switch (format) { | ||
154 | default: | ||
155 | WARN_ON(1); | ||
156 | /* fall through */ | ||
157 | case SNDRV_PCM_FORMAT_S16: | ||
158 | s->transfer_samples = amdtp_write_s16; | ||
159 | break; | ||
160 | case SNDRV_PCM_FORMAT_S32: | ||
161 | s->transfer_samples = amdtp_write_s32; | ||
162 | break; | ||
163 | } | ||
164 | } | ||
165 | EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format); | ||
166 | |||
167 | static unsigned int calculate_data_blocks(struct amdtp_out_stream *s) | ||
168 | { | ||
169 | unsigned int phase, data_blocks; | ||
170 | |||
171 | if (!cip_sfc_is_base_44100(s->sfc)) { | ||
172 | /* Sample_rate / 8000 is an integer, and precomputed. */ | ||
173 | data_blocks = s->data_block_state; | ||
174 | } else { | ||
175 | phase = s->data_block_state; | ||
176 | |||
177 | /* | ||
178 | * This calculates the number of data blocks per packet so that | ||
179 | * 1) the overall rate is correct and exactly synchronized to | ||
180 | * the bus clock, and | ||
181 | * 2) packets with a rounded-up number of blocks occur as early | ||
182 | * as possible in the sequence (to prevent underruns of the | ||
183 | * device's buffer). | ||
184 | */ | ||
185 | if (s->sfc == CIP_SFC_44100) | ||
186 | /* 6 6 5 6 5 6 5 ... */ | ||
187 | data_blocks = 5 + ((phase & 1) ^ | ||
188 | (phase == 0 || phase >= 40)); | ||
189 | else | ||
190 | /* 12 11 11 11 11 ... or 23 22 22 22 22 ... */ | ||
191 | data_blocks = 11 * (s->sfc >> 1) + (phase == 0); | ||
192 | if (++phase >= (80 >> (s->sfc >> 1))) | ||
193 | phase = 0; | ||
194 | s->data_block_state = phase; | ||
195 | } | ||
196 | |||
197 | return data_blocks; | ||
198 | } | ||
199 | |||
200 | static unsigned int calculate_syt(struct amdtp_out_stream *s, | ||
201 | unsigned int cycle) | ||
202 | { | ||
203 | unsigned int syt_offset, phase, index, syt; | ||
204 | |||
205 | if (s->last_syt_offset < TICKS_PER_CYCLE) { | ||
206 | if (!cip_sfc_is_base_44100(s->sfc)) | ||
207 | syt_offset = s->last_syt_offset + s->syt_offset_state; | ||
208 | else { | ||
209 | /* | ||
210 | * The time, in ticks, of the n'th SYT_INTERVAL sample is: | ||
211 | * n * SYT_INTERVAL * 24576000 / sample_rate | ||
212 | * Modulo TICKS_PER_CYCLE, the difference between successive | ||
213 | * elements is about 1386.23. Rounding the results of this | ||
214 | * formula to the SYT precision results in a sequence of | ||
215 | * differences that begins with: | ||
216 | * 1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ... | ||
217 | * This code generates _exactly_ the same sequence. | ||
218 | */ | ||
219 | phase = s->syt_offset_state; | ||
220 | index = phase % 13; | ||
221 | syt_offset = s->last_syt_offset; | ||
222 | syt_offset += 1386 + ((index && !(index & 3)) || | ||
223 | phase == 146); | ||
224 | if (++phase >= 147) | ||
225 | phase = 0; | ||
226 | s->syt_offset_state = phase; | ||
227 | } | ||
228 | } else | ||
229 | syt_offset = s->last_syt_offset - TICKS_PER_CYCLE; | ||
230 | s->last_syt_offset = syt_offset; | ||
231 | |||
232 | if (syt_offset < TICKS_PER_CYCLE) { | ||
233 | syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE; | ||
234 | syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12; | ||
235 | syt += syt_offset % TICKS_PER_CYCLE; | ||
236 | |||
237 | return syt & 0xffff; | ||
238 | } else { | ||
239 | return 0xffff; /* no info */ | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static void amdtp_write_s32(struct amdtp_out_stream *s, | ||
244 | struct snd_pcm_substream *pcm, | ||
245 | __be32 *buffer, unsigned int frames) | ||
246 | { | ||
247 | struct snd_pcm_runtime *runtime = pcm->runtime; | ||
248 | unsigned int channels, remaining_frames, frame_step, i, c; | ||
249 | const u32 *src; | ||
250 | |||
251 | channels = s->pcm_channels; | ||
252 | src = (void *)runtime->dma_area + | ||
253 | s->pcm_buffer_pointer * (runtime->frame_bits / 8); | ||
254 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | ||
255 | frame_step = s->data_block_quadlets - channels; | ||
256 | |||
257 | for (i = 0; i < frames; ++i) { | ||
258 | for (c = 0; c < channels; ++c) { | ||
259 | *buffer = cpu_to_be32((*src >> 8) | 0x40000000); | ||
260 | src++; | ||
261 | buffer++; | ||
262 | } | ||
263 | buffer += frame_step; | ||
264 | if (--remaining_frames == 0) | ||
265 | src = (void *)runtime->dma_area; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | static void amdtp_write_s16(struct amdtp_out_stream *s, | ||
270 | struct snd_pcm_substream *pcm, | ||
271 | __be32 *buffer, unsigned int frames) | ||
272 | { | ||
273 | struct snd_pcm_runtime *runtime = pcm->runtime; | ||
274 | unsigned int channels, remaining_frames, frame_step, i, c; | ||
275 | const u16 *src; | ||
276 | |||
277 | channels = s->pcm_channels; | ||
278 | src = (void *)runtime->dma_area + | ||
279 | s->pcm_buffer_pointer * (runtime->frame_bits / 8); | ||
280 | remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer; | ||
281 | frame_step = s->data_block_quadlets - channels; | ||
282 | |||
283 | for (i = 0; i < frames; ++i) { | ||
284 | for (c = 0; c < channels; ++c) { | ||
285 | *buffer = cpu_to_be32((*src << 8) | 0x40000000); | ||
286 | src++; | ||
287 | buffer++; | ||
288 | } | ||
289 | buffer += frame_step; | ||
290 | if (--remaining_frames == 0) | ||
291 | src = (void *)runtime->dma_area; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s, | ||
296 | __be32 *buffer, unsigned int frames) | ||
297 | { | ||
298 | unsigned int i, c; | ||
299 | |||
300 | for (i = 0; i < frames; ++i) { | ||
301 | for (c = 0; c < s->pcm_channels; ++c) | ||
302 | buffer[c] = cpu_to_be32(0x40000000); | ||
303 | buffer += s->data_block_quadlets; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | static void amdtp_fill_midi(struct amdtp_out_stream *s, | ||
308 | __be32 *buffer, unsigned int frames) | ||
309 | { | ||
310 | unsigned int i; | ||
311 | |||
312 | for (i = 0; i < frames; ++i) | ||
313 | buffer[s->pcm_channels + i * s->data_block_quadlets] = | ||
314 | cpu_to_be32(0x80000000); | ||
315 | } | ||
316 | |||
317 | static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle) | ||
318 | { | ||
319 | __be32 *buffer; | ||
320 | unsigned int index, data_blocks, syt, ptr; | ||
321 | struct snd_pcm_substream *pcm; | ||
322 | struct fw_iso_packet packet; | ||
323 | int err; | ||
324 | |||
325 | if (s->packet_index < 0) | ||
326 | return; | ||
327 | index = s->packet_index; | ||
328 | |||
329 | data_blocks = calculate_data_blocks(s); | ||
330 | syt = calculate_syt(s, cycle); | ||
331 | |||
332 | buffer = s->buffer.packets[index].buffer; | ||
333 | buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) | | ||
334 | (s->data_block_quadlets << 16) | | ||
335 | s->data_block_counter); | ||
336 | buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 | | ||
337 | (s->sfc << AMDTP_FDF_SFC_SHIFT) | syt); | ||
338 | buffer += 2; | ||
339 | |||
340 | pcm = ACCESS_ONCE(s->pcm); | ||
341 | if (pcm) | ||
342 | s->transfer_samples(s, pcm, buffer, data_blocks); | ||
343 | else | ||
344 | amdtp_fill_pcm_silence(s, buffer, data_blocks); | ||
345 | if (s->midi_ports) | ||
346 | amdtp_fill_midi(s, buffer, data_blocks); | ||
347 | |||
348 | s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff; | ||
349 | |||
350 | packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets; | ||
351 | packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL); | ||
352 | packet.skip = 0; | ||
353 | packet.tag = TAG_CIP; | ||
354 | packet.sy = 0; | ||
355 | packet.header_length = 0; | ||
356 | |||
357 | err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer, | ||
358 | s->buffer.packets[index].offset); | ||
359 | if (err < 0) { | ||
360 | dev_err(&s->unit->device, "queueing error: %d\n", err); | ||
361 | s->packet_index = -1; | ||
362 | amdtp_out_stream_pcm_abort(s); | ||
363 | return; | ||
364 | } | ||
365 | |||
366 | if (++index >= QUEUE_LENGTH) | ||
367 | index = 0; | ||
368 | s->packet_index = index; | ||
369 | |||
370 | if (pcm) { | ||
371 | ptr = s->pcm_buffer_pointer + data_blocks; | ||
372 | if (ptr >= pcm->runtime->buffer_size) | ||
373 | ptr -= pcm->runtime->buffer_size; | ||
374 | ACCESS_ONCE(s->pcm_buffer_pointer) = ptr; | ||
375 | |||
376 | s->pcm_period_pointer += data_blocks; | ||
377 | if (s->pcm_period_pointer >= pcm->runtime->period_size) { | ||
378 | s->pcm_period_pointer -= pcm->runtime->period_size; | ||
379 | snd_pcm_period_elapsed(pcm); | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
384 | static void out_packet_callback(struct fw_iso_context *context, u32 cycle, | ||
385 | size_t header_length, void *header, void *data) | ||
386 | { | ||
387 | struct amdtp_out_stream *s = data; | ||
388 | unsigned int i, packets = header_length / 4; | ||
389 | |||
390 | /* | ||
391 | * Compute the cycle of the last queued packet. | ||
392 | * (We need only the four lowest bits for the SYT, so we can ignore | ||
393 | * that bits 0-11 must wrap around at 3072.) | ||
394 | */ | ||
395 | cycle += QUEUE_LENGTH - packets; | ||
396 | |||
397 | for (i = 0; i < packets; ++i) | ||
398 | queue_out_packet(s, ++cycle); | ||
399 | } | ||
400 | |||
401 | static int queue_initial_skip_packets(struct amdtp_out_stream *s) | ||
402 | { | ||
403 | struct fw_iso_packet skip_packet = { | ||
404 | .skip = 1, | ||
405 | }; | ||
406 | unsigned int i; | ||
407 | int err; | ||
408 | |||
409 | for (i = 0; i < QUEUE_LENGTH; ++i) { | ||
410 | skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1, | ||
411 | INTERRUPT_INTERVAL); | ||
412 | err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0); | ||
413 | if (err < 0) | ||
414 | return err; | ||
415 | if (++s->packet_index >= QUEUE_LENGTH) | ||
416 | s->packet_index = 0; | ||
417 | } | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * amdtp_out_stream_start - start sending packets | ||
424 | * @s: the AMDTP output stream to start | ||
425 | * @channel: the isochronous channel on the bus | ||
426 | * @speed: firewire speed code | ||
427 | * | ||
428 | * The stream cannot be started until it has been configured with | ||
429 | * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and | ||
430 | * amdtp_out_stream_set_midi(); and it must be started before any | ||
431 | * PCM or MIDI device can be started. | ||
432 | */ | ||
433 | int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed) | ||
434 | { | ||
435 | static const struct { | ||
436 | unsigned int data_block; | ||
437 | unsigned int syt_offset; | ||
438 | } initial_state[] = { | ||
439 | [CIP_SFC_32000] = { 4, 3072 }, | ||
440 | [CIP_SFC_48000] = { 6, 1024 }, | ||
441 | [CIP_SFC_96000] = { 12, 1024 }, | ||
442 | [CIP_SFC_192000] = { 24, 1024 }, | ||
443 | [CIP_SFC_44100] = { 0, 67 }, | ||
444 | [CIP_SFC_88200] = { 0, 67 }, | ||
445 | [CIP_SFC_176400] = { 0, 67 }, | ||
446 | }; | ||
447 | int err; | ||
448 | |||
449 | mutex_lock(&s->mutex); | ||
450 | |||
451 | if (WARN_ON(!IS_ERR(s->context) || | ||
452 | (!s->pcm_channels && !s->midi_ports))) { | ||
453 | err = -EBADFD; | ||
454 | goto err_unlock; | ||
455 | } | ||
456 | |||
457 | s->data_block_state = initial_state[s->sfc].data_block; | ||
458 | s->syt_offset_state = initial_state[s->sfc].syt_offset; | ||
459 | s->last_syt_offset = TICKS_PER_CYCLE; | ||
460 | |||
461 | err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH, | ||
462 | amdtp_out_stream_get_max_payload(s), | ||
463 | DMA_TO_DEVICE); | ||
464 | if (err < 0) | ||
465 | goto err_unlock; | ||
466 | |||
467 | s->context = fw_iso_context_create(fw_parent_device(s->unit)->card, | ||
468 | FW_ISO_CONTEXT_TRANSMIT, | ||
469 | channel, speed, 0, | ||
470 | out_packet_callback, s); | ||
471 | if (IS_ERR(s->context)) { | ||
472 | err = PTR_ERR(s->context); | ||
473 | if (err == -EBUSY) | ||
474 | dev_err(&s->unit->device, | ||
475 | "no free output stream on this controller\n"); | ||
476 | goto err_buffer; | ||
477 | } | ||
478 | |||
479 | amdtp_out_stream_update(s); | ||
480 | |||
481 | s->packet_index = 0; | ||
482 | s->data_block_counter = 0; | ||
483 | err = queue_initial_skip_packets(s); | ||
484 | if (err < 0) | ||
485 | goto err_context; | ||
486 | |||
487 | err = fw_iso_context_start(s->context, -1, 0, 0); | ||
488 | if (err < 0) | ||
489 | goto err_context; | ||
490 | |||
491 | mutex_unlock(&s->mutex); | ||
492 | |||
493 | return 0; | ||
494 | |||
495 | err_context: | ||
496 | fw_iso_context_destroy(s->context); | ||
497 | s->context = ERR_PTR(-1); | ||
498 | err_buffer: | ||
499 | iso_packets_buffer_destroy(&s->buffer, s->unit); | ||
500 | err_unlock: | ||
501 | mutex_unlock(&s->mutex); | ||
502 | |||
503 | return err; | ||
504 | } | ||
505 | EXPORT_SYMBOL(amdtp_out_stream_start); | ||
506 | |||
507 | /** | ||
508 | * amdtp_out_stream_update - update the stream after a bus reset | ||
509 | * @s: the AMDTP output stream | ||
510 | */ | ||
511 | void amdtp_out_stream_update(struct amdtp_out_stream *s) | ||
512 | { | ||
513 | ACCESS_ONCE(s->source_node_id_field) = | ||
514 | (fw_parent_device(s->unit)->card->node_id & 0x3f) << 24; | ||
515 | } | ||
516 | EXPORT_SYMBOL(amdtp_out_stream_update); | ||
517 | |||
518 | /** | ||
519 | * amdtp_out_stream_stop - stop sending packets | ||
520 | * @s: the AMDTP output stream to stop | ||
521 | * | ||
522 | * All PCM and MIDI devices of the stream must be stopped before the stream | ||
523 | * itself can be stopped. | ||
524 | */ | ||
525 | void amdtp_out_stream_stop(struct amdtp_out_stream *s) | ||
526 | { | ||
527 | mutex_lock(&s->mutex); | ||
528 | |||
529 | if (IS_ERR(s->context)) { | ||
530 | mutex_unlock(&s->mutex); | ||
531 | return; | ||
532 | } | ||
533 | |||
534 | fw_iso_context_stop(s->context); | ||
535 | fw_iso_context_destroy(s->context); | ||
536 | s->context = ERR_PTR(-1); | ||
537 | iso_packets_buffer_destroy(&s->buffer, s->unit); | ||
538 | |||
539 | mutex_unlock(&s->mutex); | ||
540 | } | ||
541 | EXPORT_SYMBOL(amdtp_out_stream_stop); | ||
542 | |||
543 | /** | ||
544 | * amdtp_out_stream_pcm_abort - abort the running PCM device | ||
545 | * @s: the AMDTP stream about to be stopped | ||
546 | * | ||
547 | * If the isochronous stream needs to be stopped asynchronously, call this | ||
548 | * function first to stop the PCM device. | ||
549 | */ | ||
550 | void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s) | ||
551 | { | ||
552 | struct snd_pcm_substream *pcm; | ||
553 | |||
554 | pcm = ACCESS_ONCE(s->pcm); | ||
555 | if (pcm) { | ||
556 | snd_pcm_stream_lock_irq(pcm); | ||
557 | if (snd_pcm_running(pcm)) | ||
558 | snd_pcm_stop(pcm, SNDRV_PCM_STATE_XRUN); | ||
559 | snd_pcm_stream_unlock_irq(pcm); | ||
560 | } | ||
561 | } | ||
562 | EXPORT_SYMBOL(amdtp_out_stream_pcm_abort); | ||
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h new file mode 100644 index 000000000000..537a9cb83581 --- /dev/null +++ b/sound/firewire/amdtp.h | |||
@@ -0,0 +1,169 @@ | |||
1 | #ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED | ||
2 | #define SOUND_FIREWIRE_AMDTP_H_INCLUDED | ||
3 | |||
4 | #include <linux/mutex.h> | ||
5 | #include <linux/spinlock.h> | ||
6 | #include "packets-buffer.h" | ||
7 | |||
8 | /** | ||
9 | * enum cip_out_flags - describes details of the streaming protocol | ||
10 | * @CIP_NONBLOCKING: In non-blocking mode, each packet contains | ||
11 | * sample_rate/8000 samples, with rounding up or down to adjust | ||
12 | * for clock skew and left-over fractional samples. This should | ||
13 | * be used if supported by the device. | ||
14 | */ | ||
15 | enum cip_out_flags { | ||
16 | CIP_NONBLOCKING = 0, | ||
17 | }; | ||
18 | |||
19 | /** | ||
20 | * enum cip_sfc - a stream's sample rate | ||
21 | */ | ||
22 | enum cip_sfc { | ||
23 | CIP_SFC_32000 = 0, | ||
24 | CIP_SFC_44100 = 1, | ||
25 | CIP_SFC_48000 = 2, | ||
26 | CIP_SFC_88200 = 3, | ||
27 | CIP_SFC_96000 = 4, | ||
28 | CIP_SFC_176400 = 5, | ||
29 | CIP_SFC_192000 = 6, | ||
30 | }; | ||
31 | |||
32 | #define AMDTP_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \ | ||
33 | SNDRV_PCM_FMTBIT_S32) | ||
34 | |||
35 | struct fw_unit; | ||
36 | struct fw_iso_context; | ||
37 | struct snd_pcm_substream; | ||
38 | |||
39 | struct amdtp_out_stream { | ||
40 | struct fw_unit *unit; | ||
41 | enum cip_out_flags flags; | ||
42 | struct fw_iso_context *context; | ||
43 | struct mutex mutex; | ||
44 | |||
45 | enum cip_sfc sfc; | ||
46 | unsigned int data_block_quadlets; | ||
47 | unsigned int pcm_channels; | ||
48 | unsigned int midi_ports; | ||
49 | void (*transfer_samples)(struct amdtp_out_stream *s, | ||
50 | struct snd_pcm_substream *pcm, | ||
51 | __be32 *buffer, unsigned int frames); | ||
52 | |||
53 | unsigned int syt_interval; | ||
54 | unsigned int source_node_id_field; | ||
55 | struct iso_packets_buffer buffer; | ||
56 | |||
57 | struct snd_pcm_substream *pcm; | ||
58 | |||
59 | int packet_index; | ||
60 | unsigned int data_block_counter; | ||
61 | |||
62 | unsigned int data_block_state; | ||
63 | |||
64 | unsigned int last_syt_offset; | ||
65 | unsigned int syt_offset_state; | ||
66 | |||
67 | unsigned int pcm_buffer_pointer; | ||
68 | unsigned int pcm_period_pointer; | ||
69 | }; | ||
70 | |||
71 | int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit, | ||
72 | enum cip_out_flags flags); | ||
73 | void amdtp_out_stream_destroy(struct amdtp_out_stream *s); | ||
74 | |||
75 | void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate); | ||
76 | unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s); | ||
77 | |||
78 | int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed); | ||
79 | void amdtp_out_stream_update(struct amdtp_out_stream *s); | ||
80 | void amdtp_out_stream_stop(struct amdtp_out_stream *s); | ||
81 | |||
82 | void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s, | ||
83 | snd_pcm_format_t format); | ||
84 | void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s); | ||
85 | |||
86 | /** | ||
87 | * amdtp_out_stream_set_pcm - configure format of PCM samples | ||
88 | * @s: the AMDTP output stream to be configured | ||
89 | * @pcm_channels: the number of PCM samples in each data block, to be encoded | ||
90 | * as AM824 multi-bit linear audio | ||
91 | * | ||
92 | * This function must not be called while the stream is running. | ||
93 | */ | ||
94 | static inline void amdtp_out_stream_set_pcm(struct amdtp_out_stream *s, | ||
95 | unsigned int pcm_channels) | ||
96 | { | ||
97 | s->pcm_channels = pcm_channels; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * amdtp_out_stream_set_midi - configure format of MIDI data | ||
102 | * @s: the AMDTP output stream to be configured | ||
103 | * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels) | ||
104 | * | ||
105 | * This function must not be called while the stream is running. | ||
106 | */ | ||
107 | static inline void amdtp_out_stream_set_midi(struct amdtp_out_stream *s, | ||
108 | unsigned int midi_ports) | ||
109 | { | ||
110 | s->midi_ports = midi_ports; | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * amdtp_out_streaming_error - check for streaming error | ||
115 | * @s: the AMDTP output stream | ||
116 | * | ||
117 | * If this function returns true, the stream's packet queue has stopped due to | ||
118 | * an asynchronous error. | ||
119 | */ | ||
120 | static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s) | ||
121 | { | ||
122 | return s->packet_index < 0; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * amdtp_out_stream_pcm_prepare - prepare PCM device for running | ||
127 | * @s: the AMDTP output stream | ||
128 | * | ||
129 | * This function should be called from the PCM device's .prepare callback. | ||
130 | */ | ||
131 | static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s) | ||
132 | { | ||
133 | s->pcm_buffer_pointer = 0; | ||
134 | s->pcm_period_pointer = 0; | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device | ||
139 | * @s: the AMDTP output stream | ||
140 | * @pcm: the PCM device to be started, or %NULL to stop the current device | ||
141 | * | ||
142 | * Call this function on a running isochronous stream to enable the actual | ||
143 | * transmission of PCM data. This function should be called from the PCM | ||
144 | * device's .trigger callback. | ||
145 | */ | ||
146 | static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s, | ||
147 | struct snd_pcm_substream *pcm) | ||
148 | { | ||
149 | ACCESS_ONCE(s->pcm) = pcm; | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * amdtp_out_stream_pcm_pointer - get the PCM buffer position | ||
154 | * @s: the AMDTP output stream that transports the PCM data | ||
155 | * | ||
156 | * Returns the current buffer position, in frames. | ||
157 | */ | ||
158 | static inline unsigned long | ||
159 | amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s) | ||
160 | { | ||
161 | return ACCESS_ONCE(s->pcm_buffer_pointer); | ||
162 | } | ||
163 | |||
164 | static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc) | ||
165 | { | ||
166 | return sfc & 1; | ||
167 | } | ||
168 | |||
169 | #endif | ||
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c new file mode 100644 index 000000000000..4a37f3a6fab9 --- /dev/null +++ b/sound/firewire/cmp.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * Connection Management Procedures (IEC 61883-1) helper functions | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Licensed under the terms of the GNU General Public License, version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/device.h> | ||
9 | #include <linux/firewire.h> | ||
10 | #include <linux/firewire-constants.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include "lib.h" | ||
14 | #include "iso-resources.h" | ||
15 | #include "cmp.h" | ||
16 | |||
17 | #define IMPR_SPEED_MASK 0xc0000000 | ||
18 | #define IMPR_SPEED_SHIFT 30 | ||
19 | #define IMPR_XSPEED_MASK 0x00000060 | ||
20 | #define IMPR_XSPEED_SHIFT 5 | ||
21 | #define IMPR_PLUGS_MASK 0x0000001f | ||
22 | |||
23 | #define IPCR_ONLINE 0x80000000 | ||
24 | #define IPCR_BCAST_CONN 0x40000000 | ||
25 | #define IPCR_P2P_CONN_MASK 0x3f000000 | ||
26 | #define IPCR_P2P_CONN_SHIFT 24 | ||
27 | #define IPCR_CHANNEL_MASK 0x003f0000 | ||
28 | #define IPCR_CHANNEL_SHIFT 16 | ||
29 | |||
30 | enum bus_reset_handling { | ||
31 | ABORT_ON_BUS_RESET, | ||
32 | SUCCEED_ON_BUS_RESET, | ||
33 | }; | ||
34 | |||
35 | static __attribute__((format(printf, 2, 3))) | ||
36 | void cmp_error(struct cmp_connection *c, const char *fmt, ...) | ||
37 | { | ||
38 | va_list va; | ||
39 | |||
40 | va_start(va, fmt); | ||
41 | dev_err(&c->resources.unit->device, "%cPCR%u: %pV", | ||
42 | 'i', c->pcr_index, &(struct va_format){ fmt, &va }); | ||
43 | va_end(va); | ||
44 | } | ||
45 | |||
46 | static int pcr_modify(struct cmp_connection *c, | ||
47 | __be32 (*modify)(struct cmp_connection *c, __be32 old), | ||
48 | int (*check)(struct cmp_connection *c, __be32 pcr), | ||
49 | enum bus_reset_handling bus_reset_handling) | ||
50 | { | ||
51 | struct fw_device *device = fw_parent_device(c->resources.unit); | ||
52 | __be32 *buffer = c->resources.buffer; | ||
53 | int generation = c->resources.generation; | ||
54 | int rcode, errors = 0; | ||
55 | __be32 old_arg; | ||
56 | int err; | ||
57 | |||
58 | buffer[0] = c->last_pcr_value; | ||
59 | for (;;) { | ||
60 | old_arg = buffer[0]; | ||
61 | buffer[1] = modify(c, buffer[0]); | ||
62 | |||
63 | rcode = fw_run_transaction( | ||
64 | device->card, TCODE_LOCK_COMPARE_SWAP, | ||
65 | device->node_id, generation, device->max_speed, | ||
66 | CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index), | ||
67 | buffer, 8); | ||
68 | |||
69 | if (rcode == RCODE_COMPLETE) { | ||
70 | if (buffer[0] == old_arg) /* success? */ | ||
71 | break; | ||
72 | |||
73 | if (check) { | ||
74 | err = check(c, buffer[0]); | ||
75 | if (err < 0) | ||
76 | return err; | ||
77 | } | ||
78 | } else if (rcode == RCODE_GENERATION) | ||
79 | goto bus_reset; | ||
80 | else if (rcode_is_permanent_error(rcode) || ++errors >= 3) | ||
81 | goto io_error; | ||
82 | } | ||
83 | c->last_pcr_value = buffer[1]; | ||
84 | |||
85 | return 0; | ||
86 | |||
87 | io_error: | ||
88 | cmp_error(c, "transaction failed: %s\n", rcode_string(rcode)); | ||
89 | return -EIO; | ||
90 | |||
91 | bus_reset: | ||
92 | return bus_reset_handling == ABORT_ON_BUS_RESET ? -EAGAIN : 0; | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * cmp_connection_init - initializes a connection manager | ||
98 | * @c: the connection manager to initialize | ||
99 | * @unit: a unit of the target device | ||
100 | * @ipcr_index: the index of the iPCR on the target device | ||
101 | */ | ||
102 | int cmp_connection_init(struct cmp_connection *c, | ||
103 | struct fw_unit *unit, | ||
104 | unsigned int ipcr_index) | ||
105 | { | ||
106 | __be32 impr_be; | ||
107 | u32 impr; | ||
108 | int err; | ||
109 | |||
110 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | ||
111 | CSR_REGISTER_BASE + CSR_IMPR, | ||
112 | &impr_be, 4); | ||
113 | if (err < 0) | ||
114 | return err; | ||
115 | impr = be32_to_cpu(impr_be); | ||
116 | |||
117 | if (ipcr_index >= (impr & IMPR_PLUGS_MASK)) | ||
118 | return -EINVAL; | ||
119 | |||
120 | err = fw_iso_resources_init(&c->resources, unit); | ||
121 | if (err < 0) | ||
122 | return err; | ||
123 | |||
124 | c->connected = false; | ||
125 | mutex_init(&c->mutex); | ||
126 | c->last_pcr_value = cpu_to_be32(0x80000000); | ||
127 | c->pcr_index = ipcr_index; | ||
128 | c->max_speed = (impr & IMPR_SPEED_MASK) >> IMPR_SPEED_SHIFT; | ||
129 | if (c->max_speed == SCODE_BETA) | ||
130 | c->max_speed += (impr & IMPR_XSPEED_MASK) >> IMPR_XSPEED_SHIFT; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | EXPORT_SYMBOL(cmp_connection_init); | ||
135 | |||
136 | /** | ||
137 | * cmp_connection_destroy - free connection manager resources | ||
138 | * @c: the connection manager | ||
139 | */ | ||
140 | void cmp_connection_destroy(struct cmp_connection *c) | ||
141 | { | ||
142 | WARN_ON(c->connected); | ||
143 | mutex_destroy(&c->mutex); | ||
144 | fw_iso_resources_destroy(&c->resources); | ||
145 | } | ||
146 | EXPORT_SYMBOL(cmp_connection_destroy); | ||
147 | |||
148 | |||
149 | static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) | ||
150 | { | ||
151 | ipcr &= ~cpu_to_be32(IPCR_BCAST_CONN | | ||
152 | IPCR_P2P_CONN_MASK | | ||
153 | IPCR_CHANNEL_MASK); | ||
154 | ipcr |= cpu_to_be32(1 << IPCR_P2P_CONN_SHIFT); | ||
155 | ipcr |= cpu_to_be32(c->resources.channel << IPCR_CHANNEL_SHIFT); | ||
156 | |||
157 | return ipcr; | ||
158 | } | ||
159 | |||
160 | static int ipcr_set_check(struct cmp_connection *c, __be32 ipcr) | ||
161 | { | ||
162 | if (ipcr & cpu_to_be32(IPCR_BCAST_CONN | | ||
163 | IPCR_P2P_CONN_MASK)) { | ||
164 | cmp_error(c, "plug is already in use\n"); | ||
165 | return -EBUSY; | ||
166 | } | ||
167 | if (!(ipcr & cpu_to_be32(IPCR_ONLINE))) { | ||
168 | cmp_error(c, "plug is not on-line\n"); | ||
169 | return -ECONNREFUSED; | ||
170 | } | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * cmp_connection_establish - establish a connection to the target | ||
177 | * @c: the connection manager | ||
178 | * @max_payload_bytes: the amount of data (including CIP headers) per packet | ||
179 | * | ||
180 | * This function establishes a point-to-point connection from the local | ||
181 | * computer to the target by allocating isochronous resources (channel and | ||
182 | * bandwidth) and setting the target's input plug control register. When this | ||
183 | * function succeeds, the caller is responsible for starting transmitting | ||
184 | * packets. | ||
185 | */ | ||
186 | int cmp_connection_establish(struct cmp_connection *c, | ||
187 | unsigned int max_payload_bytes) | ||
188 | { | ||
189 | int err; | ||
190 | |||
191 | if (WARN_ON(c->connected)) | ||
192 | return -EISCONN; | ||
193 | |||
194 | c->speed = min(c->max_speed, | ||
195 | fw_parent_device(c->resources.unit)->max_speed); | ||
196 | |||
197 | mutex_lock(&c->mutex); | ||
198 | |||
199 | retry_after_bus_reset: | ||
200 | err = fw_iso_resources_allocate(&c->resources, | ||
201 | max_payload_bytes, c->speed); | ||
202 | if (err < 0) | ||
203 | goto err_mutex; | ||
204 | |||
205 | err = pcr_modify(c, ipcr_set_modify, ipcr_set_check, | ||
206 | ABORT_ON_BUS_RESET); | ||
207 | if (err == -EAGAIN) { | ||
208 | fw_iso_resources_free(&c->resources); | ||
209 | goto retry_after_bus_reset; | ||
210 | } | ||
211 | if (err < 0) | ||
212 | goto err_resources; | ||
213 | |||
214 | c->connected = true; | ||
215 | |||
216 | mutex_unlock(&c->mutex); | ||
217 | |||
218 | return 0; | ||
219 | |||
220 | err_resources: | ||
221 | fw_iso_resources_free(&c->resources); | ||
222 | err_mutex: | ||
223 | mutex_unlock(&c->mutex); | ||
224 | |||
225 | return err; | ||
226 | } | ||
227 | EXPORT_SYMBOL(cmp_connection_establish); | ||
228 | |||
229 | /** | ||
230 | * cmp_connection_update - update the connection after a bus reset | ||
231 | * @c: the connection manager | ||
232 | * | ||
233 | * This function must be called from the driver's .update handler to reestablish | ||
234 | * any connection that might have been active. | ||
235 | * | ||
236 | * Returns zero on success, or a negative error code. On an error, the | ||
237 | * connection is broken and the caller must stop transmitting iso packets. | ||
238 | */ | ||
239 | int cmp_connection_update(struct cmp_connection *c) | ||
240 | { | ||
241 | int err; | ||
242 | |||
243 | mutex_lock(&c->mutex); | ||
244 | |||
245 | if (!c->connected) { | ||
246 | mutex_unlock(&c->mutex); | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | err = fw_iso_resources_update(&c->resources); | ||
251 | if (err < 0) | ||
252 | goto err_unconnect; | ||
253 | |||
254 | err = pcr_modify(c, ipcr_set_modify, ipcr_set_check, | ||
255 | SUCCEED_ON_BUS_RESET); | ||
256 | if (err < 0) | ||
257 | goto err_resources; | ||
258 | |||
259 | mutex_unlock(&c->mutex); | ||
260 | |||
261 | return 0; | ||
262 | |||
263 | err_resources: | ||
264 | fw_iso_resources_free(&c->resources); | ||
265 | err_unconnect: | ||
266 | c->connected = false; | ||
267 | mutex_unlock(&c->mutex); | ||
268 | |||
269 | return err; | ||
270 | } | ||
271 | EXPORT_SYMBOL(cmp_connection_update); | ||
272 | |||
273 | |||
274 | static __be32 ipcr_break_modify(struct cmp_connection *c, __be32 ipcr) | ||
275 | { | ||
276 | return ipcr & ~cpu_to_be32(IPCR_BCAST_CONN | IPCR_P2P_CONN_MASK); | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * cmp_connection_break - break the connection to the target | ||
281 | * @c: the connection manager | ||
282 | * | ||
283 | * This function deactives the connection in the target's input plug control | ||
284 | * register, and frees the isochronous resources of the connection. Before | ||
285 | * calling this function, the caller should cease transmitting packets. | ||
286 | */ | ||
287 | void cmp_connection_break(struct cmp_connection *c) | ||
288 | { | ||
289 | int err; | ||
290 | |||
291 | mutex_lock(&c->mutex); | ||
292 | |||
293 | if (!c->connected) { | ||
294 | mutex_unlock(&c->mutex); | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | err = pcr_modify(c, ipcr_break_modify, NULL, SUCCEED_ON_BUS_RESET); | ||
299 | if (err < 0) | ||
300 | cmp_error(c, "plug is still connected\n"); | ||
301 | |||
302 | fw_iso_resources_free(&c->resources); | ||
303 | |||
304 | c->connected = false; | ||
305 | |||
306 | mutex_unlock(&c->mutex); | ||
307 | } | ||
308 | EXPORT_SYMBOL(cmp_connection_break); | ||
diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h new file mode 100644 index 000000000000..f47de08feb12 --- /dev/null +++ b/sound/firewire/cmp.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef SOUND_FIREWIRE_CMP_H_INCLUDED | ||
2 | #define SOUND_FIREWIRE_CMP_H_INCLUDED | ||
3 | |||
4 | #include <linux/mutex.h> | ||
5 | #include <linux/types.h> | ||
6 | #include "iso-resources.h" | ||
7 | |||
8 | struct fw_unit; | ||
9 | |||
10 | /** | ||
11 | * struct cmp_connection - manages an isochronous connection to a device | ||
12 | * @speed: the connection's actual speed | ||
13 | * | ||
14 | * This structure manages (using CMP) an isochronous stream from the local | ||
15 | * computer to a device's input plug (iPCR). | ||
16 | * | ||
17 | * There is no corresponding oPCR created on the local computer, so it is not | ||
18 | * possible to overlay connections on top of this one. | ||
19 | */ | ||
20 | struct cmp_connection { | ||
21 | int speed; | ||
22 | /* private: */ | ||
23 | bool connected; | ||
24 | struct mutex mutex; | ||
25 | struct fw_iso_resources resources; | ||
26 | __be32 last_pcr_value; | ||
27 | unsigned int pcr_index; | ||
28 | unsigned int max_speed; | ||
29 | }; | ||
30 | |||
31 | int cmp_connection_init(struct cmp_connection *connection, | ||
32 | struct fw_unit *unit, | ||
33 | unsigned int ipcr_index); | ||
34 | void cmp_connection_destroy(struct cmp_connection *connection); | ||
35 | |||
36 | int cmp_connection_establish(struct cmp_connection *connection, | ||
37 | unsigned int max_payload); | ||
38 | int cmp_connection_update(struct cmp_connection *connection); | ||
39 | void cmp_connection_break(struct cmp_connection *connection); | ||
40 | |||
41 | #endif | ||
diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c new file mode 100644 index 000000000000..ec578b5ad8da --- /dev/null +++ b/sound/firewire/fcp.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Function Control Protocol (IEC 61883-1) helper functions | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Licensed under the terms of the GNU General Public License, version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/device.h> | ||
9 | #include <linux/firewire.h> | ||
10 | #include <linux/firewire-constants.h> | ||
11 | #include <linux/list.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/wait.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include "fcp.h" | ||
18 | #include "lib.h" | ||
19 | |||
20 | #define CTS_AVC 0x00 | ||
21 | |||
22 | #define ERROR_RETRIES 3 | ||
23 | #define ERROR_DELAY_MS 5 | ||
24 | #define FCP_TIMEOUT_MS 125 | ||
25 | |||
26 | static DEFINE_SPINLOCK(transactions_lock); | ||
27 | static LIST_HEAD(transactions); | ||
28 | |||
29 | enum fcp_state { | ||
30 | STATE_PENDING, | ||
31 | STATE_BUS_RESET, | ||
32 | STATE_COMPLETE, | ||
33 | }; | ||
34 | |||
35 | struct fcp_transaction { | ||
36 | struct list_head list; | ||
37 | struct fw_unit *unit; | ||
38 | void *response_buffer; | ||
39 | unsigned int response_size; | ||
40 | unsigned int response_match_bytes; | ||
41 | enum fcp_state state; | ||
42 | wait_queue_head_t wait; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * fcp_avc_transaction - send an AV/C command and wait for its response | ||
47 | * @unit: a unit on the target device | ||
48 | * @command: a buffer containing the command frame; must be DMA-able | ||
49 | * @command_size: the size of @command | ||
50 | * @response: a buffer for the response frame | ||
51 | * @response_size: the maximum size of @response | ||
52 | * @response_match_bytes: a bitmap specifying the bytes used to detect the | ||
53 | * correct response frame | ||
54 | * | ||
55 | * This function sends a FCP command frame to the target and waits for the | ||
56 | * corresponding response frame to be returned. | ||
57 | * | ||
58 | * Because it is possible for multiple FCP transactions to be active at the | ||
59 | * same time, the correct response frame is detected by the value of certain | ||
60 | * bytes. These bytes must be set in @response before calling this function, | ||
61 | * and the corresponding bits must be set in @response_match_bytes. | ||
62 | * | ||
63 | * @command and @response can point to the same buffer. | ||
64 | * | ||
65 | * Asynchronous operation (INTERIM, NOTIFY) is not supported at the moment. | ||
66 | * | ||
67 | * Returns the actual size of the response frame, or a negative error code. | ||
68 | */ | ||
69 | int fcp_avc_transaction(struct fw_unit *unit, | ||
70 | const void *command, unsigned int command_size, | ||
71 | void *response, unsigned int response_size, | ||
72 | unsigned int response_match_bytes) | ||
73 | { | ||
74 | struct fcp_transaction t; | ||
75 | int tcode, ret, tries = 0; | ||
76 | |||
77 | t.unit = unit; | ||
78 | t.response_buffer = response; | ||
79 | t.response_size = response_size; | ||
80 | t.response_match_bytes = response_match_bytes; | ||
81 | t.state = STATE_PENDING; | ||
82 | init_waitqueue_head(&t.wait); | ||
83 | |||
84 | spin_lock_irq(&transactions_lock); | ||
85 | list_add_tail(&t.list, &transactions); | ||
86 | spin_unlock_irq(&transactions_lock); | ||
87 | |||
88 | for (;;) { | ||
89 | tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST | ||
90 | : TCODE_WRITE_BLOCK_REQUEST; | ||
91 | ret = snd_fw_transaction(t.unit, tcode, | ||
92 | CSR_REGISTER_BASE + CSR_FCP_COMMAND, | ||
93 | (void *)command, command_size); | ||
94 | if (ret < 0) | ||
95 | break; | ||
96 | |||
97 | wait_event_timeout(t.wait, t.state != STATE_PENDING, | ||
98 | msecs_to_jiffies(FCP_TIMEOUT_MS)); | ||
99 | |||
100 | if (t.state == STATE_COMPLETE) { | ||
101 | ret = t.response_size; | ||
102 | break; | ||
103 | } else if (t.state == STATE_BUS_RESET) { | ||
104 | msleep(ERROR_DELAY_MS); | ||
105 | } else if (++tries >= ERROR_RETRIES) { | ||
106 | dev_err(&t.unit->device, "FCP command timed out\n"); | ||
107 | ret = -EIO; | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | spin_lock_irq(&transactions_lock); | ||
113 | list_del(&t.list); | ||
114 | spin_unlock_irq(&transactions_lock); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | EXPORT_SYMBOL(fcp_avc_transaction); | ||
119 | |||
120 | /** | ||
121 | * fcp_bus_reset - inform the target handler about a bus reset | ||
122 | * @unit: the unit that might be used by fcp_avc_transaction() | ||
123 | * | ||
124 | * This function must be called from the driver's .update handler to inform | ||
125 | * the FCP transaction handler that a bus reset has happened. Any pending FCP | ||
126 | * transactions are retried. | ||
127 | */ | ||
128 | void fcp_bus_reset(struct fw_unit *unit) | ||
129 | { | ||
130 | struct fcp_transaction *t; | ||
131 | |||
132 | spin_lock_irq(&transactions_lock); | ||
133 | list_for_each_entry(t, &transactions, list) { | ||
134 | if (t->unit == unit && | ||
135 | t->state == STATE_PENDING) { | ||
136 | t->state = STATE_BUS_RESET; | ||
137 | wake_up(&t->wait); | ||
138 | } | ||
139 | } | ||
140 | spin_unlock_irq(&transactions_lock); | ||
141 | } | ||
142 | EXPORT_SYMBOL(fcp_bus_reset); | ||
143 | |||
144 | /* checks whether the response matches the masked bytes in response_buffer */ | ||
145 | static bool is_matching_response(struct fcp_transaction *transaction, | ||
146 | const void *response, size_t length) | ||
147 | { | ||
148 | const u8 *p1, *p2; | ||
149 | unsigned int mask, i; | ||
150 | |||
151 | p1 = response; | ||
152 | p2 = transaction->response_buffer; | ||
153 | mask = transaction->response_match_bytes; | ||
154 | |||
155 | for (i = 0; ; ++i) { | ||
156 | if ((mask & 1) && p1[i] != p2[i]) | ||
157 | return false; | ||
158 | mask >>= 1; | ||
159 | if (!mask) | ||
160 | return true; | ||
161 | if (--length == 0) | ||
162 | return false; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void fcp_response(struct fw_card *card, struct fw_request *request, | ||
167 | int tcode, int destination, int source, | ||
168 | int generation, unsigned long long offset, | ||
169 | void *data, size_t length, void *callback_data) | ||
170 | { | ||
171 | struct fcp_transaction *t; | ||
172 | unsigned long flags; | ||
173 | |||
174 | if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC) | ||
175 | return; | ||
176 | |||
177 | spin_lock_irqsave(&transactions_lock, flags); | ||
178 | list_for_each_entry(t, &transactions, list) { | ||
179 | struct fw_device *device = fw_parent_device(t->unit); | ||
180 | if (device->card != card || | ||
181 | device->generation != generation) | ||
182 | continue; | ||
183 | smp_rmb(); /* node_id vs. generation */ | ||
184 | if (device->node_id != source) | ||
185 | continue; | ||
186 | |||
187 | if (t->state == STATE_PENDING && | ||
188 | is_matching_response(t, data, length)) { | ||
189 | t->state = STATE_COMPLETE; | ||
190 | t->response_size = min((unsigned int)length, | ||
191 | t->response_size); | ||
192 | memcpy(t->response_buffer, data, t->response_size); | ||
193 | wake_up(&t->wait); | ||
194 | } | ||
195 | } | ||
196 | spin_unlock_irqrestore(&transactions_lock, flags); | ||
197 | } | ||
198 | |||
199 | static struct fw_address_handler response_register_handler = { | ||
200 | .length = 0x200, | ||
201 | .address_callback = fcp_response, | ||
202 | }; | ||
203 | |||
204 | static int __init fcp_module_init(void) | ||
205 | { | ||
206 | static const struct fw_address_region response_register_region = { | ||
207 | .start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE, | ||
208 | .end = CSR_REGISTER_BASE + CSR_FCP_END, | ||
209 | }; | ||
210 | |||
211 | fw_core_add_address_handler(&response_register_handler, | ||
212 | &response_register_region); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static void __exit fcp_module_exit(void) | ||
218 | { | ||
219 | WARN_ON(!list_empty(&transactions)); | ||
220 | fw_core_remove_address_handler(&response_register_handler); | ||
221 | } | ||
222 | |||
223 | module_init(fcp_module_init); | ||
224 | module_exit(fcp_module_exit); | ||
diff --git a/sound/firewire/fcp.h b/sound/firewire/fcp.h new file mode 100644 index 000000000000..86595688bd91 --- /dev/null +++ b/sound/firewire/fcp.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef SOUND_FIREWIRE_FCP_H_INCLUDED | ||
2 | #define SOUND_FIREWIRE_FCP_H_INCLUDED | ||
3 | |||
4 | struct fw_unit; | ||
5 | |||
6 | int fcp_avc_transaction(struct fw_unit *unit, | ||
7 | const void *command, unsigned int command_size, | ||
8 | void *response, unsigned int response_size, | ||
9 | unsigned int response_match_bytes); | ||
10 | void fcp_bus_reset(struct fw_unit *unit); | ||
11 | |||
12 | #endif | ||
diff --git a/sound/firewire/iso-resources.c b/sound/firewire/iso-resources.c new file mode 100644 index 000000000000..775dbd5f3445 --- /dev/null +++ b/sound/firewire/iso-resources.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * isochronous resources helper functions | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Licensed under the terms of the GNU General Public License, version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/device.h> | ||
9 | #include <linux/firewire.h> | ||
10 | #include <linux/firewire-constants.h> | ||
11 | #include <linux/jiffies.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include "iso-resources.h" | ||
17 | |||
18 | /** | ||
19 | * fw_iso_resources_init - initializes a &struct fw_iso_resources | ||
20 | * @r: the resource manager to initialize | ||
21 | * @unit: the device unit for which the resources will be needed | ||
22 | * | ||
23 | * If the device does not support all channel numbers, change @r->channels_mask | ||
24 | * after calling this function. | ||
25 | */ | ||
26 | int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit) | ||
27 | { | ||
28 | r->buffer = kmalloc(2 * 4, GFP_KERNEL); | ||
29 | if (!r->buffer) | ||
30 | return -ENOMEM; | ||
31 | |||
32 | r->channels_mask = ~0uLL; | ||
33 | r->unit = fw_unit_get(unit); | ||
34 | mutex_init(&r->mutex); | ||
35 | r->allocated = false; | ||
36 | |||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | /** | ||
41 | * fw_iso_resources_destroy - destroy a resource manager | ||
42 | * @r: the resource manager that is no longer needed | ||
43 | */ | ||
44 | void fw_iso_resources_destroy(struct fw_iso_resources *r) | ||
45 | { | ||
46 | WARN_ON(r->allocated); | ||
47 | kfree(r->buffer); | ||
48 | mutex_destroy(&r->mutex); | ||
49 | fw_unit_put(r->unit); | ||
50 | } | ||
51 | |||
52 | static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed) | ||
53 | { | ||
54 | unsigned int bytes, s400_bytes; | ||
55 | |||
56 | /* iso packets have three header quadlets and quadlet-aligned payload */ | ||
57 | bytes = 3 * 4 + ALIGN(max_payload_bytes, 4); | ||
58 | |||
59 | /* convert to bandwidth units (quadlets at S1600 = bytes at S400) */ | ||
60 | if (speed <= SCODE_400) | ||
61 | s400_bytes = bytes * (1 << (SCODE_400 - speed)); | ||
62 | else | ||
63 | s400_bytes = DIV_ROUND_UP(bytes, 1 << (speed - SCODE_400)); | ||
64 | |||
65 | return s400_bytes; | ||
66 | } | ||
67 | |||
68 | static int current_bandwidth_overhead(struct fw_card *card) | ||
69 | { | ||
70 | /* | ||
71 | * Under the usual pessimistic assumption (cable length 4.5 m), the | ||
72 | * isochronous overhead for N cables is 1.797 µs + N * 0.494 µs, or | ||
73 | * 88.3 + N * 24.3 in bandwidth units. | ||
74 | * | ||
75 | * The calculation below tries to deduce N from the current gap count. | ||
76 | * If the gap count has been optimized by measuring the actual packet | ||
77 | * transmission time, this derived overhead should be near the actual | ||
78 | * overhead as well. | ||
79 | */ | ||
80 | return card->gap_count < 63 ? card->gap_count * 97 / 10 + 89 : 512; | ||
81 | } | ||
82 | |||
83 | static int wait_isoch_resource_delay_after_bus_reset(struct fw_card *card) | ||
84 | { | ||
85 | for (;;) { | ||
86 | s64 delay = (card->reset_jiffies + HZ) - get_jiffies_64(); | ||
87 | if (delay <= 0) | ||
88 | return 0; | ||
89 | if (schedule_timeout_interruptible(delay) > 0) | ||
90 | return -ERESTARTSYS; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * fw_iso_resources_allocate - allocate isochronous channel and bandwidth | ||
96 | * @r: the resource manager | ||
97 | * @max_payload_bytes: the amount of data (including CIP headers) per packet | ||
98 | * @speed: the speed (e.g., SCODE_400) at which the packets will be sent | ||
99 | * | ||
100 | * This function allocates one isochronous channel and enough bandwidth for the | ||
101 | * specified packet size. | ||
102 | * | ||
103 | * Returns the channel number that the caller must use for streaming, or | ||
104 | * a negative error code. Due to potentionally long delays, this function is | ||
105 | * interruptible and can return -ERESTARTSYS. On success, the caller is | ||
106 | * responsible for calling fw_iso_resources_update() on bus resets, and | ||
107 | * fw_iso_resources_free() when the resources are not longer needed. | ||
108 | */ | ||
109 | int fw_iso_resources_allocate(struct fw_iso_resources *r, | ||
110 | unsigned int max_payload_bytes, int speed) | ||
111 | { | ||
112 | struct fw_card *card = fw_parent_device(r->unit)->card; | ||
113 | int bandwidth, channel, err; | ||
114 | |||
115 | if (WARN_ON(r->allocated)) | ||
116 | return -EBADFD; | ||
117 | |||
118 | r->bandwidth = packet_bandwidth(max_payload_bytes, speed); | ||
119 | |||
120 | retry_after_bus_reset: | ||
121 | spin_lock_irq(&card->lock); | ||
122 | r->generation = card->generation; | ||
123 | r->bandwidth_overhead = current_bandwidth_overhead(card); | ||
124 | spin_unlock_irq(&card->lock); | ||
125 | |||
126 | err = wait_isoch_resource_delay_after_bus_reset(card); | ||
127 | if (err < 0) | ||
128 | return err; | ||
129 | |||
130 | mutex_lock(&r->mutex); | ||
131 | |||
132 | bandwidth = r->bandwidth + r->bandwidth_overhead; | ||
133 | fw_iso_resource_manage(card, r->generation, r->channels_mask, | ||
134 | &channel, &bandwidth, true, r->buffer); | ||
135 | if (channel == -EAGAIN) { | ||
136 | mutex_unlock(&r->mutex); | ||
137 | goto retry_after_bus_reset; | ||
138 | } | ||
139 | if (channel >= 0) { | ||
140 | r->channel = channel; | ||
141 | r->allocated = true; | ||
142 | } else { | ||
143 | if (channel == -EBUSY) | ||
144 | dev_err(&r->unit->device, | ||
145 | "isochronous resources exhausted\n"); | ||
146 | else | ||
147 | dev_err(&r->unit->device, | ||
148 | "isochronous resource allocation failed\n"); | ||
149 | } | ||
150 | |||
151 | mutex_unlock(&r->mutex); | ||
152 | |||
153 | return channel; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * fw_iso_resources_update - update resource allocations after a bus reset | ||
158 | * @r: the resource manager | ||
159 | * | ||
160 | * This function must be called from the driver's .update handler to reallocate | ||
161 | * any resources that were allocated before the bus reset. It is safe to call | ||
162 | * this function if no resources are currently allocated. | ||
163 | * | ||
164 | * Returns a negative error code on failure. If this happens, the caller must | ||
165 | * stop streaming. | ||
166 | */ | ||
167 | int fw_iso_resources_update(struct fw_iso_resources *r) | ||
168 | { | ||
169 | struct fw_card *card = fw_parent_device(r->unit)->card; | ||
170 | int bandwidth, channel; | ||
171 | |||
172 | mutex_lock(&r->mutex); | ||
173 | |||
174 | if (!r->allocated) { | ||
175 | mutex_unlock(&r->mutex); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | spin_lock_irq(&card->lock); | ||
180 | r->generation = card->generation; | ||
181 | r->bandwidth_overhead = current_bandwidth_overhead(card); | ||
182 | spin_unlock_irq(&card->lock); | ||
183 | |||
184 | bandwidth = r->bandwidth + r->bandwidth_overhead; | ||
185 | |||
186 | fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, | ||
187 | &channel, &bandwidth, true, r->buffer); | ||
188 | /* | ||
189 | * When another bus reset happens, pretend that the allocation | ||
190 | * succeeded; we will try again for the new generation later. | ||
191 | */ | ||
192 | if (channel < 0 && channel != -EAGAIN) { | ||
193 | r->allocated = false; | ||
194 | if (channel == -EBUSY) | ||
195 | dev_err(&r->unit->device, | ||
196 | "isochronous resources exhausted\n"); | ||
197 | else | ||
198 | dev_err(&r->unit->device, | ||
199 | "isochronous resource allocation failed\n"); | ||
200 | } | ||
201 | |||
202 | mutex_unlock(&r->mutex); | ||
203 | |||
204 | return channel; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * fw_iso_resources_free - frees allocated resources | ||
209 | * @r: the resource manager | ||
210 | * | ||
211 | * This function deallocates the channel and bandwidth, if allocated. | ||
212 | */ | ||
213 | void fw_iso_resources_free(struct fw_iso_resources *r) | ||
214 | { | ||
215 | struct fw_card *card = fw_parent_device(r->unit)->card; | ||
216 | int bandwidth, channel; | ||
217 | |||
218 | mutex_lock(&r->mutex); | ||
219 | |||
220 | if (r->allocated) { | ||
221 | bandwidth = r->bandwidth + r->bandwidth_overhead; | ||
222 | fw_iso_resource_manage(card, r->generation, 1uLL << r->channel, | ||
223 | &channel, &bandwidth, false, r->buffer); | ||
224 | if (channel < 0) | ||
225 | dev_err(&r->unit->device, | ||
226 | "isochronous resource deallocation failed\n"); | ||
227 | |||
228 | r->allocated = false; | ||
229 | } | ||
230 | |||
231 | mutex_unlock(&r->mutex); | ||
232 | } | ||
diff --git a/sound/firewire/iso-resources.h b/sound/firewire/iso-resources.h new file mode 100644 index 000000000000..3f0730e4d841 --- /dev/null +++ b/sound/firewire/iso-resources.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED | ||
2 | #define SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED | ||
3 | |||
4 | #include <linux/mutex.h> | ||
5 | #include <linux/types.h> | ||
6 | |||
7 | struct fw_unit; | ||
8 | |||
9 | /** | ||
10 | * struct fw_iso_resources - manages channel/bandwidth allocation | ||
11 | * @channels_mask: if the device does not support all channel numbers, set this | ||
12 | * bit mask to something else than the default (all ones) | ||
13 | * | ||
14 | * This structure manages (de)allocation of isochronous resources (channel and | ||
15 | * bandwidth) for one isochronous stream. | ||
16 | */ | ||
17 | struct fw_iso_resources { | ||
18 | u64 channels_mask; | ||
19 | /* private: */ | ||
20 | struct fw_unit *unit; | ||
21 | struct mutex mutex; | ||
22 | unsigned int channel; | ||
23 | unsigned int bandwidth; /* in bandwidth units, without overhead */ | ||
24 | unsigned int bandwidth_overhead; | ||
25 | int generation; /* in which allocation is valid */ | ||
26 | bool allocated; | ||
27 | __be32 *buffer; | ||
28 | }; | ||
29 | |||
30 | int fw_iso_resources_init(struct fw_iso_resources *r, | ||
31 | struct fw_unit *unit); | ||
32 | void fw_iso_resources_destroy(struct fw_iso_resources *r); | ||
33 | |||
34 | int fw_iso_resources_allocate(struct fw_iso_resources *r, | ||
35 | unsigned int max_payload_bytes, int speed); | ||
36 | int fw_iso_resources_update(struct fw_iso_resources *r); | ||
37 | void fw_iso_resources_free(struct fw_iso_resources *r); | ||
38 | |||
39 | #endif | ||
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c new file mode 100644 index 000000000000..4750cea2210e --- /dev/null +++ b/sound/firewire/lib.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * miscellaneous helper functions | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Licensed under the terms of the GNU General Public License, version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/delay.h> | ||
9 | #include <linux/device.h> | ||
10 | #include <linux/firewire.h> | ||
11 | #include <linux/module.h> | ||
12 | #include "lib.h" | ||
13 | |||
14 | #define ERROR_RETRY_DELAY_MS 5 | ||
15 | |||
16 | /** | ||
17 | * rcode_string - convert a firewire result code to a string | ||
18 | * @rcode: the result | ||
19 | */ | ||
20 | const char *rcode_string(unsigned int rcode) | ||
21 | { | ||
22 | static const char *const names[] = { | ||
23 | [RCODE_COMPLETE] = "complete", | ||
24 | [RCODE_CONFLICT_ERROR] = "conflict error", | ||
25 | [RCODE_DATA_ERROR] = "data error", | ||
26 | [RCODE_TYPE_ERROR] = "type error", | ||
27 | [RCODE_ADDRESS_ERROR] = "address error", | ||
28 | [RCODE_SEND_ERROR] = "send error", | ||
29 | [RCODE_CANCELLED] = "cancelled", | ||
30 | [RCODE_BUSY] = "busy", | ||
31 | [RCODE_GENERATION] = "generation", | ||
32 | [RCODE_NO_ACK] = "no ack", | ||
33 | }; | ||
34 | |||
35 | if (rcode < ARRAY_SIZE(names) && names[rcode]) | ||
36 | return names[rcode]; | ||
37 | else | ||
38 | return "unknown"; | ||
39 | } | ||
40 | EXPORT_SYMBOL(rcode_string); | ||
41 | |||
42 | /** | ||
43 | * snd_fw_transaction - send a request and wait for its completion | ||
44 | * @unit: the driver's unit on the target device | ||
45 | * @tcode: the transaction code | ||
46 | * @offset: the address in the target's address space | ||
47 | * @buffer: input/output data | ||
48 | * @length: length of @buffer | ||
49 | * | ||
50 | * Submits an asynchronous request to the target device, and waits for the | ||
51 | * response. The node ID and the current generation are derived from @unit. | ||
52 | * On a bus reset or an error, the transaction is retried a few times. | ||
53 | * Returns zero on success, or a negative error code. | ||
54 | */ | ||
55 | int snd_fw_transaction(struct fw_unit *unit, int tcode, | ||
56 | u64 offset, void *buffer, size_t length) | ||
57 | { | ||
58 | struct fw_device *device = fw_parent_device(unit); | ||
59 | int generation, rcode, tries = 0; | ||
60 | |||
61 | for (;;) { | ||
62 | generation = device->generation; | ||
63 | smp_rmb(); /* node_id vs. generation */ | ||
64 | rcode = fw_run_transaction(device->card, tcode, | ||
65 | device->node_id, generation, | ||
66 | device->max_speed, offset, | ||
67 | buffer, length); | ||
68 | |||
69 | if (rcode == RCODE_COMPLETE) | ||
70 | return 0; | ||
71 | |||
72 | if (rcode_is_permanent_error(rcode) || ++tries >= 3) { | ||
73 | dev_err(&unit->device, "transaction failed: %s\n", | ||
74 | rcode_string(rcode)); | ||
75 | return -EIO; | ||
76 | } | ||
77 | |||
78 | msleep(ERROR_RETRY_DELAY_MS); | ||
79 | } | ||
80 | } | ||
81 | EXPORT_SYMBOL(snd_fw_transaction); | ||
82 | |||
83 | MODULE_DESCRIPTION("FireWire audio helper functions"); | ||
84 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | ||
85 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h new file mode 100644 index 000000000000..064f3fd9ab06 --- /dev/null +++ b/sound/firewire/lib.h | |||
@@ -0,0 +1,19 @@ | |||
1 | #ifndef SOUND_FIREWIRE_LIB_H_INCLUDED | ||
2 | #define SOUND_FIREWIRE_LIB_H_INCLUDED | ||
3 | |||
4 | #include <linux/firewire-constants.h> | ||
5 | #include <linux/types.h> | ||
6 | |||
7 | struct fw_unit; | ||
8 | |||
9 | int snd_fw_transaction(struct fw_unit *unit, int tcode, | ||
10 | u64 offset, void *buffer, size_t length); | ||
11 | const char *rcode_string(unsigned int rcode); | ||
12 | |||
13 | /* returns true if retrying the transaction would not make sense */ | ||
14 | static inline bool rcode_is_permanent_error(int rcode) | ||
15 | { | ||
16 | return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR; | ||
17 | } | ||
18 | |||
19 | #endif | ||
diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c new file mode 100644 index 000000000000..1e20e60ba6a6 --- /dev/null +++ b/sound/firewire/packets-buffer.c | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * helpers for managing a buffer for many packets | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Licensed under the terms of the GNU General Public License, version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/firewire.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include "packets-buffer.h" | ||
11 | |||
12 | /** | ||
13 | * iso_packets_buffer_init - allocates the memory for packets | ||
14 | * @b: the buffer structure to initialize | ||
15 | * @unit: the device at the other end of the stream | ||
16 | * @count: the number of packets | ||
17 | * @packet_size: the (maximum) size of a packet, in bytes | ||
18 | * @direction: %DMA_TO_DEVICE or %DMA_FROM_DEVICE | ||
19 | */ | ||
20 | int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, | ||
21 | unsigned int count, unsigned int packet_size, | ||
22 | enum dma_data_direction direction) | ||
23 | { | ||
24 | unsigned int packets_per_page, pages; | ||
25 | unsigned int i, page_index, offset_in_page; | ||
26 | void *p; | ||
27 | int err; | ||
28 | |||
29 | b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL); | ||
30 | if (!b->packets) { | ||
31 | err = -ENOMEM; | ||
32 | goto error; | ||
33 | } | ||
34 | |||
35 | packet_size = L1_CACHE_ALIGN(packet_size); | ||
36 | packets_per_page = PAGE_SIZE / packet_size; | ||
37 | if (WARN_ON(!packets_per_page)) { | ||
38 | err = -EINVAL; | ||
39 | goto error; | ||
40 | } | ||
41 | pages = DIV_ROUND_UP(count, packets_per_page); | ||
42 | |||
43 | err = fw_iso_buffer_init(&b->iso_buffer, fw_parent_device(unit)->card, | ||
44 | pages, direction); | ||
45 | if (err < 0) | ||
46 | goto err_packets; | ||
47 | |||
48 | for (i = 0; i < count; ++i) { | ||
49 | page_index = i / packets_per_page; | ||
50 | p = page_address(b->iso_buffer.pages[page_index]); | ||
51 | offset_in_page = (i % packets_per_page) * packet_size; | ||
52 | b->packets[i].buffer = p + offset_in_page; | ||
53 | b->packets[i].offset = page_index * PAGE_SIZE + offset_in_page; | ||
54 | } | ||
55 | |||
56 | return 0; | ||
57 | |||
58 | err_packets: | ||
59 | kfree(b->packets); | ||
60 | error: | ||
61 | return err; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * iso_packets_buffer_destroy - frees packet buffer resources | ||
66 | * @b: the buffer structure to free | ||
67 | * @unit: the device at the other end of the stream | ||
68 | */ | ||
69 | void iso_packets_buffer_destroy(struct iso_packets_buffer *b, | ||
70 | struct fw_unit *unit) | ||
71 | { | ||
72 | fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card); | ||
73 | kfree(b->packets); | ||
74 | } | ||
diff --git a/sound/firewire/packets-buffer.h b/sound/firewire/packets-buffer.h new file mode 100644 index 000000000000..6513c5cb6ea9 --- /dev/null +++ b/sound/firewire/packets-buffer.h | |||
@@ -0,0 +1,26 @@ | |||
1 | #ifndef SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED | ||
2 | #define SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED | ||
3 | |||
4 | #include <linux/dma-mapping.h> | ||
5 | #include <linux/firewire.h> | ||
6 | |||
7 | /** | ||
8 | * struct iso_packets_buffer - manages a buffer for many packets | ||
9 | * @iso_buffer: the memory containing the packets | ||
10 | * @packets: an array, with each element pointing to one packet | ||
11 | */ | ||
12 | struct iso_packets_buffer { | ||
13 | struct fw_iso_buffer iso_buffer; | ||
14 | struct { | ||
15 | void *buffer; | ||
16 | unsigned int offset; | ||
17 | } *packets; | ||
18 | }; | ||
19 | |||
20 | int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit, | ||
21 | unsigned int count, unsigned int packet_size, | ||
22 | enum dma_data_direction direction); | ||
23 | void iso_packets_buffer_destroy(struct iso_packets_buffer *b, | ||
24 | struct fw_unit *unit); | ||
25 | |||
26 | #endif | ||
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c new file mode 100644 index 000000000000..0fce9218abb1 --- /dev/null +++ b/sound/firewire/speakers.c | |||
@@ -0,0 +1,858 @@ | |||
1 | /* | ||
2 | * OXFW970-based speakers driver | ||
3 | * | ||
4 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> | ||
5 | * Licensed under the terms of the GNU General Public License, version 2. | ||
6 | */ | ||
7 | |||
8 | #include <linux/device.h> | ||
9 | #include <linux/firewire.h> | ||
10 | #include <linux/firewire-constants.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/mod_devicetable.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <sound/control.h> | ||
16 | #include <sound/core.h> | ||
17 | #include <sound/initval.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include "cmp.h" | ||
21 | #include "fcp.h" | ||
22 | #include "amdtp.h" | ||
23 | #include "lib.h" | ||
24 | |||
25 | #define OXFORD_FIRMWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x50000) | ||
26 | /* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */ | ||
27 | |||
28 | #define OXFORD_HARDWARE_ID_ADDRESS (CSR_REGISTER_BASE + 0x90020) | ||
29 | #define OXFORD_HARDWARE_ID_OXFW970 0x39443841 | ||
30 | #define OXFORD_HARDWARE_ID_OXFW971 0x39373100 | ||
31 | |||
32 | #define VENDOR_GRIFFIN 0x001292 | ||
33 | #define VENDOR_LACIE 0x00d04b | ||
34 | |||
35 | #define SPECIFIER_1394TA 0x00a02d | ||
36 | #define VERSION_AVC 0x010001 | ||
37 | |||
38 | struct device_info { | ||
39 | const char *driver_name; | ||
40 | const char *short_name; | ||
41 | const char *long_name; | ||
42 | int (*pcm_constraints)(struct snd_pcm_runtime *runtime); | ||
43 | unsigned int mixer_channels; | ||
44 | u8 mute_fb_id; | ||
45 | u8 volume_fb_id; | ||
46 | }; | ||
47 | |||
48 | struct fwspk { | ||
49 | struct snd_card *card; | ||
50 | struct fw_unit *unit; | ||
51 | const struct device_info *device_info; | ||
52 | struct snd_pcm_substream *pcm; | ||
53 | struct mutex mutex; | ||
54 | struct cmp_connection connection; | ||
55 | struct amdtp_out_stream stream; | ||
56 | bool stream_running; | ||
57 | bool mute; | ||
58 | s16 volume[6]; | ||
59 | s16 volume_min; | ||
60 | s16 volume_max; | ||
61 | }; | ||
62 | |||
63 | MODULE_DESCRIPTION("FireWire speakers driver"); | ||
64 | MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | ||
65 | MODULE_LICENSE("GPL v2"); | ||
66 | |||
67 | static int firewave_rate_constraint(struct snd_pcm_hw_params *params, | ||
68 | struct snd_pcm_hw_rule *rule) | ||
69 | { | ||
70 | static unsigned int stereo_rates[] = { 48000, 96000 }; | ||
71 | struct snd_interval *channels = | ||
72 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
73 | struct snd_interval *rate = | ||
74 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
75 | |||
76 | /* two channels work only at 48/96 kHz */ | ||
77 | if (snd_interval_max(channels) < 6) | ||
78 | return snd_interval_list(rate, 2, stereo_rates, 0); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int firewave_channels_constraint(struct snd_pcm_hw_params *params, | ||
83 | struct snd_pcm_hw_rule *rule) | ||
84 | { | ||
85 | static const struct snd_interval all_channels = { .min = 6, .max = 6 }; | ||
86 | struct snd_interval *rate = | ||
87 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
88 | struct snd_interval *channels = | ||
89 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
90 | |||
91 | /* 32/44.1 kHz work only with all six channels */ | ||
92 | if (snd_interval_max(rate) < 48000) | ||
93 | return snd_interval_refine(channels, &all_channels); | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int firewave_constraints(struct snd_pcm_runtime *runtime) | ||
98 | { | ||
99 | static unsigned int channels_list[] = { 2, 6 }; | ||
100 | static struct snd_pcm_hw_constraint_list channels_list_constraint = { | ||
101 | .count = 2, | ||
102 | .list = channels_list, | ||
103 | }; | ||
104 | int err; | ||
105 | |||
106 | runtime->hw.rates = SNDRV_PCM_RATE_32000 | | ||
107 | SNDRV_PCM_RATE_44100 | | ||
108 | SNDRV_PCM_RATE_48000 | | ||
109 | SNDRV_PCM_RATE_96000; | ||
110 | runtime->hw.channels_max = 6; | ||
111 | |||
112 | err = snd_pcm_hw_constraint_list(runtime, 0, | ||
113 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
114 | &channels_list_constraint); | ||
115 | if (err < 0) | ||
116 | return err; | ||
117 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
118 | firewave_rate_constraint, NULL, | ||
119 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
120 | if (err < 0) | ||
121 | return err; | ||
122 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
123 | firewave_channels_constraint, NULL, | ||
124 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
125 | if (err < 0) | ||
126 | return err; | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int lacie_speakers_constraints(struct snd_pcm_runtime *runtime) | ||
132 | { | ||
133 | runtime->hw.rates = SNDRV_PCM_RATE_32000 | | ||
134 | SNDRV_PCM_RATE_44100 | | ||
135 | SNDRV_PCM_RATE_48000 | | ||
136 | SNDRV_PCM_RATE_88200 | | ||
137 | SNDRV_PCM_RATE_96000; | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int fwspk_open(struct snd_pcm_substream *substream) | ||
143 | { | ||
144 | static const struct snd_pcm_hardware hardware = { | ||
145 | .info = SNDRV_PCM_INFO_MMAP | | ||
146 | SNDRV_PCM_INFO_MMAP_VALID | | ||
147 | SNDRV_PCM_INFO_BATCH | | ||
148 | SNDRV_PCM_INFO_INTERLEAVED | | ||
149 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
150 | .formats = AMDTP_OUT_PCM_FORMAT_BITS, | ||
151 | .channels_min = 2, | ||
152 | .channels_max = 2, | ||
153 | .buffer_bytes_max = 4 * 1024 * 1024, | ||
154 | .period_bytes_min = 1, | ||
155 | .period_bytes_max = UINT_MAX, | ||
156 | .periods_min = 1, | ||
157 | .periods_max = UINT_MAX, | ||
158 | }; | ||
159 | struct fwspk *fwspk = substream->private_data; | ||
160 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
161 | int err; | ||
162 | |||
163 | runtime->hw = hardware; | ||
164 | |||
165 | err = fwspk->device_info->pcm_constraints(runtime); | ||
166 | if (err < 0) | ||
167 | return err; | ||
168 | err = snd_pcm_limit_hw_rates(runtime); | ||
169 | if (err < 0) | ||
170 | return err; | ||
171 | |||
172 | err = snd_pcm_hw_constraint_minmax(runtime, | ||
173 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | ||
174 | 5000, 8192000); | ||
175 | if (err < 0) | ||
176 | return err; | ||
177 | |||
178 | err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | ||
179 | if (err < 0) | ||
180 | return err; | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int fwspk_close(struct snd_pcm_substream *substream) | ||
186 | { | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void fwspk_stop_stream(struct fwspk *fwspk) | ||
191 | { | ||
192 | if (fwspk->stream_running) { | ||
193 | amdtp_out_stream_stop(&fwspk->stream); | ||
194 | cmp_connection_break(&fwspk->connection); | ||
195 | fwspk->stream_running = false; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | static int fwspk_set_rate(struct fwspk *fwspk, unsigned int sfc) | ||
200 | { | ||
201 | u8 *buf; | ||
202 | int err; | ||
203 | |||
204 | buf = kmalloc(8, GFP_KERNEL); | ||
205 | if (!buf) | ||
206 | return -ENOMEM; | ||
207 | |||
208 | buf[0] = 0x00; /* AV/C, CONTROL */ | ||
209 | buf[1] = 0xff; /* unit */ | ||
210 | buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ | ||
211 | buf[3] = 0x00; /* plug 0 */ | ||
212 | buf[4] = 0x90; /* format: audio */ | ||
213 | buf[5] = 0x00 | sfc; /* AM824, frequency */ | ||
214 | buf[6] = 0xff; /* SYT (not used) */ | ||
215 | buf[7] = 0xff; | ||
216 | |||
217 | err = fcp_avc_transaction(fwspk->unit, buf, 8, buf, 8, | ||
218 | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5)); | ||
219 | if (err < 0) | ||
220 | goto error; | ||
221 | if (err < 6 || buf[0] != 0x09 /* ACCEPTED */) { | ||
222 | dev_err(&fwspk->unit->device, "failed to set sample rate\n"); | ||
223 | err = -EIO; | ||
224 | goto error; | ||
225 | } | ||
226 | |||
227 | err = 0; | ||
228 | |||
229 | error: | ||
230 | kfree(buf); | ||
231 | |||
232 | return err; | ||
233 | } | ||
234 | |||
235 | static int fwspk_hw_params(struct snd_pcm_substream *substream, | ||
236 | struct snd_pcm_hw_params *hw_params) | ||
237 | { | ||
238 | struct fwspk *fwspk = substream->private_data; | ||
239 | int err; | ||
240 | |||
241 | mutex_lock(&fwspk->mutex); | ||
242 | fwspk_stop_stream(fwspk); | ||
243 | mutex_unlock(&fwspk->mutex); | ||
244 | |||
245 | err = snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
246 | params_buffer_bytes(hw_params)); | ||
247 | if (err < 0) | ||
248 | goto error; | ||
249 | |||
250 | amdtp_out_stream_set_rate(&fwspk->stream, params_rate(hw_params)); | ||
251 | amdtp_out_stream_set_pcm(&fwspk->stream, params_channels(hw_params)); | ||
252 | |||
253 | amdtp_out_stream_set_pcm_format(&fwspk->stream, | ||
254 | params_format(hw_params)); | ||
255 | |||
256 | err = fwspk_set_rate(fwspk, fwspk->stream.sfc); | ||
257 | if (err < 0) | ||
258 | goto err_buffer; | ||
259 | |||
260 | return 0; | ||
261 | |||
262 | err_buffer: | ||
263 | snd_pcm_lib_free_vmalloc_buffer(substream); | ||
264 | error: | ||
265 | return err; | ||
266 | } | ||
267 | |||
268 | static int fwspk_hw_free(struct snd_pcm_substream *substream) | ||
269 | { | ||
270 | struct fwspk *fwspk = substream->private_data; | ||
271 | |||
272 | mutex_lock(&fwspk->mutex); | ||
273 | fwspk_stop_stream(fwspk); | ||
274 | mutex_unlock(&fwspk->mutex); | ||
275 | |||
276 | return snd_pcm_lib_free_vmalloc_buffer(substream); | ||
277 | } | ||
278 | |||
279 | static int fwspk_prepare(struct snd_pcm_substream *substream) | ||
280 | { | ||
281 | struct fwspk *fwspk = substream->private_data; | ||
282 | int err; | ||
283 | |||
284 | mutex_lock(&fwspk->mutex); | ||
285 | |||
286 | if (amdtp_out_streaming_error(&fwspk->stream)) | ||
287 | fwspk_stop_stream(fwspk); | ||
288 | |||
289 | if (!fwspk->stream_running) { | ||
290 | err = cmp_connection_establish(&fwspk->connection, | ||
291 | amdtp_out_stream_get_max_payload(&fwspk->stream)); | ||
292 | if (err < 0) | ||
293 | goto err_mutex; | ||
294 | |||
295 | err = amdtp_out_stream_start(&fwspk->stream, | ||
296 | fwspk->connection.resources.channel, | ||
297 | fwspk->connection.speed); | ||
298 | if (err < 0) | ||
299 | goto err_connection; | ||
300 | |||
301 | fwspk->stream_running = true; | ||
302 | } | ||
303 | |||
304 | mutex_unlock(&fwspk->mutex); | ||
305 | |||
306 | amdtp_out_stream_pcm_prepare(&fwspk->stream); | ||
307 | |||
308 | return 0; | ||
309 | |||
310 | err_connection: | ||
311 | cmp_connection_break(&fwspk->connection); | ||
312 | err_mutex: | ||
313 | mutex_unlock(&fwspk->mutex); | ||
314 | |||
315 | return err; | ||
316 | } | ||
317 | |||
318 | static int fwspk_trigger(struct snd_pcm_substream *substream, int cmd) | ||
319 | { | ||
320 | struct fwspk *fwspk = substream->private_data; | ||
321 | struct snd_pcm_substream *pcm; | ||
322 | |||
323 | switch (cmd) { | ||
324 | case SNDRV_PCM_TRIGGER_START: | ||
325 | pcm = substream; | ||
326 | break; | ||
327 | case SNDRV_PCM_TRIGGER_STOP: | ||
328 | pcm = NULL; | ||
329 | break; | ||
330 | default: | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | amdtp_out_stream_pcm_trigger(&fwspk->stream, pcm); | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | static snd_pcm_uframes_t fwspk_pointer(struct snd_pcm_substream *substream) | ||
338 | { | ||
339 | struct fwspk *fwspk = substream->private_data; | ||
340 | |||
341 | return amdtp_out_stream_pcm_pointer(&fwspk->stream); | ||
342 | } | ||
343 | |||
344 | static int fwspk_create_pcm(struct fwspk *fwspk) | ||
345 | { | ||
346 | static struct snd_pcm_ops ops = { | ||
347 | .open = fwspk_open, | ||
348 | .close = fwspk_close, | ||
349 | .ioctl = snd_pcm_lib_ioctl, | ||
350 | .hw_params = fwspk_hw_params, | ||
351 | .hw_free = fwspk_hw_free, | ||
352 | .prepare = fwspk_prepare, | ||
353 | .trigger = fwspk_trigger, | ||
354 | .pointer = fwspk_pointer, | ||
355 | .page = snd_pcm_lib_get_vmalloc_page, | ||
356 | .mmap = snd_pcm_lib_mmap_vmalloc, | ||
357 | }; | ||
358 | struct snd_pcm *pcm; | ||
359 | int err; | ||
360 | |||
361 | err = snd_pcm_new(fwspk->card, "OXFW970", 0, 1, 0, &pcm); | ||
362 | if (err < 0) | ||
363 | return err; | ||
364 | pcm->private_data = fwspk; | ||
365 | strcpy(pcm->name, fwspk->device_info->short_name); | ||
366 | fwspk->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | ||
367 | fwspk->pcm->ops = &ops; | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | enum control_action { CTL_READ, CTL_WRITE }; | ||
372 | enum control_attribute { | ||
373 | CTL_MIN = 0x02, | ||
374 | CTL_MAX = 0x03, | ||
375 | CTL_CURRENT = 0x10, | ||
376 | }; | ||
377 | |||
378 | static int fwspk_mute_command(struct fwspk *fwspk, bool *value, | ||
379 | enum control_action action) | ||
380 | { | ||
381 | u8 *buf; | ||
382 | u8 response_ok; | ||
383 | int err; | ||
384 | |||
385 | buf = kmalloc(11, GFP_KERNEL); | ||
386 | if (!buf) | ||
387 | return -ENOMEM; | ||
388 | |||
389 | if (action == CTL_READ) { | ||
390 | buf[0] = 0x01; /* AV/C, STATUS */ | ||
391 | response_ok = 0x0c; /* STABLE */ | ||
392 | } else { | ||
393 | buf[0] = 0x00; /* AV/C, CONTROL */ | ||
394 | response_ok = 0x09; /* ACCEPTED */ | ||
395 | } | ||
396 | buf[1] = 0x08; /* audio unit 0 */ | ||
397 | buf[2] = 0xb8; /* FUNCTION BLOCK */ | ||
398 | buf[3] = 0x81; /* function block type: feature */ | ||
399 | buf[4] = fwspk->device_info->mute_fb_id; /* function block ID */ | ||
400 | buf[5] = 0x10; /* control attribute: current */ | ||
401 | buf[6] = 0x02; /* selector length */ | ||
402 | buf[7] = 0x00; /* audio channel number */ | ||
403 | buf[8] = 0x01; /* control selector: mute */ | ||
404 | buf[9] = 0x01; /* control data length */ | ||
405 | if (action == CTL_READ) | ||
406 | buf[10] = 0xff; | ||
407 | else | ||
408 | buf[10] = *value ? 0x70 : 0x60; | ||
409 | |||
410 | err = fcp_avc_transaction(fwspk->unit, buf, 11, buf, 11, 0x3fe); | ||
411 | if (err < 0) | ||
412 | goto error; | ||
413 | if (err < 11) { | ||
414 | dev_err(&fwspk->unit->device, "short FCP response\n"); | ||
415 | err = -EIO; | ||
416 | goto error; | ||
417 | } | ||
418 | if (buf[0] != response_ok) { | ||
419 | dev_err(&fwspk->unit->device, "mute command failed\n"); | ||
420 | err = -EIO; | ||
421 | goto error; | ||
422 | } | ||
423 | if (action == CTL_READ) | ||
424 | *value = buf[10] == 0x70; | ||
425 | |||
426 | err = 0; | ||
427 | |||
428 | error: | ||
429 | kfree(buf); | ||
430 | |||
431 | return err; | ||
432 | } | ||
433 | |||
434 | static int fwspk_volume_command(struct fwspk *fwspk, s16 *value, | ||
435 | unsigned int channel, | ||
436 | enum control_attribute attribute, | ||
437 | enum control_action action) | ||
438 | { | ||
439 | u8 *buf; | ||
440 | u8 response_ok; | ||
441 | int err; | ||
442 | |||
443 | buf = kmalloc(12, GFP_KERNEL); | ||
444 | if (!buf) | ||
445 | return -ENOMEM; | ||
446 | |||
447 | if (action == CTL_READ) { | ||
448 | buf[0] = 0x01; /* AV/C, STATUS */ | ||
449 | response_ok = 0x0c; /* STABLE */ | ||
450 | } else { | ||
451 | buf[0] = 0x00; /* AV/C, CONTROL */ | ||
452 | response_ok = 0x09; /* ACCEPTED */ | ||
453 | } | ||
454 | buf[1] = 0x08; /* audio unit 0 */ | ||
455 | buf[2] = 0xb8; /* FUNCTION BLOCK */ | ||
456 | buf[3] = 0x81; /* function block type: feature */ | ||
457 | buf[4] = fwspk->device_info->volume_fb_id; /* function block ID */ | ||
458 | buf[5] = attribute; /* control attribute */ | ||
459 | buf[6] = 0x02; /* selector length */ | ||
460 | buf[7] = channel; /* audio channel number */ | ||
461 | buf[8] = 0x02; /* control selector: volume */ | ||
462 | buf[9] = 0x02; /* control data length */ | ||
463 | if (action == CTL_READ) { | ||
464 | buf[10] = 0xff; | ||
465 | buf[11] = 0xff; | ||
466 | } else { | ||
467 | buf[10] = *value >> 8; | ||
468 | buf[11] = *value; | ||
469 | } | ||
470 | |||
471 | err = fcp_avc_transaction(fwspk->unit, buf, 12, buf, 12, 0x3fe); | ||
472 | if (err < 0) | ||
473 | goto error; | ||
474 | if (err < 12) { | ||
475 | dev_err(&fwspk->unit->device, "short FCP response\n"); | ||
476 | err = -EIO; | ||
477 | goto error; | ||
478 | } | ||
479 | if (buf[0] != response_ok) { | ||
480 | dev_err(&fwspk->unit->device, "volume command failed\n"); | ||
481 | err = -EIO; | ||
482 | goto error; | ||
483 | } | ||
484 | if (action == CTL_READ) | ||
485 | *value = (buf[10] << 8) | buf[11]; | ||
486 | |||
487 | err = 0; | ||
488 | |||
489 | error: | ||
490 | kfree(buf); | ||
491 | |||
492 | return err; | ||
493 | } | ||
494 | |||
495 | static int fwspk_mute_get(struct snd_kcontrol *control, | ||
496 | struct snd_ctl_elem_value *value) | ||
497 | { | ||
498 | struct fwspk *fwspk = control->private_data; | ||
499 | |||
500 | value->value.integer.value[0] = !fwspk->mute; | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | static int fwspk_mute_put(struct snd_kcontrol *control, | ||
506 | struct snd_ctl_elem_value *value) | ||
507 | { | ||
508 | struct fwspk *fwspk = control->private_data; | ||
509 | bool mute; | ||
510 | int err; | ||
511 | |||
512 | mute = !value->value.integer.value[0]; | ||
513 | |||
514 | if (mute == fwspk->mute) | ||
515 | return 0; | ||
516 | |||
517 | err = fwspk_mute_command(fwspk, &mute, CTL_WRITE); | ||
518 | if (err < 0) | ||
519 | return err; | ||
520 | fwspk->mute = mute; | ||
521 | |||
522 | return 1; | ||
523 | } | ||
524 | |||
525 | static int fwspk_volume_info(struct snd_kcontrol *control, | ||
526 | struct snd_ctl_elem_info *info) | ||
527 | { | ||
528 | struct fwspk *fwspk = control->private_data; | ||
529 | |||
530 | info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
531 | info->count = fwspk->device_info->mixer_channels; | ||
532 | info->value.integer.min = fwspk->volume_min; | ||
533 | info->value.integer.max = fwspk->volume_max; | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static const u8 channel_map[6] = { 0, 1, 4, 5, 2, 3 }; | ||
539 | |||
540 | static int fwspk_volume_get(struct snd_kcontrol *control, | ||
541 | struct snd_ctl_elem_value *value) | ||
542 | { | ||
543 | struct fwspk *fwspk = control->private_data; | ||
544 | unsigned int i; | ||
545 | |||
546 | for (i = 0; i < fwspk->device_info->mixer_channels; ++i) | ||
547 | value->value.integer.value[channel_map[i]] = fwspk->volume[i]; | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | static int fwspk_volume_put(struct snd_kcontrol *control, | ||
553 | struct snd_ctl_elem_value *value) | ||
554 | { | ||
555 | struct fwspk *fwspk = control->private_data; | ||
556 | unsigned int i, changed_channels; | ||
557 | bool equal_values = true; | ||
558 | s16 volume; | ||
559 | int err; | ||
560 | |||
561 | for (i = 0; i < fwspk->device_info->mixer_channels; ++i) { | ||
562 | if (value->value.integer.value[i] < fwspk->volume_min || | ||
563 | value->value.integer.value[i] > fwspk->volume_max) | ||
564 | return -EINVAL; | ||
565 | if (value->value.integer.value[i] != | ||
566 | value->value.integer.value[0]) | ||
567 | equal_values = false; | ||
568 | } | ||
569 | |||
570 | changed_channels = 0; | ||
571 | for (i = 0; i < fwspk->device_info->mixer_channels; ++i) | ||
572 | if (value->value.integer.value[channel_map[i]] != | ||
573 | fwspk->volume[i]) | ||
574 | changed_channels |= 1 << (i + 1); | ||
575 | |||
576 | if (equal_values && changed_channels != 0) | ||
577 | changed_channels = 1 << 0; | ||
578 | |||
579 | for (i = 0; i <= fwspk->device_info->mixer_channels; ++i) { | ||
580 | volume = value->value.integer.value[channel_map[i ? i - 1 : 0]]; | ||
581 | if (changed_channels & (1 << i)) { | ||
582 | err = fwspk_volume_command(fwspk, &volume, i, | ||
583 | CTL_CURRENT, CTL_WRITE); | ||
584 | if (err < 0) | ||
585 | return err; | ||
586 | } | ||
587 | if (i > 0) | ||
588 | fwspk->volume[i - 1] = volume; | ||
589 | } | ||
590 | |||
591 | return changed_channels != 0; | ||
592 | } | ||
593 | |||
594 | static int fwspk_create_mixer(struct fwspk *fwspk) | ||
595 | { | ||
596 | static const struct snd_kcontrol_new controls[] = { | ||
597 | { | ||
598 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
599 | .name = "PCM Playback Switch", | ||
600 | .info = snd_ctl_boolean_mono_info, | ||
601 | .get = fwspk_mute_get, | ||
602 | .put = fwspk_mute_put, | ||
603 | }, | ||
604 | { | ||
605 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
606 | .name = "PCM Playback Volume", | ||
607 | .info = fwspk_volume_info, | ||
608 | .get = fwspk_volume_get, | ||
609 | .put = fwspk_volume_put, | ||
610 | }, | ||
611 | }; | ||
612 | unsigned int i, first_ch; | ||
613 | int err; | ||
614 | |||
615 | err = fwspk_volume_command(fwspk, &fwspk->volume_min, | ||
616 | 0, CTL_MIN, CTL_READ); | ||
617 | if (err < 0) | ||
618 | return err; | ||
619 | err = fwspk_volume_command(fwspk, &fwspk->volume_max, | ||
620 | 0, CTL_MAX, CTL_READ); | ||
621 | if (err < 0) | ||
622 | return err; | ||
623 | |||
624 | err = fwspk_mute_command(fwspk, &fwspk->mute, CTL_READ); | ||
625 | if (err < 0) | ||
626 | return err; | ||
627 | |||
628 | first_ch = fwspk->device_info->mixer_channels == 1 ? 0 : 1; | ||
629 | for (i = 0; i < fwspk->device_info->mixer_channels; ++i) { | ||
630 | err = fwspk_volume_command(fwspk, &fwspk->volume[i], | ||
631 | first_ch + i, CTL_CURRENT, CTL_READ); | ||
632 | if (err < 0) | ||
633 | return err; | ||
634 | } | ||
635 | |||
636 | for (i = 0; i < ARRAY_SIZE(controls); ++i) { | ||
637 | err = snd_ctl_add(fwspk->card, | ||
638 | snd_ctl_new1(&controls[i], fwspk)); | ||
639 | if (err < 0) | ||
640 | return err; | ||
641 | } | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static u32 fwspk_read_firmware_version(struct fw_unit *unit) | ||
647 | { | ||
648 | __be32 data; | ||
649 | int err; | ||
650 | |||
651 | err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, | ||
652 | OXFORD_FIRMWARE_ID_ADDRESS, &data, 4); | ||
653 | return err >= 0 ? be32_to_cpu(data) : 0; | ||
654 | } | ||
655 | |||
656 | static void fwspk_card_free(struct snd_card *card) | ||
657 | { | ||
658 | struct fwspk *fwspk = card->private_data; | ||
659 | struct fw_device *dev = fw_parent_device(fwspk->unit); | ||
660 | |||
661 | amdtp_out_stream_destroy(&fwspk->stream); | ||
662 | cmp_connection_destroy(&fwspk->connection); | ||
663 | fw_unit_put(fwspk->unit); | ||
664 | fw_device_put(dev); | ||
665 | mutex_destroy(&fwspk->mutex); | ||
666 | } | ||
667 | |||
668 | static const struct device_info *__devinit fwspk_detect(struct fw_device *dev) | ||
669 | { | ||
670 | static const struct device_info griffin_firewave = { | ||
671 | .driver_name = "FireWave", | ||
672 | .short_name = "FireWave", | ||
673 | .long_name = "Griffin FireWave Surround", | ||
674 | .pcm_constraints = firewave_constraints, | ||
675 | .mixer_channels = 6, | ||
676 | .mute_fb_id = 0x01, | ||
677 | .volume_fb_id = 0x02, | ||
678 | }; | ||
679 | static const struct device_info lacie_speakers = { | ||
680 | .driver_name = "FWSpeakers", | ||
681 | .short_name = "FireWire Speakers", | ||
682 | .long_name = "LaCie FireWire Speakers", | ||
683 | .pcm_constraints = lacie_speakers_constraints, | ||
684 | .mixer_channels = 1, | ||
685 | .mute_fb_id = 0x01, | ||
686 | .volume_fb_id = 0x01, | ||
687 | }; | ||
688 | struct fw_csr_iterator i; | ||
689 | int key, value; | ||
690 | |||
691 | fw_csr_iterator_init(&i, dev->config_rom); | ||
692 | while (fw_csr_iterator_next(&i, &key, &value)) | ||
693 | if (key == CSR_VENDOR) | ||
694 | switch (value) { | ||
695 | case VENDOR_GRIFFIN: | ||
696 | return &griffin_firewave; | ||
697 | case VENDOR_LACIE: | ||
698 | return &lacie_speakers; | ||
699 | } | ||
700 | |||
701 | return NULL; | ||
702 | } | ||
703 | |||
704 | static int __devinit fwspk_probe(struct device *unit_dev) | ||
705 | { | ||
706 | struct fw_unit *unit = fw_unit(unit_dev); | ||
707 | struct fw_device *fw_dev = fw_parent_device(unit); | ||
708 | struct snd_card *card; | ||
709 | struct fwspk *fwspk; | ||
710 | u32 firmware; | ||
711 | int err; | ||
712 | |||
713 | err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*fwspk), &card); | ||
714 | if (err < 0) | ||
715 | return err; | ||
716 | snd_card_set_dev(card, unit_dev); | ||
717 | |||
718 | fwspk = card->private_data; | ||
719 | fwspk->card = card; | ||
720 | mutex_init(&fwspk->mutex); | ||
721 | fw_device_get(fw_dev); | ||
722 | fwspk->unit = fw_unit_get(unit); | ||
723 | fwspk->device_info = fwspk_detect(fw_dev); | ||
724 | if (!fwspk->device_info) { | ||
725 | err = -ENODEV; | ||
726 | goto err_unit; | ||
727 | } | ||
728 | |||
729 | err = cmp_connection_init(&fwspk->connection, unit, 0); | ||
730 | if (err < 0) | ||
731 | goto err_unit; | ||
732 | |||
733 | err = amdtp_out_stream_init(&fwspk->stream, unit, CIP_NONBLOCKING); | ||
734 | if (err < 0) | ||
735 | goto err_connection; | ||
736 | |||
737 | card->private_free = fwspk_card_free; | ||
738 | |||
739 | strcpy(card->driver, fwspk->device_info->driver_name); | ||
740 | strcpy(card->shortname, fwspk->device_info->short_name); | ||
741 | firmware = fwspk_read_firmware_version(unit); | ||
742 | snprintf(card->longname, sizeof(card->longname), | ||
743 | "%s (OXFW%x %04x), GUID %08x%08x at %s, S%d", | ||
744 | fwspk->device_info->long_name, | ||
745 | firmware >> 20, firmware & 0xffff, | ||
746 | fw_dev->config_rom[3], fw_dev->config_rom[4], | ||
747 | dev_name(&unit->device), 100 << fw_dev->max_speed); | ||
748 | strcpy(card->mixername, "OXFW970"); | ||
749 | |||
750 | err = fwspk_create_pcm(fwspk); | ||
751 | if (err < 0) | ||
752 | goto error; | ||
753 | |||
754 | err = fwspk_create_mixer(fwspk); | ||
755 | if (err < 0) | ||
756 | goto error; | ||
757 | |||
758 | err = snd_card_register(card); | ||
759 | if (err < 0) | ||
760 | goto error; | ||
761 | |||
762 | dev_set_drvdata(unit_dev, fwspk); | ||
763 | |||
764 | return 0; | ||
765 | |||
766 | err_connection: | ||
767 | cmp_connection_destroy(&fwspk->connection); | ||
768 | err_unit: | ||
769 | fw_unit_put(fwspk->unit); | ||
770 | fw_device_put(fw_dev); | ||
771 | mutex_destroy(&fwspk->mutex); | ||
772 | error: | ||
773 | snd_card_free(card); | ||
774 | return err; | ||
775 | } | ||
776 | |||
777 | static int __devexit fwspk_remove(struct device *dev) | ||
778 | { | ||
779 | struct fwspk *fwspk = dev_get_drvdata(dev); | ||
780 | |||
781 | snd_card_disconnect(fwspk->card); | ||
782 | |||
783 | mutex_lock(&fwspk->mutex); | ||
784 | amdtp_out_stream_pcm_abort(&fwspk->stream); | ||
785 | fwspk_stop_stream(fwspk); | ||
786 | mutex_unlock(&fwspk->mutex); | ||
787 | |||
788 | snd_card_free_when_closed(fwspk->card); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static void fwspk_bus_reset(struct fw_unit *unit) | ||
794 | { | ||
795 | struct fwspk *fwspk = dev_get_drvdata(&unit->device); | ||
796 | |||
797 | fcp_bus_reset(fwspk->unit); | ||
798 | |||
799 | if (cmp_connection_update(&fwspk->connection) < 0) { | ||
800 | mutex_lock(&fwspk->mutex); | ||
801 | amdtp_out_stream_pcm_abort(&fwspk->stream); | ||
802 | fwspk_stop_stream(fwspk); | ||
803 | mutex_unlock(&fwspk->mutex); | ||
804 | return; | ||
805 | } | ||
806 | |||
807 | amdtp_out_stream_update(&fwspk->stream); | ||
808 | } | ||
809 | |||
810 | static const struct ieee1394_device_id fwspk_id_table[] = { | ||
811 | { | ||
812 | .match_flags = IEEE1394_MATCH_VENDOR_ID | | ||
813 | IEEE1394_MATCH_MODEL_ID | | ||
814 | IEEE1394_MATCH_SPECIFIER_ID | | ||
815 | IEEE1394_MATCH_VERSION, | ||
816 | .vendor_id = VENDOR_GRIFFIN, | ||
817 | .model_id = 0x00f970, | ||
818 | .specifier_id = SPECIFIER_1394TA, | ||
819 | .version = VERSION_AVC, | ||
820 | }, | ||
821 | { | ||
822 | .match_flags = IEEE1394_MATCH_VENDOR_ID | | ||
823 | IEEE1394_MATCH_MODEL_ID | | ||
824 | IEEE1394_MATCH_SPECIFIER_ID | | ||
825 | IEEE1394_MATCH_VERSION, | ||
826 | .vendor_id = VENDOR_LACIE, | ||
827 | .model_id = 0x00f970, | ||
828 | .specifier_id = SPECIFIER_1394TA, | ||
829 | .version = VERSION_AVC, | ||
830 | }, | ||
831 | { } | ||
832 | }; | ||
833 | MODULE_DEVICE_TABLE(ieee1394, fwspk_id_table); | ||
834 | |||
835 | static struct fw_driver fwspk_driver = { | ||
836 | .driver = { | ||
837 | .owner = THIS_MODULE, | ||
838 | .name = KBUILD_MODNAME, | ||
839 | .bus = &fw_bus_type, | ||
840 | .probe = fwspk_probe, | ||
841 | .remove = __devexit_p(fwspk_remove), | ||
842 | }, | ||
843 | .update = fwspk_bus_reset, | ||
844 | .id_table = fwspk_id_table, | ||
845 | }; | ||
846 | |||
847 | static int __init alsa_fwspk_init(void) | ||
848 | { | ||
849 | return driver_register(&fwspk_driver.driver); | ||
850 | } | ||
851 | |||
852 | static void __exit alsa_fwspk_exit(void) | ||
853 | { | ||
854 | driver_unregister(&fwspk_driver.driver); | ||
855 | } | ||
856 | |||
857 | module_init(alsa_fwspk_init); | ||
858 | module_exit(alsa_fwspk_exit); | ||
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index fcb14a099822..7c7793a0eb25 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c | |||
@@ -526,31 +526,21 @@ bad: | |||
526 | } | 526 | } |
527 | 527 | ||
528 | 528 | ||
529 | /* These device names follow the official Linux device list, | ||
530 | * Documentation/devices.txt. Let us know if there are other | ||
531 | * common names we should support for compatibility. | ||
532 | * Only those devices not created by the generic code in sound_core.c are | ||
533 | * registered here. | ||
534 | */ | ||
535 | static const struct { | ||
536 | unsigned short minor; | ||
537 | char *name; | ||
538 | umode_t mode; | ||
539 | int *num; | ||
540 | } dev_list[] = { /* list of minor devices */ | ||
541 | /* seems to be some confusion here -- this device is not in the device list */ | ||
542 | {SND_DEV_DSP16, "dspW", S_IWUGO | S_IRUSR | S_IRGRP, | ||
543 | &num_audiodevs}, | ||
544 | {SND_DEV_AUDIO, "audio", S_IWUGO | S_IRUSR | S_IRGRP, | ||
545 | &num_audiodevs}, | ||
546 | }; | ||
547 | |||
548 | static int dmabuf; | 529 | static int dmabuf; |
549 | static int dmabug; | 530 | static int dmabug; |
550 | 531 | ||
551 | module_param(dmabuf, int, 0444); | 532 | module_param(dmabuf, int, 0444); |
552 | module_param(dmabug, int, 0444); | 533 | module_param(dmabug, int, 0444); |
553 | 534 | ||
535 | /* additional minors for compatibility */ | ||
536 | struct oss_minor_dev { | ||
537 | unsigned short minor; | ||
538 | unsigned int enabled; | ||
539 | } dev_list[] = { | ||
540 | { SND_DEV_DSP16 }, | ||
541 | { SND_DEV_AUDIO }, | ||
542 | }; | ||
543 | |||
554 | static int __init oss_init(void) | 544 | static int __init oss_init(void) |
555 | { | 545 | { |
556 | int err; | 546 | int err; |
@@ -571,18 +561,12 @@ static int __init oss_init(void) | |||
571 | sound_dmap_flag = (dmabuf > 0 ? 1 : 0); | 561 | sound_dmap_flag = (dmabuf > 0 ? 1 : 0); |
572 | 562 | ||
573 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { | 563 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { |
574 | device_create(sound_class, NULL, | 564 | j = 0; |
575 | MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL, | 565 | do { |
576 | "%s", dev_list[i].name); | 566 | unsigned short minor = dev_list[i].minor + j * 0x10; |
577 | 567 | if (!register_sound_special(&oss_sound_fops, minor)) | |
578 | if (!dev_list[i].num) | 568 | dev_list[i].enabled = (1 << j); |
579 | continue; | 569 | } while (++j < num_audiodevs); |
580 | |||
581 | for (j = 1; j < *dev_list[i].num; j++) | ||
582 | device_create(sound_class, NULL, | ||
583 | MKDEV(SOUND_MAJOR, | ||
584 | dev_list[i].minor + (j*0x10)), | ||
585 | NULL, "%s%d", dev_list[i].name, j); | ||
586 | } | 570 | } |
587 | 571 | ||
588 | if (sound_nblocks >= MAX_MEM_BLOCKS - 1) | 572 | if (sound_nblocks >= MAX_MEM_BLOCKS - 1) |
@@ -596,11 +580,11 @@ static void __exit oss_cleanup(void) | |||
596 | int i, j; | 580 | int i, j; |
597 | 581 | ||
598 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { | 582 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { |
599 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); | 583 | j = 0; |
600 | if (!dev_list[i].num) | 584 | do { |
601 | continue; | 585 | if (dev_list[i].enabled & (1 << j)) |
602 | for (j = 1; j < *dev_list[i].num; j++) | 586 | unregister_sound_special(dev_list[i].minor); |
603 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); | 587 | } while (++j < num_audiodevs); |
604 | } | 588 | } |
605 | 589 | ||
606 | unregister_sound_special(1); | 590 | unregister_sound_special(1); |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 9823d59d7ad7..389cd7931668 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -152,10 +152,16 @@ config SND_AZT3328 | |||
152 | select SND_MPU401_UART | 152 | select SND_MPU401_UART |
153 | select SND_PCM | 153 | select SND_PCM |
154 | select SND_RAWMIDI | 154 | select SND_RAWMIDI |
155 | select SND_AC97_CODEC | ||
155 | help | 156 | help |
156 | Say Y here to include support for Aztech AZF3328 (PCI168) | 157 | Say Y here to include support for Aztech AZF3328 (PCI168) |
157 | soundcards. | 158 | soundcards. |
158 | 159 | ||
160 | Supported features: AC97-"conformant" mixer, MPU401/OPL3, analog I/O | ||
161 | (16bit/8bit, many sample rates [<= 66.2kHz], NO hardware mixing), | ||
162 | Digital Enhanced Game Port, 1.024MHz multimedia sequencer timer, | ||
163 | ext. codec (I2S port), onboard amp (4W/4Ohms/ch), suspend/resume. | ||
164 | |||
159 | To compile this driver as a module, choose M here: the module | 165 | To compile this driver as a module, choose M here: the module |
160 | will be called snd-azt3328. | 166 | will be called snd-azt3328. |
161 | 167 | ||
@@ -572,13 +578,13 @@ comment "Don't forget to add built-in firmwares for HDSP driver" | |||
572 | depends on SND_HDSP=y | 578 | depends on SND_HDSP=y |
573 | 579 | ||
574 | config SND_HDSPM | 580 | config SND_HDSPM |
575 | tristate "RME Hammerfall DSP MADI" | 581 | tristate "RME Hammerfall DSP MADI/RayDAT/AIO" |
576 | select SND_HWDEP | 582 | select SND_HWDEP |
577 | select SND_RAWMIDI | 583 | select SND_RAWMIDI |
578 | select SND_PCM | 584 | select SND_PCM |
579 | help | 585 | help |
580 | Say Y here to include support for RME Hammerfall DSP MADI | 586 | Say Y here to include support for RME Hammerfall DSP MADI, |
581 | soundcards. | 587 | RayDAT and AIO soundcards. |
582 | 588 | ||
583 | To compile this driver as a module, choose M here: the module | 589 | To compile this driver as a module, choose M here: the module |
584 | will be called snd-hdspm. | 590 | will be called snd-hdspm. |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index cb62d178b3e0..7f4d619f4ddb 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -71,6 +71,12 @@ static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = { | |||
71 | { 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL }, | 71 | { 0x414b4d00, 0xffffff00, "Asahi Kasei", NULL, NULL }, |
72 | { 0x414c4300, 0xffffff00, "Realtek", NULL, NULL }, | 72 | { 0x414c4300, 0xffffff00, "Realtek", NULL, NULL }, |
73 | { 0x414c4700, 0xffffff00, "Realtek", NULL, NULL }, | 73 | { 0x414c4700, 0xffffff00, "Realtek", NULL, NULL }, |
74 | /* | ||
75 | * This is an _inofficial_ Aztech Labs entry | ||
76 | * (value might differ from unknown official Aztech ID), | ||
77 | * currently used by the AC97 emulation of the almost-AC97 PCI168 card. | ||
78 | */ | ||
79 | { 0x415a5400, 0xffffff00, "Aztech Labs (emulated)", NULL, NULL }, | ||
74 | { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL, NULL }, | 80 | { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL, NULL }, |
75 | { 0x43525900, 0xffffff00, "Cirrus Logic", NULL, NULL }, | 81 | { 0x43525900, 0xffffff00, "Cirrus Logic", NULL, NULL }, |
76 | { 0x43585400, 0xffffff00, "Conexant", NULL, NULL }, | 82 | { 0x43585400, 0xffffff00, "Conexant", NULL, NULL }, |
@@ -127,6 +133,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { | |||
127 | { 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */ | 133 | { 0x414c4781, 0xffffffff, "ALC658D", NULL, NULL }, /* already patched */ |
128 | { 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, | 134 | { 0x414c4780, 0xfffffff0, "ALC658", patch_alc655, NULL }, |
129 | { 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL }, | 135 | { 0x414c4790, 0xfffffff0, "ALC850", patch_alc850, NULL }, |
136 | { 0x415a5401, 0xffffffff, "AZF3328", patch_aztech_azf3328, NULL }, | ||
130 | { 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL }, | 137 | { 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL }, |
131 | { 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL }, | 138 | { 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL }, |
132 | { 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL }, | 139 | { 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL }, |
@@ -590,9 +597,9 @@ static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, | |||
590 | snd_ac97_page_restore(ac97, page_save); | 597 | snd_ac97_page_restore(ac97, page_save); |
591 | #ifdef CONFIG_SND_AC97_POWER_SAVE | 598 | #ifdef CONFIG_SND_AC97_POWER_SAVE |
592 | /* check analog mixer power-down */ | 599 | /* check analog mixer power-down */ |
593 | if ((val_mask & 0x8000) && | 600 | if ((val_mask & AC97_PD_EAPD) && |
594 | (kcontrol->private_value & (1<<30))) { | 601 | (kcontrol->private_value & (1<<30))) { |
595 | if (val & 0x8000) | 602 | if (val & AC97_PD_EAPD) |
596 | ac97->power_up &= ~(1 << (reg>>1)); | 603 | ac97->power_up &= ~(1 << (reg>>1)); |
597 | else | 604 | else |
598 | ac97->power_up |= 1 << (reg>>1); | 605 | ac97->power_up |= 1 << (reg>>1); |
@@ -1035,20 +1042,20 @@ static int snd_ac97_dev_free(struct snd_device *device) | |||
1035 | 1042 | ||
1036 | static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg) | 1043 | static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg) |
1037 | { | 1044 | { |
1038 | unsigned short val, mask = 0x8000; | 1045 | unsigned short val, mask = AC97_MUTE_MASK_MONO; |
1039 | 1046 | ||
1040 | if (! snd_ac97_valid_reg(ac97, reg)) | 1047 | if (! snd_ac97_valid_reg(ac97, reg)) |
1041 | return 0; | 1048 | return 0; |
1042 | 1049 | ||
1043 | switch (reg) { | 1050 | switch (reg) { |
1044 | case AC97_MASTER_TONE: | 1051 | case AC97_MASTER_TONE: |
1045 | return ac97->caps & 0x04 ? 1 : 0; | 1052 | return ac97->caps & AC97_BC_BASS_TREBLE ? 1 : 0; |
1046 | case AC97_HEADPHONE: | 1053 | case AC97_HEADPHONE: |
1047 | return ac97->caps & 0x10 ? 1 : 0; | 1054 | return ac97->caps & AC97_BC_HEADPHONE ? 1 : 0; |
1048 | case AC97_REC_GAIN_MIC: | 1055 | case AC97_REC_GAIN_MIC: |
1049 | return ac97->caps & 0x01 ? 1 : 0; | 1056 | return ac97->caps & AC97_BC_DEDICATED_MIC ? 1 : 0; |
1050 | case AC97_3D_CONTROL: | 1057 | case AC97_3D_CONTROL: |
1051 | if (ac97->caps & 0x7c00) { | 1058 | if (ac97->caps & AC97_BC_3D_TECH_ID_MASK) { |
1052 | val = snd_ac97_read(ac97, reg); | 1059 | val = snd_ac97_read(ac97, reg); |
1053 | /* if nonzero - fixed and we can't set it */ | 1060 | /* if nonzero - fixed and we can't set it */ |
1054 | return val == 0; | 1061 | return val == 0; |
@@ -1104,7 +1111,10 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha | |||
1104 | *lo_max = *hi_max = 0; | 1111 | *lo_max = *hi_max = 0; |
1105 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { | 1112 | for (i = 0 ; i < ARRAY_SIZE(cbit); i++) { |
1106 | unsigned short val; | 1113 | unsigned short val; |
1107 | snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8)); | 1114 | snd_ac97_write( |
1115 | ac97, reg, | ||
1116 | AC97_MUTE_MASK_STEREO | cbit[i] | (cbit[i] << 8) | ||
1117 | ); | ||
1108 | /* Do the read twice due to buffers on some ac97 codecs. | 1118 | /* Do the read twice due to buffers on some ac97 codecs. |
1109 | * e.g. The STAC9704 returns exactly what you wrote to the register | 1119 | * e.g. The STAC9704 returns exactly what you wrote to the register |
1110 | * if you read it immediately. This causes the detect routine to fail. | 1120 | * if you read it immediately. This causes the detect routine to fail. |
@@ -1139,14 +1149,14 @@ static void snd_ac97_change_volume_params2(struct snd_ac97 * ac97, int reg, int | |||
1139 | unsigned short val, val1; | 1149 | unsigned short val, val1; |
1140 | 1150 | ||
1141 | *max = 63; | 1151 | *max = 63; |
1142 | val = 0x8080 | (0x20 << shift); | 1152 | val = AC97_MUTE_MASK_STEREO | (0x20 << shift); |
1143 | snd_ac97_write(ac97, reg, val); | 1153 | snd_ac97_write(ac97, reg, val); |
1144 | val1 = snd_ac97_read(ac97, reg); | 1154 | val1 = snd_ac97_read(ac97, reg); |
1145 | if (val != val1) { | 1155 | if (val != val1) { |
1146 | *max = 31; | 1156 | *max = 31; |
1147 | } | 1157 | } |
1148 | /* reset volume to zero */ | 1158 | /* reset volume to zero */ |
1149 | snd_ac97_write_cache(ac97, reg, 0x8080); | 1159 | snd_ac97_write_cache(ac97, reg, AC97_MUTE_MASK_STEREO); |
1150 | } | 1160 | } |
1151 | 1161 | ||
1152 | static inline int printable(unsigned int x) | 1162 | static inline int printable(unsigned int x) |
@@ -1183,16 +1193,16 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, | |||
1183 | if (! snd_ac97_valid_reg(ac97, reg)) | 1193 | if (! snd_ac97_valid_reg(ac97, reg)) |
1184 | return 0; | 1194 | return 0; |
1185 | 1195 | ||
1186 | mute_mask = 0x8000; | 1196 | mute_mask = AC97_MUTE_MASK_MONO; |
1187 | val = snd_ac97_read(ac97, reg); | 1197 | val = snd_ac97_read(ac97, reg); |
1188 | if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) { | 1198 | if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) { |
1189 | /* check whether both mute bits work */ | 1199 | /* check whether both mute bits work */ |
1190 | val1 = val | 0x8080; | 1200 | val1 = val | AC97_MUTE_MASK_STEREO; |
1191 | snd_ac97_write(ac97, reg, val1); | 1201 | snd_ac97_write(ac97, reg, val1); |
1192 | if (val1 == snd_ac97_read(ac97, reg)) | 1202 | if (val1 == snd_ac97_read(ac97, reg)) |
1193 | mute_mask = 0x8080; | 1203 | mute_mask = AC97_MUTE_MASK_STEREO; |
1194 | } | 1204 | } |
1195 | if (mute_mask == 0x8080) { | 1205 | if (mute_mask == AC97_MUTE_MASK_STEREO) { |
1196 | struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1); | 1206 | struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1); |
1197 | if (check_amix) | 1207 | if (check_amix) |
1198 | tmp.private_value |= (1 << 30); | 1208 | tmp.private_value |= (1 << 30); |
@@ -1268,9 +1278,11 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne | |||
1268 | err = snd_ctl_add(card, kctl); | 1278 | err = snd_ctl_add(card, kctl); |
1269 | if (err < 0) | 1279 | if (err < 0) |
1270 | return err; | 1280 | return err; |
1271 | snd_ac97_write_cache(ac97, reg, | 1281 | snd_ac97_write_cache( |
1272 | (snd_ac97_read(ac97, reg) & 0x8080) | | 1282 | ac97, reg, |
1273 | lo_max | (hi_max << 8)); | 1283 | (snd_ac97_read(ac97, reg) & AC97_MUTE_MASK_STEREO) |
1284 | | lo_max | (hi_max << 8) | ||
1285 | ); | ||
1274 | return 0; | 1286 | return 0; |
1275 | } | 1287 | } |
1276 | 1288 | ||
@@ -1332,7 +1344,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1332 | return err; | 1344 | return err; |
1333 | } | 1345 | } |
1334 | 1346 | ||
1335 | ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080; | 1347 | ac97->regs[AC97_CENTER_LFE_MASTER] = AC97_MUTE_MASK_STEREO; |
1336 | 1348 | ||
1337 | /* build center controls */ | 1349 | /* build center controls */ |
1338 | if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) | 1350 | if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) |
@@ -1410,8 +1422,12 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1410 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) | 1422 | if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) |
1411 | return err; | 1423 | return err; |
1412 | set_tlv_db_scale(kctl, db_scale_4bit); | 1424 | set_tlv_db_scale(kctl, db_scale_4bit); |
1413 | snd_ac97_write_cache(ac97, AC97_PC_BEEP, | 1425 | snd_ac97_write_cache( |
1414 | snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e); | 1426 | ac97, |
1427 | AC97_PC_BEEP, | ||
1428 | (snd_ac97_read(ac97, AC97_PC_BEEP) | ||
1429 | | AC97_MUTE_MASK_MONO | 0x001e) | ||
1430 | ); | ||
1415 | } | 1431 | } |
1416 | 1432 | ||
1417 | /* build Phone controls */ | 1433 | /* build Phone controls */ |
@@ -1545,7 +1561,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1545 | } | 1561 | } |
1546 | 1562 | ||
1547 | /* build Simulated Stereo Enhancement control */ | 1563 | /* build Simulated Stereo Enhancement control */ |
1548 | if (ac97->caps & 0x0008) { | 1564 | if (ac97->caps & AC97_BC_SIM_STEREO) { |
1549 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0) | 1565 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0) |
1550 | return err; | 1566 | return err; |
1551 | } | 1567 | } |
@@ -1557,7 +1573,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) | |||
1557 | } | 1573 | } |
1558 | 1574 | ||
1559 | /* build Loudness control */ | 1575 | /* build Loudness control */ |
1560 | if (ac97->caps & 0x0020) { | 1576 | if (ac97->caps & AC97_BC_LOUDNESS) { |
1561 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0) | 1577 | if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0) |
1562 | return err; | 1578 | return err; |
1563 | } | 1579 | } |
@@ -2542,8 +2558,8 @@ void snd_ac97_resume(struct snd_ac97 *ac97) | |||
2542 | schedule_timeout_uninterruptible(1); | 2558 | schedule_timeout_uninterruptible(1); |
2543 | } while (time_after_eq(end_time, jiffies)); | 2559 | } while (time_after_eq(end_time, jiffies)); |
2544 | /* FIXME: extra delay */ | 2560 | /* FIXME: extra delay */ |
2545 | ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000); | 2561 | ac97->bus->ops->write(ac97, AC97_MASTER, AC97_MUTE_MASK_MONO); |
2546 | if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) | 2562 | if (snd_ac97_read(ac97, AC97_MASTER) != AC97_MUTE_MASK_MONO) |
2547 | msleep(250); | 2563 | msleep(250); |
2548 | } else { | 2564 | } else { |
2549 | end_time = jiffies + msecs_to_jiffies(100); | 2565 | end_time = jiffies + msecs_to_jiffies(100); |
@@ -2747,12 +2763,12 @@ static int master_mute_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem | |||
2747 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 2763 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
2748 | unsigned short mask; | 2764 | unsigned short mask; |
2749 | if (shift != rshift) | 2765 | if (shift != rshift) |
2750 | mask = 0x8080; | 2766 | mask = AC97_MUTE_MASK_STEREO; |
2751 | else | 2767 | else |
2752 | mask = 0x8000; | 2768 | mask = AC97_MUTE_MASK_MONO; |
2753 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, | 2769 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD, |
2754 | (ac97->regs[AC97_MASTER] & mask) == mask ? | 2770 | (ac97->regs[AC97_MASTER] & mask) == mask ? |
2755 | 0x8000 : 0); | 2771 | AC97_PD_EAPD : 0); |
2756 | } | 2772 | } |
2757 | return err; | 2773 | return err; |
2758 | } | 2774 | } |
@@ -2765,7 +2781,10 @@ static int tune_mute_led(struct snd_ac97 *ac97) | |||
2765 | return -ENOENT; | 2781 | return -ENOENT; |
2766 | msw->put = master_mute_sw_put; | 2782 | msw->put = master_mute_sw_put; |
2767 | snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); | 2783 | snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); |
2768 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */ | 2784 | snd_ac97_update_bits( |
2785 | ac97, AC97_POWERDOWN, | ||
2786 | AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */ | ||
2787 | ); | ||
2769 | ac97->scaps |= AC97_SCAP_EAPD_LED; | 2788 | ac97->scaps |= AC97_SCAP_EAPD_LED; |
2770 | return 0; | 2789 | return 0; |
2771 | } | 2790 | } |
@@ -2780,12 +2799,12 @@ static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol, | |||
2780 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 2799 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
2781 | unsigned short mask; | 2800 | unsigned short mask; |
2782 | if (shift != rshift) | 2801 | if (shift != rshift) |
2783 | mask = 0x8080; | 2802 | mask = AC97_MUTE_MASK_STEREO; |
2784 | else | 2803 | else |
2785 | mask = 0x8000; | 2804 | mask = AC97_MUTE_MASK_MONO; |
2786 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, | 2805 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD, |
2787 | (ac97->regs[AC97_MASTER] & mask) == mask ? | 2806 | (ac97->regs[AC97_MASTER] & mask) == mask ? |
2788 | 0x8000 : 0); | 2807 | AC97_PD_EAPD : 0); |
2789 | } | 2808 | } |
2790 | return err; | 2809 | return err; |
2791 | } | 2810 | } |
@@ -2801,7 +2820,10 @@ static int tune_hp_mute_led(struct snd_ac97 *ac97) | |||
2801 | snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); | 2820 | snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); |
2802 | snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch"); | 2821 | snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch"); |
2803 | snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume"); | 2822 | snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume"); |
2804 | snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */ | 2823 | snd_ac97_update_bits( |
2824 | ac97, AC97_POWERDOWN, | ||
2825 | AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */ | ||
2826 | ); | ||
2805 | return 0; | 2827 | return 0; |
2806 | } | 2828 | } |
2807 | 2829 | ||
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index bf47574ca1f0..200c9a1d48b7 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -27,6 +27,15 @@ | |||
27 | #include "ac97_patch.h" | 27 | #include "ac97_patch.h" |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Forward declarations | ||
31 | */ | ||
32 | |||
33 | static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97, | ||
34 | const char *name); | ||
35 | static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name, | ||
36 | const unsigned int *tlv, const char **slaves); | ||
37 | |||
38 | /* | ||
30 | * Chip specific initialization | 39 | * Chip specific initialization |
31 | */ | 40 | */ |
32 | 41 | ||
@@ -2940,6 +2949,49 @@ static int patch_alc850(struct snd_ac97 *ac97) | |||
2940 | return 0; | 2949 | return 0; |
2941 | } | 2950 | } |
2942 | 2951 | ||
2952 | static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97) | ||
2953 | { | ||
2954 | struct snd_kcontrol *kctl_3d_center = | ||
2955 | snd_ac97_find_mixer_ctl(ac97, "3D Control - Center"); | ||
2956 | struct snd_kcontrol *kctl_3d_depth = | ||
2957 | snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth"); | ||
2958 | |||
2959 | /* | ||
2960 | * 3D register is different from AC97 standard layout | ||
2961 | * (also do some renaming, to resemble Windows driver naming) | ||
2962 | */ | ||
2963 | if (kctl_3d_center) { | ||
2964 | kctl_3d_center->private_value = | ||
2965 | AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0); | ||
2966 | snd_ac97_rename_vol_ctl(ac97, | ||
2967 | "3D Control - Center", "3D Control - Width" | ||
2968 | ); | ||
2969 | } | ||
2970 | if (kctl_3d_depth) | ||
2971 | kctl_3d_depth->private_value = | ||
2972 | AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0); | ||
2973 | |||
2974 | /* Aztech Windows driver calls the | ||
2975 | equivalent control "Modem Playback", thus rename it: */ | ||
2976 | snd_ac97_rename_vol_ctl(ac97, | ||
2977 | "Master Mono Playback", "Modem Playback" | ||
2978 | ); | ||
2979 | snd_ac97_rename_vol_ctl(ac97, | ||
2980 | "Headphone Playback", "FM Synth Playback" | ||
2981 | ); | ||
2982 | |||
2983 | return 0; | ||
2984 | } | ||
2985 | |||
2986 | static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = { | ||
2987 | .build_specific = patch_aztech_azf3328_specific | ||
2988 | }; | ||
2989 | |||
2990 | static int patch_aztech_azf3328(struct snd_ac97 *ac97) | ||
2991 | { | ||
2992 | ac97->build_ops = &patch_aztech_azf3328_ops; | ||
2993 | return 0; | ||
2994 | } | ||
2943 | 2995 | ||
2944 | /* | 2996 | /* |
2945 | * C-Media CM97xx codecs | 2997 | * C-Media CM97xx codecs |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index c80b0b863c54..0ac1f98d91a1 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
@@ -21,6 +21,7 @@ | |||
21 | * would appreciate it if you grant us the right to use those modifications | 21 | * would appreciate it if you grant us the right to use those modifications |
22 | * for any purpose including commercial applications. | 22 | * for any purpose including commercial applications. |
23 | */ | 23 | */ |
24 | |||
24 | /* >0: print Hw params, timer vars. >1: print stream write/copy sizes */ | 25 | /* >0: print Hw params, timer vars. >1: print stream write/copy sizes */ |
25 | #define REALLY_VERBOSE_LOGGING 0 | 26 | #define REALLY_VERBOSE_LOGGING 0 |
26 | 27 | ||
@@ -36,16 +37,12 @@ | |||
36 | #define VPRINTK2(...) | 37 | #define VPRINTK2(...) |
37 | #endif | 38 | #endif |
38 | 39 | ||
39 | #ifndef ASI_STYLE_NAMES | ||
40 | /* not sure how ALSA style name should look */ | ||
41 | #define ASI_STYLE_NAMES 1 | ||
42 | #endif | ||
43 | |||
44 | #include "hpi_internal.h" | 40 | #include "hpi_internal.h" |
45 | #include "hpimsginit.h" | 41 | #include "hpimsginit.h" |
46 | #include "hpioctl.h" | 42 | #include "hpioctl.h" |
47 | 43 | ||
48 | #include <linux/pci.h> | 44 | #include <linux/pci.h> |
45 | #include <linux/version.h> | ||
49 | #include <linux/init.h> | 46 | #include <linux/init.h> |
50 | #include <linux/jiffies.h> | 47 | #include <linux/jiffies.h> |
51 | #include <linux/slab.h> | 48 | #include <linux/slab.h> |
@@ -85,11 +82,11 @@ MODULE_PARM_DESC(enable_hpi_hwdep, | |||
85 | 82 | ||
86 | /* identify driver */ | 83 | /* identify driver */ |
87 | #ifdef KERNEL_ALSA_BUILD | 84 | #ifdef KERNEL_ALSA_BUILD |
88 | static char *build_info = "built using headers from kernel source"; | 85 | static char *build_info = "Built using headers from kernel source"; |
89 | module_param(build_info, charp, S_IRUGO); | 86 | module_param(build_info, charp, S_IRUGO); |
90 | MODULE_PARM_DESC(build_info, "built using headers from kernel source"); | 87 | MODULE_PARM_DESC(build_info, "built using headers from kernel source"); |
91 | #else | 88 | #else |
92 | static char *build_info = "built within ALSA source"; | 89 | static char *build_info = "Built within ALSA source"; |
93 | module_param(build_info, charp, S_IRUGO); | 90 | module_param(build_info, charp, S_IRUGO); |
94 | MODULE_PARM_DESC(build_info, "built within ALSA source"); | 91 | MODULE_PARM_DESC(build_info, "built within ALSA source"); |
95 | #endif | 92 | #endif |
@@ -100,13 +97,14 @@ static const int mixer_dump; | |||
100 | #define DEFAULT_SAMPLERATE 44100 | 97 | #define DEFAULT_SAMPLERATE 44100 |
101 | static int adapter_fs = DEFAULT_SAMPLERATE; | 98 | static int adapter_fs = DEFAULT_SAMPLERATE; |
102 | 99 | ||
103 | static struct hpi_hsubsys *ss; /* handle to HPI audio subsystem */ | ||
104 | |||
105 | /* defaults */ | 100 | /* defaults */ |
106 | #define PERIODS_MIN 2 | 101 | #define PERIODS_MIN 2 |
107 | #define PERIOD_BYTES_MIN 2304 | 102 | #define PERIOD_BYTES_MIN 2048 |
108 | #define BUFFER_BYTES_MAX (512 * 1024) | 103 | #define BUFFER_BYTES_MAX (512 * 1024) |
109 | 104 | ||
105 | /* convert stream to character */ | ||
106 | #define SCHR(s) ((s == SNDRV_PCM_STREAM_PLAYBACK) ? 'P' : 'C') | ||
107 | |||
110 | /*#define TIMER_MILLISECONDS 20 | 108 | /*#define TIMER_MILLISECONDS 20 |
111 | #define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000) | 109 | #define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000) |
112 | */ | 110 | */ |
@@ -152,11 +150,12 @@ struct snd_card_asihpi_pcm { | |||
152 | struct timer_list timer; | 150 | struct timer_list timer; |
153 | unsigned int respawn_timer; | 151 | unsigned int respawn_timer; |
154 | unsigned int hpi_buffer_attached; | 152 | unsigned int hpi_buffer_attached; |
155 | unsigned int pcm_size; | 153 | unsigned int buffer_bytes; |
156 | unsigned int pcm_count; | 154 | unsigned int period_bytes; |
157 | unsigned int bytes_per_sec; | 155 | unsigned int bytes_per_sec; |
158 | unsigned int pcm_irq_pos; /* IRQ position */ | 156 | unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */ |
159 | unsigned int pcm_buf_pos; /* position in buffer */ | 157 | unsigned int pcm_buf_dma_ofs; /* DMA R/W offset in buffer */ |
158 | unsigned int pcm_buf_elapsed_dma_ofs; /* DMA R/W offset in buffer */ | ||
160 | struct snd_pcm_substream *substream; | 159 | struct snd_pcm_substream *substream; |
161 | u32 h_stream; | 160 | u32 h_stream; |
162 | struct hpi_format format; | 161 | struct hpi_format format; |
@@ -167,7 +166,6 @@ struct snd_card_asihpi_pcm { | |||
167 | /* Functions to allow driver to give a buffer to HPI for busmastering */ | 166 | /* Functions to allow driver to give a buffer to HPI for busmastering */ |
168 | 167 | ||
169 | static u16 hpi_stream_host_buffer_attach( | 168 | static u16 hpi_stream_host_buffer_attach( |
170 | struct hpi_hsubsys *hS, | ||
171 | u32 h_stream, /* handle to outstream. */ | 169 | u32 h_stream, /* handle to outstream. */ |
172 | u32 size_in_bytes, /* size in bytes of bus mastering buffer */ | 170 | u32 size_in_bytes, /* size in bytes of bus mastering buffer */ |
173 | u32 pci_address | 171 | u32 pci_address |
@@ -194,10 +192,7 @@ static u16 hpi_stream_host_buffer_attach( | |||
194 | return hr.error; | 192 | return hr.error; |
195 | } | 193 | } |
196 | 194 | ||
197 | static u16 hpi_stream_host_buffer_detach( | 195 | static u16 hpi_stream_host_buffer_detach(u32 h_stream) |
198 | struct hpi_hsubsys *hS, | ||
199 | u32 h_stream | ||
200 | ) | ||
201 | { | 196 | { |
202 | struct hpi_message hm; | 197 | struct hpi_message hm; |
203 | struct hpi_response hr; | 198 | struct hpi_response hr; |
@@ -218,24 +213,23 @@ static u16 hpi_stream_host_buffer_detach( | |||
218 | return hr.error; | 213 | return hr.error; |
219 | } | 214 | } |
220 | 215 | ||
221 | static inline u16 hpi_stream_start(struct hpi_hsubsys *hS, u32 h_stream) | 216 | static inline u16 hpi_stream_start(u32 h_stream) |
222 | { | 217 | { |
223 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 218 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
224 | return hpi_outstream_start(hS, h_stream); | 219 | return hpi_outstream_start(h_stream); |
225 | else | 220 | else |
226 | return hpi_instream_start(hS, h_stream); | 221 | return hpi_instream_start(h_stream); |
227 | } | 222 | } |
228 | 223 | ||
229 | static inline u16 hpi_stream_stop(struct hpi_hsubsys *hS, u32 h_stream) | 224 | static inline u16 hpi_stream_stop(u32 h_stream) |
230 | { | 225 | { |
231 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 226 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
232 | return hpi_outstream_stop(hS, h_stream); | 227 | return hpi_outstream_stop(h_stream); |
233 | else | 228 | else |
234 | return hpi_instream_stop(hS, h_stream); | 229 | return hpi_instream_stop(h_stream); |
235 | } | 230 | } |
236 | 231 | ||
237 | static inline u16 hpi_stream_get_info_ex( | 232 | static inline u16 hpi_stream_get_info_ex( |
238 | struct hpi_hsubsys *hS, | ||
239 | u32 h_stream, | 233 | u32 h_stream, |
240 | u16 *pw_state, | 234 | u16 *pw_state, |
241 | u32 *pbuffer_size, | 235 | u32 *pbuffer_size, |
@@ -244,42 +238,43 @@ static inline u16 hpi_stream_get_info_ex( | |||
244 | u32 *pauxiliary_data | 238 | u32 *pauxiliary_data |
245 | ) | 239 | ) |
246 | { | 240 | { |
241 | u16 e; | ||
247 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 242 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
248 | return hpi_outstream_get_info_ex(hS, h_stream, pw_state, | 243 | e = hpi_outstream_get_info_ex(h_stream, pw_state, |
249 | pbuffer_size, pdata_in_buffer, | 244 | pbuffer_size, pdata_in_buffer, |
250 | psample_count, pauxiliary_data); | 245 | psample_count, pauxiliary_data); |
251 | else | 246 | else |
252 | return hpi_instream_get_info_ex(hS, h_stream, pw_state, | 247 | e = hpi_instream_get_info_ex(h_stream, pw_state, |
253 | pbuffer_size, pdata_in_buffer, | 248 | pbuffer_size, pdata_in_buffer, |
254 | psample_count, pauxiliary_data); | 249 | psample_count, pauxiliary_data); |
250 | return e; | ||
255 | } | 251 | } |
256 | 252 | ||
257 | static inline u16 hpi_stream_group_add(struct hpi_hsubsys *hS, | 253 | static inline u16 hpi_stream_group_add( |
258 | u32 h_master, | 254 | u32 h_master, |
259 | u32 h_stream) | 255 | u32 h_stream) |
260 | { | 256 | { |
261 | if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM) | 257 | if (hpi_handle_object(h_master) == HPI_OBJ_OSTREAM) |
262 | return hpi_outstream_group_add(hS, h_master, h_stream); | 258 | return hpi_outstream_group_add(h_master, h_stream); |
263 | else | 259 | else |
264 | return hpi_instream_group_add(hS, h_master, h_stream); | 260 | return hpi_instream_group_add(h_master, h_stream); |
265 | } | 261 | } |
266 | 262 | ||
267 | static inline u16 hpi_stream_group_reset(struct hpi_hsubsys *hS, | 263 | static inline u16 hpi_stream_group_reset(u32 h_stream) |
268 | u32 h_stream) | ||
269 | { | 264 | { |
270 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 265 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
271 | return hpi_outstream_group_reset(hS, h_stream); | 266 | return hpi_outstream_group_reset(h_stream); |
272 | else | 267 | else |
273 | return hpi_instream_group_reset(hS, h_stream); | 268 | return hpi_instream_group_reset(h_stream); |
274 | } | 269 | } |
275 | 270 | ||
276 | static inline u16 hpi_stream_group_get_map(struct hpi_hsubsys *hS, | 271 | static inline u16 hpi_stream_group_get_map( |
277 | u32 h_stream, u32 *mo, u32 *mi) | 272 | u32 h_stream, u32 *mo, u32 *mi) |
278 | { | 273 | { |
279 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) | 274 | if (hpi_handle_object(h_stream) == HPI_OBJ_OSTREAM) |
280 | return hpi_outstream_group_get_map(hS, h_stream, mo, mi); | 275 | return hpi_outstream_group_get_map(h_stream, mo, mi); |
281 | else | 276 | else |
282 | return hpi_instream_group_get_map(hS, h_stream, mo, mi); | 277 | return hpi_instream_group_get_map(h_stream, mo, mi); |
283 | } | 278 | } |
284 | 279 | ||
285 | static u16 handle_error(u16 err, int line, char *filename) | 280 | static u16 handle_error(u16 err, int line, char *filename) |
@@ -299,11 +294,11 @@ static void print_hwparams(struct snd_pcm_hw_params *p) | |||
299 | { | 294 | { |
300 | snd_printd("HWPARAMS \n"); | 295 | snd_printd("HWPARAMS \n"); |
301 | snd_printd("samplerate %d \n", params_rate(p)); | 296 | snd_printd("samplerate %d \n", params_rate(p)); |
302 | snd_printd("channels %d \n", params_channels(p)); | 297 | snd_printd("Channels %d \n", params_channels(p)); |
303 | snd_printd("format %d \n", params_format(p)); | 298 | snd_printd("Format %d \n", params_format(p)); |
304 | snd_printd("subformat %d \n", params_subformat(p)); | 299 | snd_printd("subformat %d \n", params_subformat(p)); |
305 | snd_printd("buffer bytes %d \n", params_buffer_bytes(p)); | 300 | snd_printd("Buffer bytes %d \n", params_buffer_bytes(p)); |
306 | snd_printd("period bytes %d \n", params_period_bytes(p)); | 301 | snd_printd("Period bytes %d \n", params_period_bytes(p)); |
307 | snd_printd("access %d \n", params_access(p)); | 302 | snd_printd("access %d \n", params_access(p)); |
308 | snd_printd("period_size %d \n", params_period_size(p)); | 303 | snd_printd("period_size %d \n", params_period_size(p)); |
309 | snd_printd("periods %d \n", params_periods(p)); | 304 | snd_printd("periods %d \n", params_periods(p)); |
@@ -335,7 +330,7 @@ static snd_pcm_format_t hpi_to_alsa_formats[] = { | |||
335 | */ | 330 | */ |
336 | -1 | 331 | -1 |
337 | #else | 332 | #else |
338 | /* SNDRV_PCM_FORMAT_S24_3LE */ /* { HPI_FORMAT_PCM24_SIGNED 15 */ | 333 | /* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */ |
339 | #endif | 334 | #endif |
340 | }; | 335 | }; |
341 | 336 | ||
@@ -378,20 +373,20 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi, | |||
378 | } else { | 373 | } else { |
379 | /* on cards without SRC, | 374 | /* on cards without SRC, |
380 | valid rates are determined by sampleclock */ | 375 | valid rates are determined by sampleclock */ |
381 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 376 | err = hpi_mixer_get_control(asihpi->h_mixer, |
382 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 377 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
383 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 378 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
384 | if (err) { | 379 | if (err) { |
385 | snd_printk(KERN_ERR | 380 | snd_printk(KERN_ERR |
386 | "no local sampleclock, err %d\n", err); | 381 | "No local sampleclock, err %d\n", err); |
387 | } | 382 | } |
388 | 383 | ||
389 | for (idx = 0; idx < 100; idx++) { | 384 | for (idx = 0; idx < 100; idx++) { |
390 | if (hpi_sample_clock_query_local_rate(ss, | 385 | if (hpi_sample_clock_query_local_rate( |
391 | h_control, idx, &sample_rate)) { | 386 | h_control, idx, &sample_rate)) { |
392 | if (!idx) | 387 | if (!idx) |
393 | snd_printk(KERN_ERR | 388 | snd_printk(KERN_ERR |
394 | "local rate query failed\n"); | 389 | "Local rate query failed\n"); |
395 | 390 | ||
396 | break; | 391 | break; |
397 | } | 392 | } |
@@ -480,10 +475,10 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
480 | format, params_rate(params), 0, 0)); | 475 | format, params_rate(params), 0, 0)); |
481 | 476 | ||
482 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 477 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
483 | if (hpi_instream_reset(ss, dpcm->h_stream) != 0) | 478 | if (hpi_instream_reset(dpcm->h_stream) != 0) |
484 | return -EINVAL; | 479 | return -EINVAL; |
485 | 480 | ||
486 | if (hpi_instream_set_format(ss, | 481 | if (hpi_instream_set_format( |
487 | dpcm->h_stream, &dpcm->format) != 0) | 482 | dpcm->h_stream, &dpcm->format) != 0) |
488 | return -EINVAL; | 483 | return -EINVAL; |
489 | } | 484 | } |
@@ -491,10 +486,10 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
491 | dpcm->hpi_buffer_attached = 0; | 486 | dpcm->hpi_buffer_attached = 0; |
492 | if (card->support_mmap) { | 487 | if (card->support_mmap) { |
493 | 488 | ||
494 | err = hpi_stream_host_buffer_attach(ss, dpcm->h_stream, | 489 | err = hpi_stream_host_buffer_attach(dpcm->h_stream, |
495 | params_buffer_bytes(params), runtime->dma_addr); | 490 | params_buffer_bytes(params), runtime->dma_addr); |
496 | if (err == 0) { | 491 | if (err == 0) { |
497 | snd_printd(KERN_INFO | 492 | VPRINTK1(KERN_INFO |
498 | "stream_host_buffer_attach succeeded %u %lu\n", | 493 | "stream_host_buffer_attach succeeded %u %lu\n", |
499 | params_buffer_bytes(params), | 494 | params_buffer_bytes(params), |
500 | (unsigned long)runtime->dma_addr); | 495 | (unsigned long)runtime->dma_addr); |
@@ -505,11 +500,11 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
505 | return -ENOMEM; | 500 | return -ENOMEM; |
506 | } | 501 | } |
507 | 502 | ||
508 | err = hpi_stream_get_info_ex(ss, dpcm->h_stream, NULL, | 503 | err = hpi_stream_get_info_ex(dpcm->h_stream, NULL, |
509 | &dpcm->hpi_buffer_attached, | 504 | &dpcm->hpi_buffer_attached, |
510 | NULL, NULL, NULL); | 505 | NULL, NULL, NULL); |
511 | 506 | ||
512 | snd_printd(KERN_INFO "stream_host_buffer_attach status 0x%x\n", | 507 | VPRINTK1(KERN_INFO "stream_host_buffer_attach status 0x%x\n", |
513 | dpcm->hpi_buffer_attached); | 508 | dpcm->hpi_buffer_attached); |
514 | } | 509 | } |
515 | bytes_per_sec = params_rate(params) * params_channels(params); | 510 | bytes_per_sec = params_rate(params) * params_channels(params); |
@@ -520,16 +515,32 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream, | |||
520 | return -EINVAL; | 515 | return -EINVAL; |
521 | 516 | ||
522 | dpcm->bytes_per_sec = bytes_per_sec; | 517 | dpcm->bytes_per_sec = bytes_per_sec; |
523 | dpcm->pcm_size = params_buffer_bytes(params); | 518 | dpcm->buffer_bytes = params_buffer_bytes(params); |
524 | dpcm->pcm_count = params_period_bytes(params); | 519 | dpcm->period_bytes = params_period_bytes(params); |
525 | snd_printd(KERN_INFO "pcm_size=%d, pcm_count=%d, bps=%d\n", | 520 | VPRINTK1(KERN_INFO "buffer_bytes=%d, period_bytes=%d, bps=%d\n", |
526 | dpcm->pcm_size, dpcm->pcm_count, bytes_per_sec); | 521 | dpcm->buffer_bytes, dpcm->period_bytes, bytes_per_sec); |
527 | 522 | ||
528 | dpcm->pcm_irq_pos = 0; | ||
529 | dpcm->pcm_buf_pos = 0; | ||
530 | return 0; | 523 | return 0; |
531 | } | 524 | } |
532 | 525 | ||
526 | static int | ||
527 | snd_card_asihpi_hw_free(struct snd_pcm_substream *substream) | ||
528 | { | ||
529 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
530 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
531 | if (dpcm->hpi_buffer_attached) | ||
532 | hpi_stream_host_buffer_detach(dpcm->h_stream); | ||
533 | |||
534 | snd_pcm_lib_free_pages(substream); | ||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime) | ||
539 | { | ||
540 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
541 | kfree(dpcm); | ||
542 | } | ||
543 | |||
533 | static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * | 544 | static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * |
534 | substream) | 545 | substream) |
535 | { | 546 | { |
@@ -537,9 +548,9 @@ static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream * | |||
537 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 548 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
538 | int expiry; | 549 | int expiry; |
539 | 550 | ||
540 | expiry = (dpcm->pcm_count * HZ / dpcm->bytes_per_sec); | 551 | expiry = HZ / 200; |
541 | /* wait longer the first time, for samples to propagate */ | 552 | /*? (dpcm->period_bytes * HZ / dpcm->bytes_per_sec); */ |
542 | expiry = max(expiry, 20); | 553 | expiry = max(expiry, 1); /* don't let it be zero! */ |
543 | dpcm->timer.expires = jiffies + expiry; | 554 | dpcm->timer.expires = jiffies + expiry; |
544 | dpcm->respawn_timer = 1; | 555 | dpcm->respawn_timer = 1; |
545 | add_timer(&dpcm->timer); | 556 | add_timer(&dpcm->timer); |
@@ -562,37 +573,44 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
562 | struct snd_pcm_substream *s; | 573 | struct snd_pcm_substream *s; |
563 | u16 e; | 574 | u16 e; |
564 | 575 | ||
565 | snd_printd("trigger %dstream %d\n", | 576 | VPRINTK1(KERN_INFO "%c%d trigger\n", |
566 | substream->stream, substream->number); | 577 | SCHR(substream->stream), substream->number); |
567 | switch (cmd) { | 578 | switch (cmd) { |
568 | case SNDRV_PCM_TRIGGER_START: | 579 | case SNDRV_PCM_TRIGGER_START: |
569 | snd_pcm_group_for_each_entry(s, substream) { | 580 | snd_pcm_group_for_each_entry(s, substream) { |
570 | struct snd_card_asihpi_pcm *ds; | 581 | struct snd_pcm_runtime *runtime = s->runtime; |
571 | ds = s->runtime->private_data; | 582 | struct snd_card_asihpi_pcm *ds = runtime->private_data; |
572 | 583 | ||
573 | if (snd_pcm_substream_chip(s) != card) | 584 | if (snd_pcm_substream_chip(s) != card) |
574 | continue; | 585 | continue; |
575 | 586 | ||
587 | /* don't link Cap and Play */ | ||
588 | if (substream->stream != s->stream) | ||
589 | continue; | ||
590 | |||
576 | if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) && | 591 | if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) && |
577 | (card->support_mmap)) { | 592 | (card->support_mmap)) { |
578 | /* How do I know how much valid data is present | 593 | /* How do I know how much valid data is present |
579 | * in buffer? Just guessing 2 periods, but if | 594 | * in buffer? Must be at least one period! |
595 | * Guessing 2 periods, but if | ||
580 | * buffer is bigger it may contain even more | 596 | * buffer is bigger it may contain even more |
581 | * data?? | 597 | * data?? |
582 | */ | 598 | */ |
583 | unsigned int preload = ds->pcm_count * 2; | 599 | unsigned int preload = ds->period_bytes * 1; |
584 | VPRINTK2("preload %d\n", preload); | 600 | VPRINTK2(KERN_INFO "%d preload x%x\n", s->number, preload); |
585 | hpi_handle_error(hpi_outstream_write_buf( | 601 | hpi_handle_error(hpi_outstream_write_buf( |
586 | ss, ds->h_stream, | 602 | ds->h_stream, |
587 | &s->runtime->dma_area[0], | 603 | &runtime->dma_area[0], |
588 | preload, | 604 | preload, |
589 | &ds->format)); | 605 | &ds->format)); |
606 | ds->pcm_buf_host_rw_ofs = preload; | ||
590 | } | 607 | } |
591 | 608 | ||
592 | if (card->support_grouping) { | 609 | if (card->support_grouping) { |
593 | VPRINTK1("\t_group %dstream %d\n", s->stream, | 610 | VPRINTK1(KERN_INFO "\t%c%d group\n", |
611 | SCHR(s->stream), | ||
594 | s->number); | 612 | s->number); |
595 | e = hpi_stream_group_add(ss, | 613 | e = hpi_stream_group_add( |
596 | dpcm->h_stream, | 614 | dpcm->h_stream, |
597 | ds->h_stream); | 615 | ds->h_stream); |
598 | if (!e) { | 616 | if (!e) { |
@@ -604,10 +622,12 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
604 | } else | 622 | } else |
605 | break; | 623 | break; |
606 | } | 624 | } |
607 | snd_printd("start\n"); | 625 | VPRINTK1(KERN_INFO "start\n"); |
608 | /* start the master stream */ | 626 | /* start the master stream */ |
609 | snd_card_asihpi_pcm_timer_start(substream); | 627 | snd_card_asihpi_pcm_timer_start(substream); |
610 | hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream)); | 628 | if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) || |
629 | !card->support_mmap) | ||
630 | hpi_handle_error(hpi_stream_start(dpcm->h_stream)); | ||
611 | break; | 631 | break; |
612 | 632 | ||
613 | case SNDRV_PCM_TRIGGER_STOP: | 633 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -615,88 +635,73 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, | |||
615 | snd_pcm_group_for_each_entry(s, substream) { | 635 | snd_pcm_group_for_each_entry(s, substream) { |
616 | if (snd_pcm_substream_chip(s) != card) | 636 | if (snd_pcm_substream_chip(s) != card) |
617 | continue; | 637 | continue; |
638 | /* don't link Cap and Play */ | ||
639 | if (substream->stream != s->stream) | ||
640 | continue; | ||
618 | 641 | ||
619 | /*? workaround linked streams don't | 642 | /*? workaround linked streams don't |
620 | transition to SETUP 20070706*/ | 643 | transition to SETUP 20070706*/ |
621 | s->runtime->status->state = SNDRV_PCM_STATE_SETUP; | 644 | s->runtime->status->state = SNDRV_PCM_STATE_SETUP; |
622 | 645 | ||
623 | if (card->support_grouping) { | 646 | if (card->support_grouping) { |
624 | VPRINTK1("\t_group %dstream %d\n", s->stream, | 647 | VPRINTK1(KERN_INFO "\t%c%d group\n", |
648 | SCHR(s->stream), | ||
625 | s->number); | 649 | s->number); |
626 | snd_pcm_trigger_done(s, substream); | 650 | snd_pcm_trigger_done(s, substream); |
627 | } else | 651 | } else |
628 | break; | 652 | break; |
629 | } | 653 | } |
630 | snd_printd("stop\n"); | 654 | VPRINTK1(KERN_INFO "stop\n"); |
631 | 655 | ||
632 | /* _prepare and _hwparams reset the stream */ | 656 | /* _prepare and _hwparams reset the stream */ |
633 | hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream)); | 657 | hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); |
634 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 658 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
635 | hpi_handle_error( | 659 | hpi_handle_error( |
636 | hpi_outstream_reset(ss, dpcm->h_stream)); | 660 | hpi_outstream_reset(dpcm->h_stream)); |
637 | 661 | ||
638 | if (card->support_grouping) | 662 | if (card->support_grouping) |
639 | hpi_handle_error(hpi_stream_group_reset(ss, | 663 | hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream)); |
640 | dpcm->h_stream)); | ||
641 | break; | 664 | break; |
642 | 665 | ||
643 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 666 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
644 | snd_printd("pause release\n"); | 667 | VPRINTK1(KERN_INFO "pause release\n"); |
645 | hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream)); | 668 | hpi_handle_error(hpi_stream_start(dpcm->h_stream)); |
646 | snd_card_asihpi_pcm_timer_start(substream); | 669 | snd_card_asihpi_pcm_timer_start(substream); |
647 | break; | 670 | break; |
648 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 671 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
649 | snd_printd("pause\n"); | 672 | VPRINTK1(KERN_INFO "pause\n"); |
650 | snd_card_asihpi_pcm_timer_stop(substream); | 673 | snd_card_asihpi_pcm_timer_stop(substream); |
651 | hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream)); | 674 | hpi_handle_error(hpi_stream_stop(dpcm->h_stream)); |
652 | break; | 675 | break; |
653 | default: | 676 | default: |
654 | snd_printd("\tINVALID\n"); | 677 | snd_printd(KERN_ERR "\tINVALID\n"); |
655 | return -EINVAL; | 678 | return -EINVAL; |
656 | } | 679 | } |
657 | 680 | ||
658 | return 0; | 681 | return 0; |
659 | } | 682 | } |
660 | 683 | ||
661 | static int | ||
662 | snd_card_asihpi_hw_free(struct snd_pcm_substream *substream) | ||
663 | { | ||
664 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
665 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
666 | if (dpcm->hpi_buffer_attached) | ||
667 | hpi_stream_host_buffer_detach(ss, dpcm->h_stream); | ||
668 | |||
669 | snd_pcm_lib_free_pages(substream); | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime) | ||
674 | { | ||
675 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | ||
676 | kfree(dpcm); | ||
677 | } | ||
678 | |||
679 | /*algorithm outline | 684 | /*algorithm outline |
680 | Without linking degenerates to getting single stream pos etc | 685 | Without linking degenerates to getting single stream pos etc |
681 | Without mmap 2nd loop degenerates to snd_pcm_period_elapsed | 686 | Without mmap 2nd loop degenerates to snd_pcm_period_elapsed |
682 | */ | 687 | */ |
683 | /* | 688 | /* |
684 | buf_pos=get_buf_pos(s); | 689 | pcm_buf_dma_ofs=get_buf_pos(s); |
685 | for_each_linked_stream(s) { | 690 | for_each_linked_stream(s) { |
686 | buf_pos=get_buf_pos(s); | 691 | pcm_buf_dma_ofs=get_buf_pos(s); |
687 | min_buf_pos = modulo_min(min_buf_pos, buf_pos, pcm_size) | 692 | min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes) |
688 | new_data = min(new_data, calc_new_data(buf_pos,irq_pos) | 693 | new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos) |
689 | } | 694 | } |
690 | timer.expires = jiffies + predict_next_period_ready(min_buf_pos); | 695 | timer.expires = jiffies + predict_next_period_ready(min_buf_pos); |
691 | for_each_linked_stream(s) { | 696 | for_each_linked_stream(s) { |
692 | s->buf_pos = min_buf_pos; | 697 | s->pcm_buf_dma_ofs = min_buf_pos; |
693 | if (new_data > pcm_count) { | 698 | if (new_data > period_bytes) { |
694 | if (mmap) { | 699 | if (mmap) { |
695 | irq_pos = (irq_pos + pcm_count) % pcm_size; | 700 | irq_pos = (irq_pos + period_bytes) % buffer_bytes; |
696 | if (playback) { | 701 | if (playback) { |
697 | write(pcm_count); | 702 | write(period_bytes); |
698 | } else { | 703 | } else { |
699 | read(pcm_count); | 704 | read(period_bytes); |
700 | } | 705 | } |
701 | } | 706 | } |
702 | snd_pcm_period_elapsed(s); | 707 | snd_pcm_period_elapsed(s); |
@@ -724,105 +729,136 @@ static inline unsigned int modulo_min(unsigned int a, unsigned int b, | |||
724 | static void snd_card_asihpi_timer_function(unsigned long data) | 729 | static void snd_card_asihpi_timer_function(unsigned long data) |
725 | { | 730 | { |
726 | struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data; | 731 | struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data; |
727 | struct snd_card_asihpi *card = snd_pcm_substream_chip(dpcm->substream); | 732 | struct snd_pcm_substream *substream = dpcm->substream; |
733 | struct snd_card_asihpi *card = snd_pcm_substream_chip(substream); | ||
728 | struct snd_pcm_runtime *runtime; | 734 | struct snd_pcm_runtime *runtime; |
729 | struct snd_pcm_substream *s; | 735 | struct snd_pcm_substream *s; |
730 | unsigned int newdata = 0; | 736 | unsigned int newdata = 0; |
731 | unsigned int buf_pos, min_buf_pos = 0; | 737 | unsigned int pcm_buf_dma_ofs, min_buf_pos = 0; |
732 | unsigned int remdata, xfercount, next_jiffies; | 738 | unsigned int remdata, xfercount, next_jiffies; |
733 | int first = 1; | 739 | int first = 1; |
740 | int loops = 0; | ||
734 | u16 state; | 741 | u16 state; |
735 | u32 buffer_size, data_avail, samples_played, aux; | 742 | u32 buffer_size, bytes_avail, samples_played, on_card_bytes; |
743 | |||
744 | VPRINTK1(KERN_INFO "%c%d snd_card_asihpi_timer_function\n", | ||
745 | SCHR(substream->stream), substream->number); | ||
736 | 746 | ||
737 | /* find minimum newdata and buffer pos in group */ | 747 | /* find minimum newdata and buffer pos in group */ |
738 | snd_pcm_group_for_each_entry(s, dpcm->substream) { | 748 | snd_pcm_group_for_each_entry(s, substream) { |
739 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; | 749 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; |
740 | runtime = s->runtime; | 750 | runtime = s->runtime; |
741 | 751 | ||
742 | if (snd_pcm_substream_chip(s) != card) | 752 | if (snd_pcm_substream_chip(s) != card) |
743 | continue; | 753 | continue; |
744 | 754 | ||
745 | hpi_handle_error(hpi_stream_get_info_ex(ss, | 755 | /* don't link Cap and Play */ |
756 | if (substream->stream != s->stream) | ||
757 | continue; | ||
758 | |||
759 | hpi_handle_error(hpi_stream_get_info_ex( | ||
746 | ds->h_stream, &state, | 760 | ds->h_stream, &state, |
747 | &buffer_size, &data_avail, | 761 | &buffer_size, &bytes_avail, |
748 | &samples_played, &aux)); | 762 | &samples_played, &on_card_bytes)); |
749 | 763 | ||
750 | /* number of bytes in on-card buffer */ | 764 | /* number of bytes in on-card buffer */ |
751 | runtime->delay = aux; | 765 | runtime->delay = on_card_bytes; |
752 | |||
753 | if (state == HPI_STATE_DRAINED) { | ||
754 | snd_printd(KERN_WARNING "outstream %d drained\n", | ||
755 | s->number); | ||
756 | snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); | ||
757 | return; | ||
758 | } | ||
759 | 766 | ||
760 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 767 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
761 | buf_pos = frames_to_bytes(runtime, samples_played); | 768 | pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail; |
762 | } else { | 769 | if (state == HPI_STATE_STOPPED) { |
763 | buf_pos = data_avail + ds->pcm_irq_pos; | 770 | if ((bytes_avail == 0) && |
764 | } | 771 | (on_card_bytes < ds->pcm_buf_host_rw_ofs)) { |
772 | hpi_handle_error(hpi_stream_start(ds->h_stream)); | ||
773 | VPRINTK1(KERN_INFO "P%d start\n", s->number); | ||
774 | } | ||
775 | } else if (state == HPI_STATE_DRAINED) { | ||
776 | VPRINTK1(KERN_WARNING "P%d drained\n", | ||
777 | s->number); | ||
778 | /*snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN); | ||
779 | continue; */ | ||
780 | } | ||
781 | } else | ||
782 | pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs; | ||
765 | 783 | ||
766 | if (first) { | 784 | if (first) { |
767 | /* can't statically init min when wrap is involved */ | 785 | /* can't statically init min when wrap is involved */ |
768 | min_buf_pos = buf_pos; | 786 | min_buf_pos = pcm_buf_dma_ofs; |
769 | newdata = (buf_pos - ds->pcm_irq_pos) % ds->pcm_size; | 787 | newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes; |
770 | first = 0; | 788 | first = 0; |
771 | } else { | 789 | } else { |
772 | min_buf_pos = | 790 | min_buf_pos = |
773 | modulo_min(min_buf_pos, buf_pos, UINT_MAX+1L); | 791 | modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L); |
774 | newdata = min( | 792 | newdata = min( |
775 | (buf_pos - ds->pcm_irq_pos) % ds->pcm_size, | 793 | (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes, |
776 | newdata); | 794 | newdata); |
777 | } | 795 | } |
778 | 796 | ||
779 | VPRINTK1("PB timer hw_ptr x%04lX, appl_ptr x%04lX\n", | 797 | VPRINTK1(KERN_INFO "PB timer hw_ptr x%04lX, appl_ptr x%04lX\n", |
780 | (unsigned long)frames_to_bytes(runtime, | 798 | (unsigned long)frames_to_bytes(runtime, |
781 | runtime->status->hw_ptr), | 799 | runtime->status->hw_ptr), |
782 | (unsigned long)frames_to_bytes(runtime, | 800 | (unsigned long)frames_to_bytes(runtime, |
783 | runtime->control->appl_ptr)); | 801 | runtime->control->appl_ptr)); |
784 | VPRINTK1("%d S=%d, irq=%04X, pos=x%04X, left=x%04X," | 802 | |
785 | " aux=x%04X space=x%04X\n", s->number, | 803 | VPRINTK1(KERN_INFO "%d %c%d S=%d, rw=%04X, dma=x%04X, left=x%04X," |
786 | state, ds->pcm_irq_pos, buf_pos, (int)data_avail, | 804 | " aux=x%04X space=x%04X\n", |
787 | (int)aux, buffer_size-data_avail); | 805 | loops, SCHR(s->stream), s->number, |
806 | state, ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, (int)bytes_avail, | ||
807 | (int)on_card_bytes, buffer_size-bytes_avail); | ||
808 | loops++; | ||
788 | } | 809 | } |
810 | pcm_buf_dma_ofs = min_buf_pos; | ||
789 | 811 | ||
790 | remdata = newdata % dpcm->pcm_count; | 812 | remdata = newdata % dpcm->period_bytes; |
791 | xfercount = newdata - remdata; /* a multiple of pcm_count */ | 813 | xfercount = newdata - remdata; /* a multiple of period_bytes */ |
792 | next_jiffies = ((dpcm->pcm_count-remdata) * HZ / dpcm->bytes_per_sec)+1; | 814 | /* come back when on_card_bytes has decreased enough to allow |
793 | next_jiffies = max(next_jiffies, 2U * HZ / 1000U); | 815 | write to happen, or when data has been consumed to make another |
816 | period | ||
817 | */ | ||
818 | if (xfercount && (on_card_bytes > dpcm->period_bytes)) | ||
819 | next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec); | ||
820 | else | ||
821 | next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec); | ||
822 | |||
823 | next_jiffies = max(next_jiffies, 1U); | ||
794 | dpcm->timer.expires = jiffies + next_jiffies; | 824 | dpcm->timer.expires = jiffies + next_jiffies; |
795 | VPRINTK1("jif %d buf pos x%04X newdata x%04X xc x%04X\n", | 825 | VPRINTK1(KERN_INFO "jif %d buf pos x%04X newdata x%04X xfer x%04X\n", |
796 | next_jiffies, min_buf_pos, newdata, xfercount); | 826 | next_jiffies, pcm_buf_dma_ofs, newdata, xfercount); |
797 | 827 | ||
798 | snd_pcm_group_for_each_entry(s, dpcm->substream) { | 828 | snd_pcm_group_for_each_entry(s, substream) { |
799 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; | 829 | struct snd_card_asihpi_pcm *ds = s->runtime->private_data; |
800 | ds->pcm_buf_pos = min_buf_pos; | ||
801 | 830 | ||
802 | if (xfercount) { | 831 | /* don't link Cap and Play */ |
832 | if (substream->stream != s->stream) | ||
833 | continue; | ||
834 | |||
835 | ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs; | ||
836 | |||
837 | if (xfercount && (on_card_bytes <= ds->period_bytes)) { | ||
803 | if (card->support_mmap) { | 838 | if (card->support_mmap) { |
804 | ds->pcm_irq_pos = ds->pcm_irq_pos + xfercount; | ||
805 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 839 | if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
806 | VPRINTK2("write OS%d x%04x\n", | 840 | VPRINTK2(KERN_INFO "P%d write x%04x\n", |
807 | s->number, | 841 | s->number, |
808 | ds->pcm_count); | 842 | ds->period_bytes); |
809 | hpi_handle_error( | 843 | hpi_handle_error( |
810 | hpi_outstream_write_buf( | 844 | hpi_outstream_write_buf( |
811 | ss, ds->h_stream, | 845 | ds->h_stream, |
812 | &s->runtime-> | 846 | &s->runtime-> |
813 | dma_area[0], | 847 | dma_area[0], |
814 | xfercount, | 848 | xfercount, |
815 | &ds->format)); | 849 | &ds->format)); |
816 | } else { | 850 | } else { |
817 | VPRINTK2("read IS%d x%04x\n", | 851 | VPRINTK2(KERN_INFO "C%d read x%04x\n", |
818 | s->number, | 852 | s->number, |
819 | dpcm->pcm_count); | 853 | xfercount); |
820 | hpi_handle_error( | 854 | hpi_handle_error( |
821 | hpi_instream_read_buf( | 855 | hpi_instream_read_buf( |
822 | ss, ds->h_stream, | 856 | ds->h_stream, |
823 | NULL, xfercount)); | 857 | NULL, xfercount)); |
824 | } | 858 | } |
859 | ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount; | ||
825 | } /* else R/W will be handled by read/write callbacks */ | 860 | } /* else R/W will be handled by read/write callbacks */ |
861 | ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs; | ||
826 | snd_pcm_period_elapsed(s); | 862 | snd_pcm_period_elapsed(s); |
827 | } | 863 | } |
828 | } | 864 | } |
@@ -845,12 +881,12 @@ static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream * | |||
845 | struct snd_pcm_runtime *runtime = substream->runtime; | 881 | struct snd_pcm_runtime *runtime = substream->runtime; |
846 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 882 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
847 | 883 | ||
848 | snd_printd(KERN_INFO "playback prepare %d\n", substream->number); | 884 | VPRINTK1(KERN_INFO "playback prepare %d\n", substream->number); |
849 | |||
850 | hpi_handle_error(hpi_outstream_reset(ss, dpcm->h_stream)); | ||
851 | dpcm->pcm_irq_pos = 0; | ||
852 | dpcm->pcm_buf_pos = 0; | ||
853 | 885 | ||
886 | hpi_handle_error(hpi_outstream_reset(dpcm->h_stream)); | ||
887 | dpcm->pcm_buf_host_rw_ofs = 0; | ||
888 | dpcm->pcm_buf_dma_ofs = 0; | ||
889 | dpcm->pcm_buf_elapsed_dma_ofs = 0; | ||
854 | return 0; | 890 | return 0; |
855 | } | 891 | } |
856 | 892 | ||
@@ -861,27 +897,8 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream) | |||
861 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 897 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
862 | snd_pcm_uframes_t ptr; | 898 | snd_pcm_uframes_t ptr; |
863 | 899 | ||
864 | u32 samples_played; | 900 | ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); |
865 | u16 err; | 901 | /* VPRINTK2(KERN_INFO "playback_pointer=x%04lx\n", (unsigned long)ptr); */ |
866 | |||
867 | if (!snd_pcm_stream_linked(substream)) { | ||
868 | /* NOTE, can use samples played for playback position here and | ||
869 | * in timer fn because it LAGS the actual read pointer, and is a | ||
870 | * better representation of actual playout position | ||
871 | */ | ||
872 | err = hpi_outstream_get_info_ex(ss, dpcm->h_stream, NULL, | ||
873 | NULL, NULL, | ||
874 | &samples_played, NULL); | ||
875 | hpi_handle_error(err); | ||
876 | |||
877 | dpcm->pcm_buf_pos = frames_to_bytes(runtime, samples_played); | ||
878 | } | ||
879 | /* else must return most conservative value found in timer func | ||
880 | * by looping over all streams | ||
881 | */ | ||
882 | |||
883 | ptr = bytes_to_frames(runtime, dpcm->pcm_buf_pos % dpcm->pcm_size); | ||
884 | VPRINTK2("playback_pointer=%04ld\n", (unsigned long)ptr); | ||
885 | return ptr; | 902 | return ptr; |
886 | } | 903 | } |
887 | 904 | ||
@@ -898,12 +915,12 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi, | |||
898 | /* on cards without SRC, must query at valid rate, | 915 | /* on cards without SRC, must query at valid rate, |
899 | * maybe set by external sync | 916 | * maybe set by external sync |
900 | */ | 917 | */ |
901 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 918 | err = hpi_mixer_get_control(asihpi->h_mixer, |
902 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 919 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
903 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 920 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
904 | 921 | ||
905 | if (!err) | 922 | if (!err) |
906 | err = hpi_sample_clock_get_sample_rate(ss, h_control, | 923 | err = hpi_sample_clock_get_sample_rate(h_control, |
907 | &sample_rate); | 924 | &sample_rate); |
908 | 925 | ||
909 | for (format = HPI_FORMAT_PCM8_UNSIGNED; | 926 | for (format = HPI_FORMAT_PCM8_UNSIGNED; |
@@ -911,7 +928,7 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi, | |||
911 | err = hpi_format_create(&hpi_format, | 928 | err = hpi_format_create(&hpi_format, |
912 | 2, format, sample_rate, 128000, 0); | 929 | 2, format, sample_rate, 128000, 0); |
913 | if (!err) | 930 | if (!err) |
914 | err = hpi_outstream_query_format(ss, h_stream, | 931 | err = hpi_outstream_query_format(h_stream, |
915 | &hpi_format); | 932 | &hpi_format); |
916 | if (!err && (hpi_to_alsa_formats[format] != -1)) | 933 | if (!err && (hpi_to_alsa_formats[format] != -1)) |
917 | pcmhw->formats |= | 934 | pcmhw->formats |= |
@@ -942,7 +959,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
942 | return -ENOMEM; | 959 | return -ENOMEM; |
943 | 960 | ||
944 | err = | 961 | err = |
945 | hpi_outstream_open(ss, card->adapter_index, | 962 | hpi_outstream_open(card->adapter_index, |
946 | substream->number, &dpcm->h_stream); | 963 | substream->number, &dpcm->h_stream); |
947 | hpi_handle_error(err); | 964 | hpi_handle_error(err); |
948 | if (err) | 965 | if (err) |
@@ -998,11 +1015,11 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream) | |||
998 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 1015 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
999 | card->update_interval_frames); | 1016 | card->update_interval_frames); |
1000 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 1017 | snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
1001 | card->update_interval_frames * 4, UINT_MAX); | 1018 | card->update_interval_frames * 2, UINT_MAX); |
1002 | 1019 | ||
1003 | snd_pcm_set_sync(substream); | 1020 | snd_pcm_set_sync(substream); |
1004 | 1021 | ||
1005 | snd_printd(KERN_INFO "playback open\n"); | 1022 | VPRINTK1(KERN_INFO "playback open\n"); |
1006 | 1023 | ||
1007 | return 0; | 1024 | return 0; |
1008 | } | 1025 | } |
@@ -1012,8 +1029,8 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream) | |||
1012 | struct snd_pcm_runtime *runtime = substream->runtime; | 1029 | struct snd_pcm_runtime *runtime = substream->runtime; |
1013 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1030 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1014 | 1031 | ||
1015 | hpi_handle_error(hpi_outstream_close(ss, dpcm->h_stream)); | 1032 | hpi_handle_error(hpi_outstream_close(dpcm->h_stream)); |
1016 | snd_printd(KERN_INFO "playback close\n"); | 1033 | VPRINTK1(KERN_INFO "playback close\n"); |
1017 | 1034 | ||
1018 | return 0; | 1035 | return 0; |
1019 | } | 1036 | } |
@@ -1036,9 +1053,11 @@ static int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream, | |||
1036 | VPRINTK2(KERN_DEBUG "playback copy%d %u bytes\n", | 1053 | VPRINTK2(KERN_DEBUG "playback copy%d %u bytes\n", |
1037 | substream->number, len); | 1054 | substream->number, len); |
1038 | 1055 | ||
1039 | hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream, | 1056 | hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream, |
1040 | runtime->dma_area, len, &dpcm->format)); | 1057 | runtime->dma_area, len, &dpcm->format)); |
1041 | 1058 | ||
1059 | dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len; | ||
1060 | |||
1042 | return 0; | 1061 | return 0; |
1043 | } | 1062 | } |
1044 | 1063 | ||
@@ -1052,10 +1071,10 @@ static int snd_card_asihpi_playback_silence(struct snd_pcm_substream * | |||
1052 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1071 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1053 | 1072 | ||
1054 | len = frames_to_bytes(runtime, count); | 1073 | len = frames_to_bytes(runtime, count); |
1055 | snd_printd(KERN_INFO "playback silence %u bytes\n", len); | 1074 | VPRINTK1(KERN_INFO "playback silence %u bytes\n", len); |
1056 | 1075 | ||
1057 | memset(runtime->dma_area, 0, len); | 1076 | memset(runtime->dma_area, 0, len); |
1058 | hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream, | 1077 | hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream, |
1059 | runtime->dma_area, len, &dpcm->format)); | 1078 | runtime->dma_area, len, &dpcm->format)); |
1060 | return 0; | 1079 | return 0; |
1061 | } | 1080 | } |
@@ -1091,13 +1110,13 @@ snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream) | |||
1091 | struct snd_pcm_runtime *runtime = substream->runtime; | 1110 | struct snd_pcm_runtime *runtime = substream->runtime; |
1092 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1111 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1093 | 1112 | ||
1094 | VPRINTK2("capture pointer %d=%d\n", | 1113 | VPRINTK2(KERN_INFO "capture pointer %d=%d\n", |
1095 | substream->number, dpcm->pcm_buf_pos); | 1114 | substream->number, dpcm->pcm_buf_dma_ofs); |
1096 | /* NOTE Unlike playback can't use actual dwSamplesPlayed | 1115 | /* NOTE Unlike playback can't use actual samples_played |
1097 | for the capture position, because those samples aren't yet in | 1116 | for the capture position, because those samples aren't yet in |
1098 | the local buffer available for reading. | 1117 | the local buffer available for reading. |
1099 | */ | 1118 | */ |
1100 | return bytes_to_frames(runtime, dpcm->pcm_buf_pos % dpcm->pcm_size); | 1119 | return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes); |
1101 | } | 1120 | } |
1102 | 1121 | ||
1103 | static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream, | 1122 | static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream, |
@@ -1111,11 +1130,12 @@ static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream) | |||
1111 | struct snd_pcm_runtime *runtime = substream->runtime; | 1130 | struct snd_pcm_runtime *runtime = substream->runtime; |
1112 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1131 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1113 | 1132 | ||
1114 | hpi_handle_error(hpi_instream_reset(ss, dpcm->h_stream)); | 1133 | hpi_handle_error(hpi_instream_reset(dpcm->h_stream)); |
1115 | dpcm->pcm_irq_pos = 0; | 1134 | dpcm->pcm_buf_host_rw_ofs = 0; |
1116 | dpcm->pcm_buf_pos = 0; | 1135 | dpcm->pcm_buf_dma_ofs = 0; |
1136 | dpcm->pcm_buf_elapsed_dma_ofs = 0; | ||
1117 | 1137 | ||
1118 | snd_printd("capture prepare %d\n", substream->number); | 1138 | VPRINTK1("Capture Prepare %d\n", substream->number); |
1119 | return 0; | 1139 | return 0; |
1120 | } | 1140 | } |
1121 | 1141 | ||
@@ -1133,12 +1153,12 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi, | |||
1133 | 1153 | ||
1134 | /* on cards without SRC, must query at valid rate, | 1154 | /* on cards without SRC, must query at valid rate, |
1135 | maybe set by external sync */ | 1155 | maybe set by external sync */ |
1136 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 1156 | err = hpi_mixer_get_control(asihpi->h_mixer, |
1137 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 1157 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
1138 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 1158 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
1139 | 1159 | ||
1140 | if (!err) | 1160 | if (!err) |
1141 | err = hpi_sample_clock_get_sample_rate(ss, h_control, | 1161 | err = hpi_sample_clock_get_sample_rate(h_control, |
1142 | &sample_rate); | 1162 | &sample_rate); |
1143 | 1163 | ||
1144 | for (format = HPI_FORMAT_PCM8_UNSIGNED; | 1164 | for (format = HPI_FORMAT_PCM8_UNSIGNED; |
@@ -1147,7 +1167,7 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi, | |||
1147 | err = hpi_format_create(&hpi_format, 2, format, | 1167 | err = hpi_format_create(&hpi_format, 2, format, |
1148 | sample_rate, 128000, 0); | 1168 | sample_rate, 128000, 0); |
1149 | if (!err) | 1169 | if (!err) |
1150 | err = hpi_instream_query_format(ss, h_stream, | 1170 | err = hpi_instream_query_format(h_stream, |
1151 | &hpi_format); | 1171 | &hpi_format); |
1152 | if (!err) | 1172 | if (!err) |
1153 | pcmhw->formats |= | 1173 | pcmhw->formats |= |
@@ -1178,11 +1198,11 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) | |||
1178 | if (dpcm == NULL) | 1198 | if (dpcm == NULL) |
1179 | return -ENOMEM; | 1199 | return -ENOMEM; |
1180 | 1200 | ||
1181 | snd_printd("hpi_instream_open adapter %d stream %d\n", | 1201 | VPRINTK1("hpi_instream_open adapter %d stream %d\n", |
1182 | card->adapter_index, substream->number); | 1202 | card->adapter_index, substream->number); |
1183 | 1203 | ||
1184 | err = hpi_handle_error( | 1204 | err = hpi_handle_error( |
1185 | hpi_instream_open(ss, card->adapter_index, | 1205 | hpi_instream_open(card->adapter_index, |
1186 | substream->number, &dpcm->h_stream)); | 1206 | substream->number, &dpcm->h_stream)); |
1187 | if (err) | 1207 | if (err) |
1188 | kfree(dpcm); | 1208 | kfree(dpcm); |
@@ -1209,6 +1229,9 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream) | |||
1209 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP | | 1229 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP | |
1210 | SNDRV_PCM_INFO_MMAP_VALID; | 1230 | SNDRV_PCM_INFO_MMAP_VALID; |
1211 | 1231 | ||
1232 | if (card->support_grouping) | ||
1233 | snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START; | ||
1234 | |||
1212 | runtime->hw = snd_card_asihpi_capture; | 1235 | runtime->hw = snd_card_asihpi_capture; |
1213 | 1236 | ||
1214 | if (card->support_mmap) | 1237 | if (card->support_mmap) |
@@ -1231,7 +1254,7 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream) | |||
1231 | { | 1254 | { |
1232 | struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; | 1255 | struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data; |
1233 | 1256 | ||
1234 | hpi_handle_error(hpi_instream_close(ss, dpcm->h_stream)); | 1257 | hpi_handle_error(hpi_instream_close(dpcm->h_stream)); |
1235 | return 0; | 1258 | return 0; |
1236 | } | 1259 | } |
1237 | 1260 | ||
@@ -1241,18 +1264,17 @@ static int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream, | |||
1241 | { | 1264 | { |
1242 | struct snd_pcm_runtime *runtime = substream->runtime; | 1265 | struct snd_pcm_runtime *runtime = substream->runtime; |
1243 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; | 1266 | struct snd_card_asihpi_pcm *dpcm = runtime->private_data; |
1244 | u32 data_size; | 1267 | u32 len; |
1245 | 1268 | ||
1246 | data_size = frames_to_bytes(runtime, count); | 1269 | len = frames_to_bytes(runtime, count); |
1247 | 1270 | ||
1248 | VPRINTK2("capture copy%d %d bytes\n", substream->number, data_size); | 1271 | VPRINTK2(KERN_INFO "capture copy%d %d bytes\n", substream->number, len); |
1249 | hpi_handle_error(hpi_instream_read_buf(ss, dpcm->h_stream, | 1272 | hpi_handle_error(hpi_instream_read_buf(dpcm->h_stream, |
1250 | runtime->dma_area, data_size)); | 1273 | runtime->dma_area, len)); |
1251 | 1274 | ||
1252 | /* Used by capture_pointer */ | 1275 | dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len; |
1253 | dpcm->pcm_irq_pos = dpcm->pcm_irq_pos + data_size; | ||
1254 | 1276 | ||
1255 | if (copy_to_user(dst, runtime->dma_area, data_size)) | 1277 | if (copy_to_user(dst, runtime->dma_area, len)) |
1256 | return -EFAULT; | 1278 | return -EFAULT; |
1257 | 1279 | ||
1258 | return 0; | 1280 | return 0; |
@@ -1287,7 +1309,7 @@ static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, | |||
1287 | struct snd_pcm *pcm; | 1309 | struct snd_pcm *pcm; |
1288 | int err; | 1310 | int err; |
1289 | 1311 | ||
1290 | err = snd_pcm_new(asihpi->card, "asihpi PCM", device, | 1312 | err = snd_pcm_new(asihpi->card, "Asihpi PCM", device, |
1291 | asihpi->num_outstreams, asihpi->num_instreams, | 1313 | asihpi->num_outstreams, asihpi->num_instreams, |
1292 | &pcm); | 1314 | &pcm); |
1293 | if (err < 0) | 1315 | if (err < 0) |
@@ -1307,7 +1329,7 @@ static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, | |||
1307 | 1329 | ||
1308 | pcm->private_data = asihpi; | 1330 | pcm->private_data = asihpi; |
1309 | pcm->info_flags = 0; | 1331 | pcm->info_flags = 0; |
1310 | strcpy(pcm->name, "asihpi PCM"); | 1332 | strcpy(pcm->name, "Asihpi PCM"); |
1311 | 1333 | ||
1312 | /*? do we want to emulate MMAP for non-BBM cards? | 1334 | /*? do we want to emulate MMAP for non-BBM cards? |
1313 | Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */ | 1335 | Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */ |
@@ -1330,8 +1352,7 @@ struct hpi_control { | |||
1330 | char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ | 1352 | char name[44]; /* copied to snd_ctl_elem_id.name[44]; */ |
1331 | }; | 1353 | }; |
1332 | 1354 | ||
1333 | static char *asihpi_tuner_band_names[] = | 1355 | static const char * const asihpi_tuner_band_names[] = { |
1334 | { | ||
1335 | "invalid", | 1356 | "invalid", |
1336 | "AM", | 1357 | "AM", |
1337 | "FM mono", | 1358 | "FM mono", |
@@ -1349,70 +1370,36 @@ compile_time_assert( | |||
1349 | (HPI_TUNER_BAND_LAST+1)), | 1370 | (HPI_TUNER_BAND_LAST+1)), |
1350 | assert_tuner_band_names_size); | 1371 | assert_tuner_band_names_size); |
1351 | 1372 | ||
1352 | #if ASI_STYLE_NAMES | 1373 | static const char * const asihpi_src_names[] = { |
1353 | static char *asihpi_src_names[] = | ||
1354 | { | ||
1355 | "no source", | 1374 | "no source", |
1356 | "outstream", | 1375 | "PCM", |
1357 | "line_in", | 1376 | "Line", |
1358 | "aes_in", | 1377 | "Digital", |
1359 | "tuner", | 1378 | "Tuner", |
1360 | "RF", | 1379 | "RF", |
1361 | "clock", | 1380 | "Clock", |
1362 | "bitstr", | 1381 | "Bitstream", |
1363 | "mic", | 1382 | "Microphone", |
1364 | "cobranet", | 1383 | "Cobranet", |
1365 | "analog_in", | 1384 | "Analog", |
1366 | "adapter", | 1385 | "Adapter", |
1367 | }; | 1386 | }; |
1368 | #else | ||
1369 | static char *asihpi_src_names[] = | ||
1370 | { | ||
1371 | "no source", | ||
1372 | "PCM playback", | ||
1373 | "line in", | ||
1374 | "digital in", | ||
1375 | "tuner", | ||
1376 | "RF", | ||
1377 | "clock", | ||
1378 | "bitstream", | ||
1379 | "mic", | ||
1380 | "cobranet in", | ||
1381 | "analog in", | ||
1382 | "adapter", | ||
1383 | }; | ||
1384 | #endif | ||
1385 | 1387 | ||
1386 | compile_time_assert( | 1388 | compile_time_assert( |
1387 | (ARRAY_SIZE(asihpi_src_names) == | 1389 | (ARRAY_SIZE(asihpi_src_names) == |
1388 | (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)), | 1390 | (HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)), |
1389 | assert_src_names_size); | 1391 | assert_src_names_size); |
1390 | 1392 | ||
1391 | #if ASI_STYLE_NAMES | 1393 | static const char * const asihpi_dst_names[] = { |
1392 | static char *asihpi_dst_names[] = | ||
1393 | { | ||
1394 | "no destination", | ||
1395 | "instream", | ||
1396 | "line_out", | ||
1397 | "aes_out", | ||
1398 | "RF", | ||
1399 | "speaker" , | ||
1400 | "cobranet", | ||
1401 | "analog_out", | ||
1402 | }; | ||
1403 | #else | ||
1404 | static char *asihpi_dst_names[] = | ||
1405 | { | ||
1406 | "no destination", | 1394 | "no destination", |
1407 | "PCM capture", | 1395 | "PCM", |
1408 | "line out", | 1396 | "Line", |
1409 | "digital out", | 1397 | "Digital", |
1410 | "RF", | 1398 | "RF", |
1411 | "speaker", | 1399 | "Speaker", |
1412 | "cobranet out", | 1400 | "Cobranet Out", |
1413 | "analog out" | 1401 | "Analog" |
1414 | }; | 1402 | }; |
1415 | #endif | ||
1416 | 1403 | ||
1417 | compile_time_assert( | 1404 | compile_time_assert( |
1418 | (ARRAY_SIZE(asihpi_dst_names) == | 1405 | (ARRAY_SIZE(asihpi_dst_names) == |
@@ -1438,30 +1425,45 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control, | |||
1438 | struct hpi_control *hpi_ctl, | 1425 | struct hpi_control *hpi_ctl, |
1439 | char *name) | 1426 | char *name) |
1440 | { | 1427 | { |
1428 | char *dir = ""; | ||
1441 | memset(snd_control, 0, sizeof(*snd_control)); | 1429 | memset(snd_control, 0, sizeof(*snd_control)); |
1442 | snd_control->name = hpi_ctl->name; | 1430 | snd_control->name = hpi_ctl->name; |
1443 | snd_control->private_value = hpi_ctl->h_control; | 1431 | snd_control->private_value = hpi_ctl->h_control; |
1444 | snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 1432 | snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
1445 | snd_control->index = 0; | 1433 | snd_control->index = 0; |
1446 | 1434 | ||
1435 | if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM) | ||
1436 | dir = "Capture "; /* On or towards a PCM capture destination*/ | ||
1437 | else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && | ||
1438 | (!hpi_ctl->dst_node_type)) | ||
1439 | dir = "Capture "; /* On a source node that is not PCM playback */ | ||
1440 | else if (hpi_ctl->src_node_type && | ||
1441 | (hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) && | ||
1442 | (hpi_ctl->dst_node_type)) | ||
1443 | dir = "Monitor Playback "; /* Between an input and an output */ | ||
1444 | else | ||
1445 | dir = "Playback "; /* PCM Playback source, or output node */ | ||
1446 | |||
1447 | if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) | 1447 | if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type) |
1448 | sprintf(hpi_ctl->name, "%s%d to %s%d %s", | 1448 | sprintf(hpi_ctl->name, "%s%d %s%d %s%s", |
1449 | asihpi_src_names[hpi_ctl->src_node_type], | 1449 | asihpi_src_names[hpi_ctl->src_node_type], |
1450 | hpi_ctl->src_node_index, | 1450 | hpi_ctl->src_node_index, |
1451 | asihpi_dst_names[hpi_ctl->dst_node_type], | 1451 | asihpi_dst_names[hpi_ctl->dst_node_type], |
1452 | hpi_ctl->dst_node_index, | 1452 | hpi_ctl->dst_node_index, |
1453 | name); | 1453 | dir, name); |
1454 | else if (hpi_ctl->dst_node_type) { | 1454 | else if (hpi_ctl->dst_node_type) { |
1455 | sprintf(hpi_ctl->name, "%s%d %s", | 1455 | sprintf(hpi_ctl->name, "%s %d %s%s", |
1456 | asihpi_dst_names[hpi_ctl->dst_node_type], | 1456 | asihpi_dst_names[hpi_ctl->dst_node_type], |
1457 | hpi_ctl->dst_node_index, | 1457 | hpi_ctl->dst_node_index, |
1458 | name); | 1458 | dir, name); |
1459 | } else { | 1459 | } else { |
1460 | sprintf(hpi_ctl->name, "%s%d %s", | 1460 | sprintf(hpi_ctl->name, "%s %d %s%s", |
1461 | asihpi_src_names[hpi_ctl->src_node_type], | 1461 | asihpi_src_names[hpi_ctl->src_node_type], |
1462 | hpi_ctl->src_node_index, | 1462 | hpi_ctl->src_node_index, |
1463 | name); | 1463 | dir, name); |
1464 | } | 1464 | } |
1465 | /* printk(KERN_INFO "Adding %s %d to %d ", hpi_ctl->name, | ||
1466 | hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */ | ||
1465 | } | 1467 | } |
1466 | 1468 | ||
1467 | /*------------------------------------------------------------ | 1469 | /*------------------------------------------------------------ |
@@ -1478,7 +1480,7 @@ static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol, | |||
1478 | short max_gain_mB; | 1480 | short max_gain_mB; |
1479 | short step_gain_mB; | 1481 | short step_gain_mB; |
1480 | 1482 | ||
1481 | err = hpi_volume_query_range(ss, h_control, | 1483 | err = hpi_volume_query_range(h_control, |
1482 | &min_gain_mB, &max_gain_mB, &step_gain_mB); | 1484 | &min_gain_mB, &max_gain_mB, &step_gain_mB); |
1483 | if (err) { | 1485 | if (err) { |
1484 | max_gain_mB = 0; | 1486 | max_gain_mB = 0; |
@@ -1500,7 +1502,7 @@ static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol, | |||
1500 | u32 h_control = kcontrol->private_value; | 1502 | u32 h_control = kcontrol->private_value; |
1501 | short an_gain_mB[HPI_MAX_CHANNELS]; | 1503 | short an_gain_mB[HPI_MAX_CHANNELS]; |
1502 | 1504 | ||
1503 | hpi_handle_error(hpi_volume_get_gain(ss, h_control, an_gain_mB)); | 1505 | hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB)); |
1504 | ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB; | 1506 | ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB; |
1505 | ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB; | 1507 | ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB; |
1506 | 1508 | ||
@@ -1522,7 +1524,7 @@ static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol, | |||
1522 | asihpi->mixer_volume[addr][1] != right; | 1524 | asihpi->mixer_volume[addr][1] != right; |
1523 | */ | 1525 | */ |
1524 | change = 1; | 1526 | change = 1; |
1525 | hpi_handle_error(hpi_volume_set_gain(ss, h_control, an_gain_mB)); | 1527 | hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB)); |
1526 | return change; | 1528 | return change; |
1527 | } | 1529 | } |
1528 | 1530 | ||
@@ -1534,7 +1536,7 @@ static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi, | |||
1534 | struct snd_card *card = asihpi->card; | 1536 | struct snd_card *card = asihpi->card; |
1535 | struct snd_kcontrol_new snd_control; | 1537 | struct snd_kcontrol_new snd_control; |
1536 | 1538 | ||
1537 | asihpi_ctl_init(&snd_control, hpi_ctl, "volume"); | 1539 | asihpi_ctl_init(&snd_control, hpi_ctl, "Volume"); |
1538 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 1540 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
1539 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 1541 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
1540 | snd_control.info = snd_asihpi_volume_info; | 1542 | snd_control.info = snd_asihpi_volume_info; |
@@ -1558,7 +1560,7 @@ static int snd_asihpi_level_info(struct snd_kcontrol *kcontrol, | |||
1558 | short step_gain_mB; | 1560 | short step_gain_mB; |
1559 | 1561 | ||
1560 | err = | 1562 | err = |
1561 | hpi_level_query_range(ss, h_control, &min_gain_mB, | 1563 | hpi_level_query_range(h_control, &min_gain_mB, |
1562 | &max_gain_mB, &step_gain_mB); | 1564 | &max_gain_mB, &step_gain_mB); |
1563 | if (err) { | 1565 | if (err) { |
1564 | max_gain_mB = 2400; | 1566 | max_gain_mB = 2400; |
@@ -1580,7 +1582,7 @@ static int snd_asihpi_level_get(struct snd_kcontrol *kcontrol, | |||
1580 | u32 h_control = kcontrol->private_value; | 1582 | u32 h_control = kcontrol->private_value; |
1581 | short an_gain_mB[HPI_MAX_CHANNELS]; | 1583 | short an_gain_mB[HPI_MAX_CHANNELS]; |
1582 | 1584 | ||
1583 | hpi_handle_error(hpi_level_get_gain(ss, h_control, an_gain_mB)); | 1585 | hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB)); |
1584 | ucontrol->value.integer.value[0] = | 1586 | ucontrol->value.integer.value[0] = |
1585 | an_gain_mB[0] / HPI_UNITS_PER_dB; | 1587 | an_gain_mB[0] / HPI_UNITS_PER_dB; |
1586 | ucontrol->value.integer.value[1] = | 1588 | ucontrol->value.integer.value[1] = |
@@ -1604,7 +1606,7 @@ static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol, | |||
1604 | asihpi->mixer_level[addr][1] != right; | 1606 | asihpi->mixer_level[addr][1] != right; |
1605 | */ | 1607 | */ |
1606 | change = 1; | 1608 | change = 1; |
1607 | hpi_handle_error(hpi_level_set_gain(ss, h_control, an_gain_mB)); | 1609 | hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB)); |
1608 | return change; | 1610 | return change; |
1609 | } | 1611 | } |
1610 | 1612 | ||
@@ -1617,7 +1619,7 @@ static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi, | |||
1617 | struct snd_kcontrol_new snd_control; | 1619 | struct snd_kcontrol_new snd_control; |
1618 | 1620 | ||
1619 | /* can't use 'volume' cos some nodes have volume as well */ | 1621 | /* can't use 'volume' cos some nodes have volume as well */ |
1620 | asihpi_ctl_init(&snd_control, hpi_ctl, "level"); | 1622 | asihpi_ctl_init(&snd_control, hpi_ctl, "Level"); |
1621 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | | 1623 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | |
1622 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; | 1624 | SNDRV_CTL_ELEM_ACCESS_TLV_READ; |
1623 | snd_control.info = snd_asihpi_level_info; | 1625 | snd_control.info = snd_asihpi_level_info; |
@@ -1633,12 +1635,8 @@ static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi, | |||
1633 | ------------------------------------------------------------*/ | 1635 | ------------------------------------------------------------*/ |
1634 | 1636 | ||
1635 | /* AESEBU format */ | 1637 | /* AESEBU format */ |
1636 | static char *asihpi_aesebu_format_names[] = | 1638 | static const char * const asihpi_aesebu_format_names[] = { |
1637 | { | 1639 | "N/A", "S/PDIF", "AES/EBU" }; |
1638 | "N/A", | ||
1639 | "S/PDIF", | ||
1640 | "AES/EBU", | ||
1641 | }; | ||
1642 | 1640 | ||
1643 | static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, | 1641 | static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, |
1644 | struct snd_ctl_elem_info *uinfo) | 1642 | struct snd_ctl_elem_info *uinfo) |
@@ -1659,12 +1657,12 @@ static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol, | |||
1659 | 1657 | ||
1660 | static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, | 1658 | static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, |
1661 | struct snd_ctl_elem_value *ucontrol, | 1659 | struct snd_ctl_elem_value *ucontrol, |
1662 | u16 (*func)(const struct hpi_hsubsys *, u32, u16 *)) | 1660 | u16 (*func)(u32, u16 *)) |
1663 | { | 1661 | { |
1664 | u32 h_control = kcontrol->private_value; | 1662 | u32 h_control = kcontrol->private_value; |
1665 | u16 source, err; | 1663 | u16 source, err; |
1666 | 1664 | ||
1667 | err = func(ss, h_control, &source); | 1665 | err = func(h_control, &source); |
1668 | 1666 | ||
1669 | /* default to N/A */ | 1667 | /* default to N/A */ |
1670 | ucontrol->value.enumerated.item[0] = 0; | 1668 | ucontrol->value.enumerated.item[0] = 0; |
@@ -1681,7 +1679,7 @@ static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol, | |||
1681 | 1679 | ||
1682 | static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, | 1680 | static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, |
1683 | struct snd_ctl_elem_value *ucontrol, | 1681 | struct snd_ctl_elem_value *ucontrol, |
1684 | u16 (*func)(const struct hpi_hsubsys *, u32, u16)) | 1682 | u16 (*func)(u32, u16)) |
1685 | { | 1683 | { |
1686 | u32 h_control = kcontrol->private_value; | 1684 | u32 h_control = kcontrol->private_value; |
1687 | 1685 | ||
@@ -1693,7 +1691,7 @@ static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, | |||
1693 | if (ucontrol->value.enumerated.item[0] == 2) | 1691 | if (ucontrol->value.enumerated.item[0] == 2) |
1694 | source = HPI_AESEBU_FORMAT_AESEBU; | 1692 | source = HPI_AESEBU_FORMAT_AESEBU; |
1695 | 1693 | ||
1696 | if (func(ss, h_control, source) != 0) | 1694 | if (func(h_control, source) != 0) |
1697 | return -EINVAL; | 1695 | return -EINVAL; |
1698 | 1696 | ||
1699 | return 1; | 1697 | return 1; |
@@ -1702,13 +1700,13 @@ static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol, | |||
1702 | static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol, | 1700 | static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol, |
1703 | struct snd_ctl_elem_value *ucontrol) { | 1701 | struct snd_ctl_elem_value *ucontrol) { |
1704 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, | 1702 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, |
1705 | HPI_AESEBU__receiver_get_format); | 1703 | hpi_aesebu_receiver_get_format); |
1706 | } | 1704 | } |
1707 | 1705 | ||
1708 | static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol, | 1706 | static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol, |
1709 | struct snd_ctl_elem_value *ucontrol) { | 1707 | struct snd_ctl_elem_value *ucontrol) { |
1710 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, | 1708 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, |
1711 | HPI_AESEBU__receiver_set_format); | 1709 | hpi_aesebu_receiver_set_format); |
1712 | } | 1710 | } |
1713 | 1711 | ||
1714 | static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol, | 1712 | static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol, |
@@ -1730,8 +1728,8 @@ static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol, | |||
1730 | u32 h_control = kcontrol->private_value; | 1728 | u32 h_control = kcontrol->private_value; |
1731 | u16 status; | 1729 | u16 status; |
1732 | 1730 | ||
1733 | hpi_handle_error(HPI_AESEBU__receiver_get_error_status( | 1731 | hpi_handle_error(hpi_aesebu_receiver_get_error_status( |
1734 | ss, h_control, &status)); | 1732 | h_control, &status)); |
1735 | ucontrol->value.integer.value[0] = status; | 1733 | ucontrol->value.integer.value[0] = status; |
1736 | return 0; | 1734 | return 0; |
1737 | } | 1735 | } |
@@ -1742,7 +1740,7 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, | |||
1742 | struct snd_card *card = asihpi->card; | 1740 | struct snd_card *card = asihpi->card; |
1743 | struct snd_kcontrol_new snd_control; | 1741 | struct snd_kcontrol_new snd_control; |
1744 | 1742 | ||
1745 | asihpi_ctl_init(&snd_control, hpi_ctl, "format"); | 1743 | asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); |
1746 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 1744 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
1747 | snd_control.info = snd_asihpi_aesebu_format_info; | 1745 | snd_control.info = snd_asihpi_aesebu_format_info; |
1748 | snd_control.get = snd_asihpi_aesebu_rx_format_get; | 1746 | snd_control.get = snd_asihpi_aesebu_rx_format_get; |
@@ -1752,7 +1750,7 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, | |||
1752 | if (ctl_add(card, &snd_control, asihpi) < 0) | 1750 | if (ctl_add(card, &snd_control, asihpi) < 0) |
1753 | return -EINVAL; | 1751 | return -EINVAL; |
1754 | 1752 | ||
1755 | asihpi_ctl_init(&snd_control, hpi_ctl, "status"); | 1753 | asihpi_ctl_init(&snd_control, hpi_ctl, "Status"); |
1756 | snd_control.access = | 1754 | snd_control.access = |
1757 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; | 1755 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; |
1758 | snd_control.info = snd_asihpi_aesebu_rxstatus_info; | 1756 | snd_control.info = snd_asihpi_aesebu_rxstatus_info; |
@@ -1764,13 +1762,13 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi, | |||
1764 | static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol, | 1762 | static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol, |
1765 | struct snd_ctl_elem_value *ucontrol) { | 1763 | struct snd_ctl_elem_value *ucontrol) { |
1766 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, | 1764 | return snd_asihpi_aesebu_format_get(kcontrol, ucontrol, |
1767 | HPI_AESEBU__transmitter_get_format); | 1765 | hpi_aesebu_transmitter_get_format); |
1768 | } | 1766 | } |
1769 | 1767 | ||
1770 | static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol, | 1768 | static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol, |
1771 | struct snd_ctl_elem_value *ucontrol) { | 1769 | struct snd_ctl_elem_value *ucontrol) { |
1772 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, | 1770 | return snd_asihpi_aesebu_format_put(kcontrol, ucontrol, |
1773 | HPI_AESEBU__transmitter_set_format); | 1771 | hpi_aesebu_transmitter_set_format); |
1774 | } | 1772 | } |
1775 | 1773 | ||
1776 | 1774 | ||
@@ -1780,7 +1778,7 @@ static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi, | |||
1780 | struct snd_card *card = asihpi->card; | 1778 | struct snd_card *card = asihpi->card; |
1781 | struct snd_kcontrol_new snd_control; | 1779 | struct snd_kcontrol_new snd_control; |
1782 | 1780 | ||
1783 | asihpi_ctl_init(&snd_control, hpi_ctl, "format"); | 1781 | asihpi_ctl_init(&snd_control, hpi_ctl, "Format"); |
1784 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 1782 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
1785 | snd_control.info = snd_asihpi_aesebu_format_info; | 1783 | snd_control.info = snd_asihpi_aesebu_format_info; |
1786 | snd_control.get = snd_asihpi_aesebu_tx_format_get; | 1784 | snd_control.get = snd_asihpi_aesebu_tx_format_get; |
@@ -1804,7 +1802,7 @@ static int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol, | |||
1804 | u16 gain_range[3]; | 1802 | u16 gain_range[3]; |
1805 | 1803 | ||
1806 | for (idx = 0; idx < 3; idx++) { | 1804 | for (idx = 0; idx < 3; idx++) { |
1807 | err = hpi_tuner_query_gain(ss, h_control, | 1805 | err = hpi_tuner_query_gain(h_control, |
1808 | idx, &gain_range[idx]); | 1806 | idx, &gain_range[idx]); |
1809 | if (err != 0) | 1807 | if (err != 0) |
1810 | return err; | 1808 | return err; |
@@ -1827,7 +1825,7 @@ static int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol, | |||
1827 | u32 h_control = kcontrol->private_value; | 1825 | u32 h_control = kcontrol->private_value; |
1828 | short gain; | 1826 | short gain; |
1829 | 1827 | ||
1830 | hpi_handle_error(hpi_tuner_get_gain(ss, h_control, &gain)); | 1828 | hpi_handle_error(hpi_tuner_get_gain(h_control, &gain)); |
1831 | ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB; | 1829 | ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB; |
1832 | 1830 | ||
1833 | return 0; | 1831 | return 0; |
@@ -1843,7 +1841,7 @@ static int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol, | |||
1843 | short gain; | 1841 | short gain; |
1844 | 1842 | ||
1845 | gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; | 1843 | gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB; |
1846 | hpi_handle_error(hpi_tuner_set_gain(ss, h_control, gain)); | 1844 | hpi_handle_error(hpi_tuner_set_gain(h_control, gain)); |
1847 | 1845 | ||
1848 | return 1; | 1846 | return 1; |
1849 | } | 1847 | } |
@@ -1857,7 +1855,7 @@ static int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol, | |||
1857 | u32 i; | 1855 | u32 i; |
1858 | 1856 | ||
1859 | for (i = 0; i < len; i++) { | 1857 | for (i = 0; i < len; i++) { |
1860 | err = hpi_tuner_query_band(ss, | 1858 | err = hpi_tuner_query_band( |
1861 | h_control, i, &band_list[i]); | 1859 | h_control, i, &band_list[i]); |
1862 | if (err != 0) | 1860 | if (err != 0) |
1863 | break; | 1861 | break; |
@@ -1913,7 +1911,7 @@ static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol, | |||
1913 | num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, | 1911 | num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands, |
1914 | HPI_TUNER_BAND_LAST); | 1912 | HPI_TUNER_BAND_LAST); |
1915 | 1913 | ||
1916 | hpi_handle_error(hpi_tuner_get_band(ss, h_control, &band)); | 1914 | hpi_handle_error(hpi_tuner_get_band(h_control, &band)); |
1917 | 1915 | ||
1918 | ucontrol->value.enumerated.item[0] = -1; | 1916 | ucontrol->value.enumerated.item[0] = -1; |
1919 | for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++) | 1917 | for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++) |
@@ -1940,7 +1938,7 @@ static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol, | |||
1940 | HPI_TUNER_BAND_LAST); | 1938 | HPI_TUNER_BAND_LAST); |
1941 | 1939 | ||
1942 | band = tuner_bands[ucontrol->value.enumerated.item[0]]; | 1940 | band = tuner_bands[ucontrol->value.enumerated.item[0]]; |
1943 | hpi_handle_error(hpi_tuner_set_band(ss, h_control, band)); | 1941 | hpi_handle_error(hpi_tuner_set_band(h_control, band)); |
1944 | 1942 | ||
1945 | return 1; | 1943 | return 1; |
1946 | } | 1944 | } |
@@ -1965,7 +1963,7 @@ static int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol, | |||
1965 | 1963 | ||
1966 | for (band_iter = 0; band_iter < num_bands; band_iter++) { | 1964 | for (band_iter = 0; band_iter < num_bands; band_iter++) { |
1967 | for (idx = 0; idx < 3; idx++) { | 1965 | for (idx = 0; idx < 3; idx++) { |
1968 | err = hpi_tuner_query_frequency(ss, h_control, | 1966 | err = hpi_tuner_query_frequency(h_control, |
1969 | idx, tuner_bands[band_iter], | 1967 | idx, tuner_bands[band_iter], |
1970 | &temp_freq_range[idx]); | 1968 | &temp_freq_range[idx]); |
1971 | if (err != 0) | 1969 | if (err != 0) |
@@ -1998,7 +1996,7 @@ static int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol, | |||
1998 | u32 h_control = kcontrol->private_value; | 1996 | u32 h_control = kcontrol->private_value; |
1999 | u32 freq; | 1997 | u32 freq; |
2000 | 1998 | ||
2001 | hpi_handle_error(hpi_tuner_get_frequency(ss, h_control, &freq)); | 1999 | hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq)); |
2002 | ucontrol->value.integer.value[0] = freq; | 2000 | ucontrol->value.integer.value[0] = freq; |
2003 | 2001 | ||
2004 | return 0; | 2002 | return 0; |
@@ -2011,7 +2009,7 @@ static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol, | |||
2011 | u32 freq; | 2009 | u32 freq; |
2012 | 2010 | ||
2013 | freq = ucontrol->value.integer.value[0]; | 2011 | freq = ucontrol->value.integer.value[0]; |
2014 | hpi_handle_error(hpi_tuner_set_frequency(ss, h_control, freq)); | 2012 | hpi_handle_error(hpi_tuner_set_frequency(h_control, freq)); |
2015 | 2013 | ||
2016 | return 1; | 2014 | return 1; |
2017 | } | 2015 | } |
@@ -2026,8 +2024,8 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, | |||
2026 | snd_control.private_value = hpi_ctl->h_control; | 2024 | snd_control.private_value = hpi_ctl->h_control; |
2027 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 2025 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
2028 | 2026 | ||
2029 | if (!hpi_tuner_get_gain(ss, hpi_ctl->h_control, NULL)) { | 2027 | if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) { |
2030 | asihpi_ctl_init(&snd_control, hpi_ctl, "gain"); | 2028 | asihpi_ctl_init(&snd_control, hpi_ctl, "Gain"); |
2031 | snd_control.info = snd_asihpi_tuner_gain_info; | 2029 | snd_control.info = snd_asihpi_tuner_gain_info; |
2032 | snd_control.get = snd_asihpi_tuner_gain_get; | 2030 | snd_control.get = snd_asihpi_tuner_gain_get; |
2033 | snd_control.put = snd_asihpi_tuner_gain_put; | 2031 | snd_control.put = snd_asihpi_tuner_gain_put; |
@@ -2036,7 +2034,7 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, | |||
2036 | return -EINVAL; | 2034 | return -EINVAL; |
2037 | } | 2035 | } |
2038 | 2036 | ||
2039 | asihpi_ctl_init(&snd_control, hpi_ctl, "band"); | 2037 | asihpi_ctl_init(&snd_control, hpi_ctl, "Band"); |
2040 | snd_control.info = snd_asihpi_tuner_band_info; | 2038 | snd_control.info = snd_asihpi_tuner_band_info; |
2041 | snd_control.get = snd_asihpi_tuner_band_get; | 2039 | snd_control.get = snd_asihpi_tuner_band_get; |
2042 | snd_control.put = snd_asihpi_tuner_band_put; | 2040 | snd_control.put = snd_asihpi_tuner_band_put; |
@@ -2044,7 +2042,7 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi, | |||
2044 | if (ctl_add(card, &snd_control, asihpi) < 0) | 2042 | if (ctl_add(card, &snd_control, asihpi) < 0) |
2045 | return -EINVAL; | 2043 | return -EINVAL; |
2046 | 2044 | ||
2047 | asihpi_ctl_init(&snd_control, hpi_ctl, "freq"); | 2045 | asihpi_ctl_init(&snd_control, hpi_ctl, "Freq"); |
2048 | snd_control.info = snd_asihpi_tuner_freq_info; | 2046 | snd_control.info = snd_asihpi_tuner_freq_info; |
2049 | snd_control.get = snd_asihpi_tuner_freq_get; | 2047 | snd_control.get = snd_asihpi_tuner_freq_get; |
2050 | snd_control.put = snd_asihpi_tuner_freq_put; | 2048 | snd_control.put = snd_asihpi_tuner_freq_put; |
@@ -2095,7 +2093,7 @@ static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol, | |||
2095 | short an_gain_mB[HPI_MAX_CHANNELS], i; | 2093 | short an_gain_mB[HPI_MAX_CHANNELS], i; |
2096 | u16 err; | 2094 | u16 err; |
2097 | 2095 | ||
2098 | err = hpi_meter_get_peak(ss, h_control, an_gain_mB); | 2096 | err = hpi_meter_get_peak(h_control, an_gain_mB); |
2099 | 2097 | ||
2100 | for (i = 0; i < HPI_MAX_CHANNELS; i++) { | 2098 | for (i = 0; i < HPI_MAX_CHANNELS; i++) { |
2101 | if (err) { | 2099 | if (err) { |
@@ -2120,7 +2118,7 @@ static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi, | |||
2120 | struct snd_card *card = asihpi->card; | 2118 | struct snd_card *card = asihpi->card; |
2121 | struct snd_kcontrol_new snd_control; | 2119 | struct snd_kcontrol_new snd_control; |
2122 | 2120 | ||
2123 | asihpi_ctl_init(&snd_control, hpi_ctl, "meter"); | 2121 | asihpi_ctl_init(&snd_control, hpi_ctl, "Meter"); |
2124 | snd_control.access = | 2122 | snd_control.access = |
2125 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; | 2123 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; |
2126 | snd_control.info = snd_asihpi_meter_info; | 2124 | snd_control.info = snd_asihpi_meter_info; |
@@ -2140,7 +2138,7 @@ static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control) | |||
2140 | struct hpi_control hpi_ctl; | 2138 | struct hpi_control hpi_ctl; |
2141 | int s, err; | 2139 | int s, err; |
2142 | for (s = 0; s < 32; s++) { | 2140 | for (s = 0; s < 32; s++) { |
2143 | err = hpi_multiplexer_query_source(ss, h_control, s, | 2141 | err = hpi_multiplexer_query_source(h_control, s, |
2144 | &hpi_ctl. | 2142 | &hpi_ctl. |
2145 | src_node_type, | 2143 | src_node_type, |
2146 | &hpi_ctl. | 2144 | &hpi_ctl. |
@@ -2168,7 +2166,7 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol, | |||
2168 | uinfo->value.enumerated.items - 1; | 2166 | uinfo->value.enumerated.items - 1; |
2169 | 2167 | ||
2170 | err = | 2168 | err = |
2171 | hpi_multiplexer_query_source(ss, h_control, | 2169 | hpi_multiplexer_query_source(h_control, |
2172 | uinfo->value.enumerated.item, | 2170 | uinfo->value.enumerated.item, |
2173 | &src_node_type, &src_node_index); | 2171 | &src_node_type, &src_node_index); |
2174 | 2172 | ||
@@ -2186,11 +2184,11 @@ static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, | |||
2186 | u16 src_node_type, src_node_index; | 2184 | u16 src_node_type, src_node_index; |
2187 | int s; | 2185 | int s; |
2188 | 2186 | ||
2189 | hpi_handle_error(hpi_multiplexer_get_source(ss, h_control, | 2187 | hpi_handle_error(hpi_multiplexer_get_source(h_control, |
2190 | &source_type, &source_index)); | 2188 | &source_type, &source_index)); |
2191 | /* Should cache this search result! */ | 2189 | /* Should cache this search result! */ |
2192 | for (s = 0; s < 256; s++) { | 2190 | for (s = 0; s < 256; s++) { |
2193 | if (hpi_multiplexer_query_source(ss, h_control, s, | 2191 | if (hpi_multiplexer_query_source(h_control, s, |
2194 | &src_node_type, &src_node_index)) | 2192 | &src_node_type, &src_node_index)) |
2195 | break; | 2193 | break; |
2196 | 2194 | ||
@@ -2201,7 +2199,7 @@ static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol, | |||
2201 | } | 2199 | } |
2202 | } | 2200 | } |
2203 | snd_printd(KERN_WARNING | 2201 | snd_printd(KERN_WARNING |
2204 | "control %x failed to match mux source %hu %hu\n", | 2202 | "Control %x failed to match mux source %hu %hu\n", |
2205 | h_control, source_type, source_index); | 2203 | h_control, source_type, source_index); |
2206 | ucontrol->value.enumerated.item[0] = 0; | 2204 | ucontrol->value.enumerated.item[0] = 0; |
2207 | return 0; | 2205 | return 0; |
@@ -2217,12 +2215,12 @@ static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol, | |||
2217 | 2215 | ||
2218 | change = 1; | 2216 | change = 1; |
2219 | 2217 | ||
2220 | e = hpi_multiplexer_query_source(ss, h_control, | 2218 | e = hpi_multiplexer_query_source(h_control, |
2221 | ucontrol->value.enumerated.item[0], | 2219 | ucontrol->value.enumerated.item[0], |
2222 | &source_type, &source_index); | 2220 | &source_type, &source_index); |
2223 | if (!e) | 2221 | if (!e) |
2224 | hpi_handle_error( | 2222 | hpi_handle_error( |
2225 | hpi_multiplexer_set_source(ss, h_control, | 2223 | hpi_multiplexer_set_source(h_control, |
2226 | source_type, source_index)); | 2224 | source_type, source_index)); |
2227 | return change; | 2225 | return change; |
2228 | } | 2226 | } |
@@ -2234,11 +2232,7 @@ static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi, | |||
2234 | struct snd_card *card = asihpi->card; | 2232 | struct snd_card *card = asihpi->card; |
2235 | struct snd_kcontrol_new snd_control; | 2233 | struct snd_kcontrol_new snd_control; |
2236 | 2234 | ||
2237 | #if ASI_STYLE_NAMES | 2235 | asihpi_ctl_init(&snd_control, hpi_ctl, "Route"); |
2238 | asihpi_ctl_init(&snd_control, hpi_ctl, "multiplexer"); | ||
2239 | #else | ||
2240 | asihpi_ctl_init(&snd_control, hpi_ctl, "route"); | ||
2241 | #endif | ||
2242 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 2236 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
2243 | snd_control.info = snd_asihpi_mux_info; | 2237 | snd_control.info = snd_asihpi_mux_info; |
2244 | snd_control.get = snd_asihpi_mux_get; | 2238 | snd_control.get = snd_asihpi_mux_get; |
@@ -2254,33 +2248,38 @@ static int __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi, | |||
2254 | static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol, | 2248 | static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol, |
2255 | struct snd_ctl_elem_info *uinfo) | 2249 | struct snd_ctl_elem_info *uinfo) |
2256 | { | 2250 | { |
2257 | static char *mode_names[HPI_CHANNEL_MODE_LAST] = { | 2251 | static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = { |
2258 | "normal", "swap", | 2252 | "invalid", |
2259 | "from_left", "from_right", | 2253 | "Normal", "Swap", |
2260 | "to_left", "to_right" | 2254 | "From Left", "From Right", |
2255 | "To Left", "To Right" | ||
2261 | }; | 2256 | }; |
2262 | 2257 | ||
2263 | u32 h_control = kcontrol->private_value; | 2258 | u32 h_control = kcontrol->private_value; |
2264 | u16 mode; | 2259 | u16 mode; |
2265 | int i; | 2260 | int i; |
2261 | u16 mode_map[6]; | ||
2262 | int valid_modes = 0; | ||
2266 | 2263 | ||
2267 | /* HPI channel mode values can be from 1 to 6 | 2264 | /* HPI channel mode values can be from 1 to 6 |
2268 | Some adapters only support a contiguous subset | 2265 | Some adapters only support a contiguous subset |
2269 | */ | 2266 | */ |
2270 | for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++) | 2267 | for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++) |
2271 | if (hpi_channel_mode_query_mode( | 2268 | if (!hpi_channel_mode_query_mode( |
2272 | ss, h_control, i, &mode)) | 2269 | h_control, i, &mode)) { |
2273 | break; | 2270 | mode_map[valid_modes] = mode; |
2271 | valid_modes++; | ||
2272 | } | ||
2274 | 2273 | ||
2275 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2274 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2276 | uinfo->count = 1; | 2275 | uinfo->count = 1; |
2277 | uinfo->value.enumerated.items = i; | 2276 | uinfo->value.enumerated.items = valid_modes; |
2278 | 2277 | ||
2279 | if (uinfo->value.enumerated.item >= i) | 2278 | if (uinfo->value.enumerated.item >= valid_modes) |
2280 | uinfo->value.enumerated.item = i - 1; | 2279 | uinfo->value.enumerated.item = valid_modes - 1; |
2281 | 2280 | ||
2282 | strcpy(uinfo->value.enumerated.name, | 2281 | strcpy(uinfo->value.enumerated.name, |
2283 | mode_names[uinfo->value.enumerated.item]); | 2282 | mode_names[mode_map[uinfo->value.enumerated.item]]); |
2284 | 2283 | ||
2285 | return 0; | 2284 | return 0; |
2286 | } | 2285 | } |
@@ -2291,7 +2290,7 @@ static int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol, | |||
2291 | u32 h_control = kcontrol->private_value; | 2290 | u32 h_control = kcontrol->private_value; |
2292 | u16 mode; | 2291 | u16 mode; |
2293 | 2292 | ||
2294 | if (hpi_channel_mode_get(ss, h_control, &mode)) | 2293 | if (hpi_channel_mode_get(h_control, &mode)) |
2295 | mode = 1; | 2294 | mode = 1; |
2296 | 2295 | ||
2297 | ucontrol->value.enumerated.item[0] = mode - 1; | 2296 | ucontrol->value.enumerated.item[0] = mode - 1; |
@@ -2307,7 +2306,7 @@ static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol, | |||
2307 | 2306 | ||
2308 | change = 1; | 2307 | change = 1; |
2309 | 2308 | ||
2310 | hpi_handle_error(hpi_channel_mode_set(ss, h_control, | 2309 | hpi_handle_error(hpi_channel_mode_set(h_control, |
2311 | ucontrol->value.enumerated.item[0] + 1)); | 2310 | ucontrol->value.enumerated.item[0] + 1)); |
2312 | return change; | 2311 | return change; |
2313 | } | 2312 | } |
@@ -2319,7 +2318,7 @@ static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi, | |||
2319 | struct snd_card *card = asihpi->card; | 2318 | struct snd_card *card = asihpi->card; |
2320 | struct snd_kcontrol_new snd_control; | 2319 | struct snd_kcontrol_new snd_control; |
2321 | 2320 | ||
2322 | asihpi_ctl_init(&snd_control, hpi_ctl, "channel mode"); | 2321 | asihpi_ctl_init(&snd_control, hpi_ctl, "Mode"); |
2323 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | 2322 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; |
2324 | snd_control.info = snd_asihpi_cmode_info; | 2323 | snd_control.info = snd_asihpi_cmode_info; |
2325 | snd_control.get = snd_asihpi_cmode_get; | 2324 | snd_control.get = snd_asihpi_cmode_get; |
@@ -2331,15 +2330,12 @@ static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi, | |||
2331 | /*------------------------------------------------------------ | 2330 | /*------------------------------------------------------------ |
2332 | Sampleclock source controls | 2331 | Sampleclock source controls |
2333 | ------------------------------------------------------------*/ | 2332 | ------------------------------------------------------------*/ |
2334 | 2333 | static char *sampleclock_sources[MAX_CLOCKSOURCES] = { | |
2335 | static char *sampleclock_sources[MAX_CLOCKSOURCES] = | 2334 | "N/A", "Local PLL", "Digital Sync", "Word External", "Word Header", |
2336 | { "N/A", "local PLL", "AES/EBU sync", "word external", "word header", | 2335 | "SMPTE", "Digital1", "Auto", "Network", "Invalid", |
2337 | "SMPTE", "AES/EBU in1", "auto", "network", "invalid", | 2336 | "Prev Module", |
2338 | "prev module", | 2337 | "Digital2", "Digital3", "Digital4", "Digital5", |
2339 | "AES/EBU in2", "AES/EBU in3", "AES/EBU in4", "AES/EBU in5", | 2338 | "Digital6", "Digital7", "Digital8"}; |
2340 | "AES/EBU in6", "AES/EBU in7", "AES/EBU in8"}; | ||
2341 | |||
2342 | |||
2343 | 2339 | ||
2344 | static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol, | 2340 | static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol, |
2345 | struct snd_ctl_elem_info *uinfo) | 2341 | struct snd_ctl_elem_info *uinfo) |
@@ -2371,11 +2367,11 @@ static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol, | |||
2371 | int i; | 2367 | int i; |
2372 | 2368 | ||
2373 | ucontrol->value.enumerated.item[0] = 0; | 2369 | ucontrol->value.enumerated.item[0] = 0; |
2374 | if (hpi_sample_clock_get_source(ss, h_control, &source)) | 2370 | if (hpi_sample_clock_get_source(h_control, &source)) |
2375 | source = 0; | 2371 | source = 0; |
2376 | 2372 | ||
2377 | if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) | 2373 | if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) |
2378 | if (hpi_sample_clock_get_source_index(ss, h_control, &srcindex)) | 2374 | if (hpi_sample_clock_get_source_index(h_control, &srcindex)) |
2379 | srcindex = 0; | 2375 | srcindex = 0; |
2380 | 2376 | ||
2381 | for (i = 0; i < clkcache->count; i++) | 2377 | for (i = 0; i < clkcache->count; i++) |
@@ -2402,11 +2398,11 @@ static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol, | |||
2402 | if (item >= clkcache->count) | 2398 | if (item >= clkcache->count) |
2403 | item = clkcache->count-1; | 2399 | item = clkcache->count-1; |
2404 | 2400 | ||
2405 | hpi_handle_error(hpi_sample_clock_set_source(ss, | 2401 | hpi_handle_error(hpi_sample_clock_set_source( |
2406 | h_control, clkcache->s[item].source)); | 2402 | h_control, clkcache->s[item].source)); |
2407 | 2403 | ||
2408 | if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) | 2404 | if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT) |
2409 | hpi_handle_error(hpi_sample_clock_set_source_index(ss, | 2405 | hpi_handle_error(hpi_sample_clock_set_source_index( |
2410 | h_control, clkcache->s[item].index)); | 2406 | h_control, clkcache->s[item].index)); |
2411 | return change; | 2407 | return change; |
2412 | } | 2408 | } |
@@ -2434,7 +2430,7 @@ static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol, | |||
2434 | u32 rate; | 2430 | u32 rate; |
2435 | u16 e; | 2431 | u16 e; |
2436 | 2432 | ||
2437 | e = hpi_sample_clock_get_local_rate(ss, h_control, &rate); | 2433 | e = hpi_sample_clock_get_local_rate(h_control, &rate); |
2438 | if (!e) | 2434 | if (!e) |
2439 | ucontrol->value.integer.value[0] = rate; | 2435 | ucontrol->value.integer.value[0] = rate; |
2440 | else | 2436 | else |
@@ -2452,7 +2448,7 @@ static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol, | |||
2452 | asihpi->mixer_clkrate[addr][1] != right; | 2448 | asihpi->mixer_clkrate[addr][1] != right; |
2453 | */ | 2449 | */ |
2454 | change = 1; | 2450 | change = 1; |
2455 | hpi_handle_error(hpi_sample_clock_set_local_rate(ss, h_control, | 2451 | hpi_handle_error(hpi_sample_clock_set_local_rate(h_control, |
2456 | ucontrol->value.integer.value[0])); | 2452 | ucontrol->value.integer.value[0])); |
2457 | return change; | 2453 | return change; |
2458 | } | 2454 | } |
@@ -2476,7 +2472,7 @@ static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol, | |||
2476 | u32 rate; | 2472 | u32 rate; |
2477 | u16 e; | 2473 | u16 e; |
2478 | 2474 | ||
2479 | e = hpi_sample_clock_get_sample_rate(ss, h_control, &rate); | 2475 | e = hpi_sample_clock_get_sample_rate(h_control, &rate); |
2480 | if (!e) | 2476 | if (!e) |
2481 | ucontrol->value.integer.value[0] = rate; | 2477 | ucontrol->value.integer.value[0] = rate; |
2482 | else | 2478 | else |
@@ -2501,7 +2497,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2501 | clkcache->has_local = 0; | 2497 | clkcache->has_local = 0; |
2502 | 2498 | ||
2503 | for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) { | 2499 | for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) { |
2504 | if (hpi_sample_clock_query_source(ss, hSC, | 2500 | if (hpi_sample_clock_query_source(hSC, |
2505 | i, &source)) | 2501 | i, &source)) |
2506 | break; | 2502 | break; |
2507 | clkcache->s[i].source = source; | 2503 | clkcache->s[i].source = source; |
@@ -2515,7 +2511,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2515 | if (has_aes_in) | 2511 | if (has_aes_in) |
2516 | /* already will have picked up index 0 above */ | 2512 | /* already will have picked up index 0 above */ |
2517 | for (j = 1; j < 8; j++) { | 2513 | for (j = 1; j < 8; j++) { |
2518 | if (hpi_sample_clock_query_source_index(ss, hSC, | 2514 | if (hpi_sample_clock_query_source_index(hSC, |
2519 | j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT, | 2515 | j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT, |
2520 | &source)) | 2516 | &source)) |
2521 | break; | 2517 | break; |
@@ -2528,7 +2524,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2528 | } | 2524 | } |
2529 | clkcache->count = i; | 2525 | clkcache->count = i; |
2530 | 2526 | ||
2531 | asihpi_ctl_init(&snd_control, hpi_ctl, "source"); | 2527 | asihpi_ctl_init(&snd_control, hpi_ctl, "Source"); |
2532 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; | 2528 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; |
2533 | snd_control.info = snd_asihpi_clksrc_info; | 2529 | snd_control.info = snd_asihpi_clksrc_info; |
2534 | snd_control.get = snd_asihpi_clksrc_get; | 2530 | snd_control.get = snd_asihpi_clksrc_get; |
@@ -2538,7 +2534,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2538 | 2534 | ||
2539 | 2535 | ||
2540 | if (clkcache->has_local) { | 2536 | if (clkcache->has_local) { |
2541 | asihpi_ctl_init(&snd_control, hpi_ctl, "local_rate"); | 2537 | asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate"); |
2542 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; | 2538 | snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ; |
2543 | snd_control.info = snd_asihpi_clklocal_info; | 2539 | snd_control.info = snd_asihpi_clklocal_info; |
2544 | snd_control.get = snd_asihpi_clklocal_get; | 2540 | snd_control.get = snd_asihpi_clklocal_get; |
@@ -2549,7 +2545,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi, | |||
2549 | return -EINVAL; | 2545 | return -EINVAL; |
2550 | } | 2546 | } |
2551 | 2547 | ||
2552 | asihpi_ctl_init(&snd_control, hpi_ctl, "rate"); | 2548 | asihpi_ctl_init(&snd_control, hpi_ctl, "Rate"); |
2553 | snd_control.access = | 2549 | snd_control.access = |
2554 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; | 2550 | SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ; |
2555 | snd_control.info = snd_asihpi_clkrate_info; | 2551 | snd_control.info = snd_asihpi_clkrate_info; |
@@ -2571,10 +2567,10 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2571 | 2567 | ||
2572 | if (snd_BUG_ON(!asihpi)) | 2568 | if (snd_BUG_ON(!asihpi)) |
2573 | return -EINVAL; | 2569 | return -EINVAL; |
2574 | strcpy(card->mixername, "asihpi mixer"); | 2570 | strcpy(card->mixername, "Asihpi Mixer"); |
2575 | 2571 | ||
2576 | err = | 2572 | err = |
2577 | hpi_mixer_open(ss, asihpi->adapter_index, | 2573 | hpi_mixer_open(asihpi->adapter_index, |
2578 | &asihpi->h_mixer); | 2574 | &asihpi->h_mixer); |
2579 | hpi_handle_error(err); | 2575 | hpi_handle_error(err); |
2580 | if (err) | 2576 | if (err) |
@@ -2585,7 +2581,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2585 | 2581 | ||
2586 | for (idx = 0; idx < 2000; idx++) { | 2582 | for (idx = 0; idx < 2000; idx++) { |
2587 | err = hpi_mixer_get_control_by_index( | 2583 | err = hpi_mixer_get_control_by_index( |
2588 | ss, asihpi->h_mixer, | 2584 | asihpi->h_mixer, |
2589 | idx, | 2585 | idx, |
2590 | &hpi_ctl.src_node_type, | 2586 | &hpi_ctl.src_node_type, |
2591 | &hpi_ctl.src_node_index, | 2587 | &hpi_ctl.src_node_index, |
@@ -2597,7 +2593,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2597 | if (err == HPI_ERROR_CONTROL_DISABLED) { | 2593 | if (err == HPI_ERROR_CONTROL_DISABLED) { |
2598 | if (mixer_dump) | 2594 | if (mixer_dump) |
2599 | snd_printk(KERN_INFO | 2595 | snd_printk(KERN_INFO |
2600 | "disabled HPI control(%d)\n", | 2596 | "Disabled HPI Control(%d)\n", |
2601 | idx); | 2597 | idx); |
2602 | continue; | 2598 | continue; |
2603 | } else | 2599 | } else |
@@ -2662,7 +2658,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
2662 | default: | 2658 | default: |
2663 | if (mixer_dump) | 2659 | if (mixer_dump) |
2664 | snd_printk(KERN_INFO | 2660 | snd_printk(KERN_INFO |
2665 | "untranslated HPI control" | 2661 | "Untranslated HPI Control" |
2666 | "(%d) %d %d %d %d %d\n", | 2662 | "(%d) %d %d %d %d %d\n", |
2667 | idx, | 2663 | idx, |
2668 | hpi_ctl.control_type, | 2664 | hpi_ctl.control_type, |
@@ -2712,14 +2708,14 @@ snd_asihpi_proc_read(struct snd_info_entry *entry, | |||
2712 | version & 0x7, | 2708 | version & 0x7, |
2713 | ((version >> 13) * 100) + ((version >> 7) & 0x3f)); | 2709 | ((version >> 13) * 100) + ((version >> 7) & 0x3f)); |
2714 | 2710 | ||
2715 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 2711 | err = hpi_mixer_get_control(asihpi->h_mixer, |
2716 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 2712 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
2717 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 2713 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
2718 | 2714 | ||
2719 | if (!err) { | 2715 | if (!err) { |
2720 | err = hpi_sample_clock_get_sample_rate(ss, | 2716 | err = hpi_sample_clock_get_sample_rate( |
2721 | h_control, &rate); | 2717 | h_control, &rate); |
2722 | err += hpi_sample_clock_get_source(ss, h_control, &source); | 2718 | err += hpi_sample_clock_get_source(h_control, &source); |
2723 | 2719 | ||
2724 | if (!err) | 2720 | if (!err) |
2725 | snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n", | 2721 | snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n", |
@@ -2841,15 +2837,17 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2841 | if (err < 0) | 2837 | if (err < 0) |
2842 | return err; | 2838 | return err; |
2843 | snd_printk(KERN_WARNING | 2839 | snd_printk(KERN_WARNING |
2844 | "**** WARNING **** adapter index %d->ALSA index %d\n", | 2840 | "**** WARNING **** Adapter index %d->ALSA index %d\n", |
2845 | hpi_card->index, card->number); | 2841 | hpi_card->index, card->number); |
2846 | } | 2842 | } |
2847 | 2843 | ||
2844 | snd_card_set_dev(card, &pci_dev->dev); | ||
2845 | |||
2848 | asihpi = (struct snd_card_asihpi *) card->private_data; | 2846 | asihpi = (struct snd_card_asihpi *) card->private_data; |
2849 | asihpi->card = card; | 2847 | asihpi->card = card; |
2850 | asihpi->pci = hpi_card->pci; | 2848 | asihpi->pci = pci_dev; |
2851 | asihpi->adapter_index = hpi_card->index; | 2849 | asihpi->adapter_index = hpi_card->index; |
2852 | hpi_handle_error(hpi_adapter_get_info(ss, | 2850 | hpi_handle_error(hpi_adapter_get_info( |
2853 | asihpi->adapter_index, | 2851 | asihpi->adapter_index, |
2854 | &asihpi->num_outstreams, | 2852 | &asihpi->num_outstreams, |
2855 | &asihpi->num_instreams, | 2853 | &asihpi->num_instreams, |
@@ -2859,7 +2857,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2859 | version = asihpi->version; | 2857 | version = asihpi->version; |
2860 | snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d " | 2858 | snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d " |
2861 | "num_instreams=%d S/N=%d\n" | 2859 | "num_instreams=%d S/N=%d\n" |
2862 | "hw version %c%d DSP code version %03d\n", | 2860 | "Hw Version %c%d DSP code version %03d\n", |
2863 | asihpi->type, asihpi->adapter_index, | 2861 | asihpi->type, asihpi->adapter_index, |
2864 | asihpi->num_outstreams, | 2862 | asihpi->num_outstreams, |
2865 | asihpi->num_instreams, asihpi->serial_number, | 2863 | asihpi->num_instreams, asihpi->serial_number, |
@@ -2871,33 +2869,33 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2871 | if (pcm_substreams < asihpi->num_instreams) | 2869 | if (pcm_substreams < asihpi->num_instreams) |
2872 | pcm_substreams = asihpi->num_instreams; | 2870 | pcm_substreams = asihpi->num_instreams; |
2873 | 2871 | ||
2874 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2872 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2875 | HPI_ADAPTER_PROPERTY_CAPS1, | 2873 | HPI_ADAPTER_PROPERTY_CAPS1, |
2876 | NULL, &asihpi->support_grouping); | 2874 | NULL, &asihpi->support_grouping); |
2877 | if (err) | 2875 | if (err) |
2878 | asihpi->support_grouping = 0; | 2876 | asihpi->support_grouping = 0; |
2879 | 2877 | ||
2880 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2878 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2881 | HPI_ADAPTER_PROPERTY_CAPS2, | 2879 | HPI_ADAPTER_PROPERTY_CAPS2, |
2882 | &asihpi->support_mrx, NULL); | 2880 | &asihpi->support_mrx, NULL); |
2883 | if (err) | 2881 | if (err) |
2884 | asihpi->support_mrx = 0; | 2882 | asihpi->support_mrx = 0; |
2885 | 2883 | ||
2886 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2884 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2887 | HPI_ADAPTER_PROPERTY_INTERVAL, | 2885 | HPI_ADAPTER_PROPERTY_INTERVAL, |
2888 | NULL, &asihpi->update_interval_frames); | 2886 | NULL, &asihpi->update_interval_frames); |
2889 | if (err) | 2887 | if (err) |
2890 | asihpi->update_interval_frames = 512; | 2888 | asihpi->update_interval_frames = 512; |
2891 | 2889 | ||
2892 | hpi_handle_error(hpi_instream_open(ss, asihpi->adapter_index, | 2890 | hpi_handle_error(hpi_instream_open(asihpi->adapter_index, |
2893 | 0, &h_stream)); | 2891 | 0, &h_stream)); |
2894 | 2892 | ||
2895 | err = hpi_instream_host_buffer_free(ss, h_stream); | 2893 | err = hpi_instream_host_buffer_free(h_stream); |
2896 | asihpi->support_mmap = (!err); | 2894 | asihpi->support_mmap = (!err); |
2897 | 2895 | ||
2898 | hpi_handle_error(hpi_instream_close(ss, h_stream)); | 2896 | hpi_handle_error(hpi_instream_close(h_stream)); |
2899 | 2897 | ||
2900 | err = hpi_adapter_get_property(ss, asihpi->adapter_index, | 2898 | err = hpi_adapter_get_property(asihpi->adapter_index, |
2901 | HPI_ADAPTER_PROPERTY_CURCHANNELS, | 2899 | HPI_ADAPTER_PROPERTY_CURCHANNELS, |
2902 | &asihpi->in_max_chans, &asihpi->out_max_chans); | 2900 | &asihpi->in_max_chans, &asihpi->out_max_chans); |
2903 | if (err) { | 2901 | if (err) { |
@@ -2923,13 +2921,13 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev, | |||
2923 | goto __nodev; | 2921 | goto __nodev; |
2924 | } | 2922 | } |
2925 | 2923 | ||
2926 | err = hpi_mixer_get_control(ss, asihpi->h_mixer, | 2924 | err = hpi_mixer_get_control(asihpi->h_mixer, |
2927 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, | 2925 | HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, |
2928 | HPI_CONTROL_SAMPLECLOCK, &h_control); | 2926 | HPI_CONTROL_SAMPLECLOCK, &h_control); |
2929 | 2927 | ||
2930 | if (!err) | 2928 | if (!err) |
2931 | err = hpi_sample_clock_set_local_rate( | 2929 | err = hpi_sample_clock_set_local_rate( |
2932 | ss, h_control, adapter_fs); | 2930 | h_control, adapter_fs); |
2933 | 2931 | ||
2934 | snd_asihpi_proc_init(asihpi); | 2932 | snd_asihpi_proc_init(asihpi); |
2935 | 2933 | ||
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h index 23399d02f666..6fc025c448de 100644 --- a/sound/pci/asihpi/hpi.h +++ b/sound/pci/asihpi/hpi.h | |||
@@ -24,17 +24,10 @@ | |||
24 | 24 | ||
25 | The HPI is a low-level hardware abstraction layer to all | 25 | The HPI is a low-level hardware abstraction layer to all |
26 | AudioScience digital audio adapters | 26 | AudioScience digital audio adapters |
27 | */ | ||
28 | /* | ||
29 | You must define one operating system that the HPI is to be compiled under | ||
30 | HPI_OS_WIN32_USER 32bit Windows | ||
31 | HPI_OS_DSP_C6000 DSP TI C6000 (automatically set) | ||
32 | HPI_OS_WDM Windows WDM kernel driver | ||
33 | HPI_OS_LINUX Linux userspace | ||
34 | HPI_OS_LINUX_KERNEL Linux kernel (automatically set) | ||
35 | 27 | ||
36 | (C) Copyright AudioScience Inc. 1998-2010 | 28 | (C) Copyright AudioScience Inc. 1998-2010 |
37 | ******************************************************************************/ | 29 | */ |
30 | |||
38 | #ifndef _HPI_H_ | 31 | #ifndef _HPI_H_ |
39 | #define _HPI_H_ | 32 | #define _HPI_H_ |
40 | /* HPI Version | 33 | /* HPI Version |
@@ -50,20 +43,20 @@ i.e 3.05.02 is a development version | |||
50 | #define HPI_VER_RELEASE(v) ((int)(v & 0xFF)) | 43 | #define HPI_VER_RELEASE(v) ((int)(v & 0xFF)) |
51 | 44 | ||
52 | /* Use single digits for versions less that 10 to avoid octal. */ | 45 | /* Use single digits for versions less that 10 to avoid octal. */ |
53 | #define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 4, 1) | 46 | #define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 6, 0) |
54 | #define HPI_VER_STRING "4.04.01" | 47 | #define HPI_VER_STRING "4.06.00" |
55 | 48 | ||
56 | /* Library version as documented in hpi-api-versions.txt */ | 49 | /* Library version as documented in hpi-api-versions.txt */ |
57 | #define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0) | 50 | #define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(9, 0, 0) |
58 | 51 | ||
59 | #include <linux/types.h> | 52 | #include <linux/types.h> |
60 | #define HPI_EXCLUDE_DEPRECATED | 53 | #define HPI_BUILD_EXCLUDE_DEPRECATED |
54 | #define HPI_BUILD_KERNEL_MODE | ||
61 | 55 | ||
62 | /******************************************************************************/ | 56 | /******************************************************************************/ |
63 | /******************************************************************************/ | ||
64 | /******** HPI API DEFINITIONS *****/ | 57 | /******** HPI API DEFINITIONS *****/ |
65 | /******************************************************************************/ | 58 | /******************************************************************************/ |
66 | /******************************************************************************/ | 59 | |
67 | /*******************************************/ | 60 | /*******************************************/ |
68 | /** Audio format types | 61 | /** Audio format types |
69 | \ingroup stream | 62 | \ingroup stream |
@@ -174,7 +167,6 @@ The range is +1.0 to -1.0, which corresponds to digital fullscale. | |||
174 | HPI_FORMAT_UNDEFINED = 0xffff | 167 | HPI_FORMAT_UNDEFINED = 0xffff |
175 | }; | 168 | }; |
176 | 169 | ||
177 | /******************************************* in/out Stream states */ | ||
178 | /*******************************************/ | 170 | /*******************************************/ |
179 | /** Stream States | 171 | /** Stream States |
180 | \ingroup stream | 172 | \ingroup stream |
@@ -194,7 +186,7 @@ enum HPI_STREAM_STATES { | |||
194 | cards to be ready. */ | 186 | cards to be ready. */ |
195 | HPI_STATE_WAIT = 6 | 187 | HPI_STATE_WAIT = 6 |
196 | }; | 188 | }; |
197 | /******************************************* mixer source node types */ | 189 | /*******************************************/ |
198 | /** Source node types | 190 | /** Source node types |
199 | \ingroup mixer | 191 | \ingroup mixer |
200 | */ | 192 | */ |
@@ -224,7 +216,7 @@ enum HPI_SOURCENODES { | |||
224 | /* AX6 max sourcenode types = 15 */ | 216 | /* AX6 max sourcenode types = 15 */ |
225 | }; | 217 | }; |
226 | 218 | ||
227 | /******************************************* mixer dest node types */ | 219 | /*******************************************/ |
228 | /** Destination node types | 220 | /** Destination node types |
229 | \ingroup mixer | 221 | \ingroup mixer |
230 | */ | 222 | */ |
@@ -262,11 +254,11 @@ enum HPI_CONTROLS { | |||
262 | HPI_CONTROL_MUTE = 4, /*mute control - not used at present. */ | 254 | HPI_CONTROL_MUTE = 4, /*mute control - not used at present. */ |
263 | HPI_CONTROL_MULTIPLEXER = 5, /**< multiplexer control. */ | 255 | HPI_CONTROL_MULTIPLEXER = 5, /**< multiplexer control. */ |
264 | 256 | ||
265 | HPI_CONTROL_AESEBU_TRANSMITTER = 6, /**< AES/EBU transmitter control. */ | 257 | HPI_CONTROL_AESEBU_TRANSMITTER = 6, /**< AES/EBU transmitter control */ |
266 | HPI_CONTROL_AESEBUTX = HPI_CONTROL_AESEBU_TRANSMITTER, | 258 | HPI_CONTROL_AESEBUTX = 6, /* HPI_CONTROL_AESEBU_TRANSMITTER */ |
267 | 259 | ||
268 | HPI_CONTROL_AESEBU_RECEIVER = 7, /**< AES/EBU receiver control. */ | 260 | HPI_CONTROL_AESEBU_RECEIVER = 7, /**< AES/EBU receiver control. */ |
269 | HPI_CONTROL_AESEBURX = HPI_CONTROL_AESEBU_RECEIVER, | 261 | HPI_CONTROL_AESEBURX = 7, /* HPI_CONTROL_AESEBU_RECEIVER */ |
270 | 262 | ||
271 | HPI_CONTROL_LEVEL = 8, /**< level/trim control - works in d_bu. */ | 263 | HPI_CONTROL_LEVEL = 8, /**< level/trim control - works in d_bu. */ |
272 | HPI_CONTROL_TUNER = 9, /**< tuner control. */ | 264 | HPI_CONTROL_TUNER = 9, /**< tuner control. */ |
@@ -281,7 +273,7 @@ enum HPI_CONTROLS { | |||
281 | HPI_CONTROL_SAMPLECLOCK = 17, /**< sample clock control. */ | 273 | HPI_CONTROL_SAMPLECLOCK = 17, /**< sample clock control. */ |
282 | HPI_CONTROL_MICROPHONE = 18, /**< microphone control. */ | 274 | HPI_CONTROL_MICROPHONE = 18, /**< microphone control. */ |
283 | HPI_CONTROL_PARAMETRIC_EQ = 19, /**< parametric EQ control. */ | 275 | HPI_CONTROL_PARAMETRIC_EQ = 19, /**< parametric EQ control. */ |
284 | HPI_CONTROL_EQUALIZER = HPI_CONTROL_PARAMETRIC_EQ, | 276 | HPI_CONTROL_EQUALIZER = 19, /*HPI_CONTROL_PARAMETRIC_EQ */ |
285 | 277 | ||
286 | HPI_CONTROL_COMPANDER = 20, /**< compander control. */ | 278 | HPI_CONTROL_COMPANDER = 20, /**< compander control. */ |
287 | HPI_CONTROL_COBRANET = 21, /**< cobranet control. */ | 279 | HPI_CONTROL_COBRANET = 21, /**< cobranet control. */ |
@@ -296,10 +288,7 @@ enum HPI_CONTROLS { | |||
296 | /* WARNING types 256 or greater impact bit packing in all AX6 DSP code */ | 288 | /* WARNING types 256 or greater impact bit packing in all AX6 DSP code */ |
297 | }; | 289 | }; |
298 | 290 | ||
299 | /* Shorthand names that match attribute names */ | 291 | /*******************************************/ |
300 | |||
301 | /******************************************* ADAPTER ATTRIBUTES ****/ | ||
302 | |||
303 | /** Adapter properties | 292 | /** Adapter properties |
304 | These are used in HPI_AdapterSetProperty() and HPI_AdapterGetProperty() | 293 | These are used in HPI_AdapterSetProperty() and HPI_AdapterGetProperty() |
305 | \ingroup adapter | 294 | \ingroup adapter |
@@ -330,12 +319,21 @@ by the driver and is not passed on to the DSP at all. | |||
330 | Indicates the state of the adapter's SSX2 setting. This setting is stored in | 319 | Indicates the state of the adapter's SSX2 setting. This setting is stored in |
331 | non-volatile memory on the adapter. A typical call sequence would be to use | 320 | non-volatile memory on the adapter. A typical call sequence would be to use |
332 | HPI_ADAPTER_PROPERTY_SSX2_SETTING to set SSX2 on the adapter and then to reload | 321 | HPI_ADAPTER_PROPERTY_SSX2_SETTING to set SSX2 on the adapter and then to reload |
333 | the driver. The driver would query HPI_ADAPTER_PROPERTY_SSX2_SETTING during startup | 322 | the driver. The driver would query HPI_ADAPTER_PROPERTY_SSX2_SETTING during |
334 | and if SSX2 is set, it would then call HPI_ADAPTER_PROPERTY_ENABLE_SSX2 to enable | 323 | startup and if SSX2 is set, it would then call HPI_ADAPTER_PROPERTY_ENABLE_SSX2 |
335 | SSX2 stream mapping within the kernel level of the driver. | 324 | to enable SSX2 stream mapping within the kernel level of the driver. |
336 | */ | 325 | */ |
337 | HPI_ADAPTER_PROPERTY_SSX2_SETTING = 4, | 326 | HPI_ADAPTER_PROPERTY_SSX2_SETTING = 4, |
338 | 327 | ||
328 | /** Enables/disables PCI(e) IRQ. | ||
329 | A setting of 0 indicates that no interrupts are being generated. A DSP boot | ||
330 | this property is set to 0. Setting to a non-zero value specifies the number | ||
331 | of frames of audio that should be processed between interrupts. This property | ||
332 | should be set to multiple of the mixer interval as read back from the | ||
333 | HPI_ADAPTER_PROPERTY_INTERVAL property. | ||
334 | */ | ||
335 | HPI_ADAPTER_PROPERTY_IRQ_RATE = 5, | ||
336 | |||
339 | /** Base number for readonly properties */ | 337 | /** Base number for readonly properties */ |
340 | HPI_ADAPTER_PROPERTY_READONLYBASE = 256, | 338 | HPI_ADAPTER_PROPERTY_READONLYBASE = 256, |
341 | 339 | ||
@@ -440,21 +438,30 @@ return value is true (1) or false (0). If the current adapter | |||
440 | mode is MONO SSX2 is disabled, even though this property will | 438 | mode is MONO SSX2 is disabled, even though this property will |
441 | return true. | 439 | return true. |
442 | */ | 440 | */ |
443 | HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271 | 441 | HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271, |
442 | /** Readonly supports PCI(e) IRQ. | ||
443 | Indicates that the adapter in it's current mode supports interrupts | ||
444 | across the host bus. Note, this does not imply that interrupts are | ||
445 | enabled. Instead it indicates that they can be enabled. | ||
446 | */ | ||
447 | HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ = 272 | ||
444 | }; | 448 | }; |
445 | 449 | ||
446 | /** Adapter mode commands | 450 | /** Adapter mode commands |
447 | 451 | ||
448 | Used in wQueryOrSet field of HPI_AdapterSetModeEx(). | 452 | Used in wQueryOrSet parameter of HPI_AdapterSetModeEx(). |
449 | \ingroup adapter | 453 | \ingroup adapter |
450 | */ | 454 | */ |
451 | enum HPI_ADAPTER_MODE_CMDS { | 455 | enum HPI_ADAPTER_MODE_CMDS { |
456 | /** Set the mode to the given parameter */ | ||
452 | HPI_ADAPTER_MODE_SET = 0, | 457 | HPI_ADAPTER_MODE_SET = 0, |
458 | /** Return 0 or error depending whether mode is valid, | ||
459 | but don't set the mode */ | ||
453 | HPI_ADAPTER_MODE_QUERY = 1 | 460 | HPI_ADAPTER_MODE_QUERY = 1 |
454 | }; | 461 | }; |
455 | 462 | ||
456 | /** Adapter Modes | 463 | /** Adapter Modes |
457 | These are used by HPI_AdapterSetModeEx() | 464 | These are used by HPI_AdapterSetModeEx() |
458 | 465 | ||
459 | \warning - more than 16 possible modes breaks | 466 | \warning - more than 16 possible modes breaks |
460 | a bitmask in the Windows WAVE DLL | 467 | a bitmask in the Windows WAVE DLL |
@@ -629,10 +636,13 @@ enum HPI_MIXER_STORE_COMMAND { | |||
629 | HPI_MIXER_STORE_SAVE_SINGLE = 6 | 636 | HPI_MIXER_STORE_SAVE_SINGLE = 6 |
630 | }; | 637 | }; |
631 | 638 | ||
632 | /************************************* CONTROL ATTRIBUTE VALUES ****/ | 639 | /****************************/ |
640 | /* CONTROL ATTRIBUTE VALUES */ | ||
641 | /****************************/ | ||
642 | |||
633 | /** Used by mixer plugin enable functions | 643 | /** Used by mixer plugin enable functions |
634 | 644 | ||
635 | E.g. HPI_ParametricEQ_SetState() | 645 | E.g. HPI_ParametricEq_SetState() |
636 | \ingroup mixer | 646 | \ingroup mixer |
637 | */ | 647 | */ |
638 | enum HPI_SWITCH_STATES { | 648 | enum HPI_SWITCH_STATES { |
@@ -641,6 +651,7 @@ enum HPI_SWITCH_STATES { | |||
641 | }; | 651 | }; |
642 | 652 | ||
643 | /* Volume control special gain values */ | 653 | /* Volume control special gain values */ |
654 | |||
644 | /** volumes units are 100ths of a dB | 655 | /** volumes units are 100ths of a dB |
645 | \ingroup volume | 656 | \ingroup volume |
646 | */ | 657 | */ |
@@ -650,6 +661,11 @@ enum HPI_SWITCH_STATES { | |||
650 | */ | 661 | */ |
651 | #define HPI_GAIN_OFF (-100 * HPI_UNITS_PER_dB) | 662 | #define HPI_GAIN_OFF (-100 * HPI_UNITS_PER_dB) |
652 | 663 | ||
664 | /** channel mask specifying all channels | ||
665 | \ingroup volume | ||
666 | */ | ||
667 | #define HPI_BITMASK_ALL_CHANNELS (0xFFFFFFFF) | ||
668 | |||
653 | /** value returned for no signal | 669 | /** value returned for no signal |
654 | \ingroup meter | 670 | \ingroup meter |
655 | */ | 671 | */ |
@@ -667,7 +683,7 @@ enum HPI_VOLUME_AUTOFADES { | |||
667 | 683 | ||
668 | /** The physical encoding format of the AESEBU I/O. | 684 | /** The physical encoding format of the AESEBU I/O. |
669 | 685 | ||
670 | Used in HPI_AESEBU_Transmitter_SetFormat(), HPI_AESEBU_Receiver_SetFormat() | 686 | Used in HPI_Aesebu_Transmitter_SetFormat(), HPI_Aesebu_Receiver_SetFormat() |
671 | along with related Get and Query functions | 687 | along with related Get and Query functions |
672 | \ingroup aestx | 688 | \ingroup aestx |
673 | */ | 689 | */ |
@@ -680,7 +696,7 @@ enum HPI_AESEBU_FORMATS { | |||
680 | 696 | ||
681 | /** AES/EBU error status bits | 697 | /** AES/EBU error status bits |
682 | 698 | ||
683 | Returned by HPI_AESEBU_Receiver_GetErrorStatus() | 699 | Returned by HPI_Aesebu_Receiver_GetErrorStatus() |
684 | \ingroup aesrx | 700 | \ingroup aesrx |
685 | */ | 701 | */ |
686 | enum HPI_AESEBU_ERRORS { | 702 | enum HPI_AESEBU_ERRORS { |
@@ -767,14 +783,6 @@ enum HPI_TUNER_MODE_VALUES { | |||
767 | HPI_TUNER_MODE_RDS_RBDS = 2 /**< RDS - RBDS mode */ | 783 | HPI_TUNER_MODE_RDS_RBDS = 2 /**< RDS - RBDS mode */ |
768 | }; | 784 | }; |
769 | 785 | ||
770 | /** Tuner Level settings | ||
771 | \ingroup tuner | ||
772 | */ | ||
773 | enum HPI_TUNER_LEVEL { | ||
774 | HPI_TUNER_LEVEL_AVERAGE = 0, | ||
775 | HPI_TUNER_LEVEL_RAW = 1 | ||
776 | }; | ||
777 | |||
778 | /** Tuner Status Bits | 786 | /** Tuner Status Bits |
779 | 787 | ||
780 | These bitfield values are returned by a call to HPI_Tuner_GetStatus(). | 788 | These bitfield values are returned by a call to HPI_Tuner_GetStatus(). |
@@ -783,13 +791,13 @@ Multiple fields are returned from a single call. | |||
783 | */ | 791 | */ |
784 | enum HPI_TUNER_STATUS_BITS { | 792 | enum HPI_TUNER_STATUS_BITS { |
785 | HPI_TUNER_VIDEO_COLOR_PRESENT = 0x0001, /**< video color is present. */ | 793 | HPI_TUNER_VIDEO_COLOR_PRESENT = 0x0001, /**< video color is present. */ |
786 | HPI_TUNER_VIDEO_IS_60HZ = 0x0020, /**< 60 hz video detected. */ | 794 | HPI_TUNER_VIDEO_IS_60HZ = 0x0020, /**< 60 hz video detected. */ |
787 | HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040, /**< video HSYNC is missing. */ | 795 | HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040, /**< video HSYNC is missing. */ |
788 | HPI_TUNER_VIDEO_STATUS_VALID = 0x0100, /**< video status is valid. */ | 796 | HPI_TUNER_VIDEO_STATUS_VALID = 0x0100, /**< video status is valid. */ |
789 | HPI_TUNER_PLL_LOCKED = 0x1000, /**< the tuner's PLL is locked. */ | 797 | HPI_TUNER_DIGITAL = 0x0200, /**< tuner reports digital programming. */ |
790 | HPI_TUNER_FM_STEREO = 0x2000, /**< tuner reports back FM stereo. */ | 798 | HPI_TUNER_MULTIPROGRAM = 0x0400, /**< tuner reports multiple programs. */ |
791 | HPI_TUNER_DIGITAL = 0x0200, /**< tuner reports digital programming. */ | 799 | HPI_TUNER_PLL_LOCKED = 0x1000, /**< the tuner's PLL is locked. */ |
792 | HPI_TUNER_MULTIPROGRAM = 0x0400 /**< tuner reports multiple programs. */ | 800 | HPI_TUNER_FM_STEREO = 0x2000 /**< tuner reports back FM stereo. */ |
793 | }; | 801 | }; |
794 | 802 | ||
795 | /** Channel Modes | 803 | /** Channel Modes |
@@ -839,7 +847,7 @@ enum HPI_SAMPLECLOCK_SOURCES { | |||
839 | HPI_SAMPLECLOCK_SOURCE_LAST = 10 | 847 | HPI_SAMPLECLOCK_SOURCE_LAST = 10 |
840 | }; | 848 | }; |
841 | 849 | ||
842 | /** Equalizer filter types. Used by HPI_ParametricEQ_SetBand() | 850 | /** Equalizer filter types. Used by HPI_ParametricEq_SetBand() |
843 | \ingroup parmeq | 851 | \ingroup parmeq |
844 | */ | 852 | */ |
845 | enum HPI_FILTER_TYPE { | 853 | enum HPI_FILTER_TYPE { |
@@ -882,7 +890,7 @@ enum HPI_ERROR_CODES { | |||
882 | HPI_ERROR_INVALID_OBJ = 101, | 890 | HPI_ERROR_INVALID_OBJ = 101, |
883 | /** Function does not exist. */ | 891 | /** Function does not exist. */ |
884 | HPI_ERROR_INVALID_FUNC = 102, | 892 | HPI_ERROR_INVALID_FUNC = 102, |
885 | /** The specified object (adapter/Stream) does not exist. */ | 893 | /** The specified object does not exist. */ |
886 | HPI_ERROR_INVALID_OBJ_INDEX = 103, | 894 | HPI_ERROR_INVALID_OBJ_INDEX = 103, |
887 | /** Trying to access an object that has not been opened yet. */ | 895 | /** Trying to access an object that has not been opened yet. */ |
888 | HPI_ERROR_OBJ_NOT_OPEN = 104, | 896 | HPI_ERROR_OBJ_NOT_OPEN = 104, |
@@ -890,8 +898,7 @@ enum HPI_ERROR_CODES { | |||
890 | HPI_ERROR_OBJ_ALREADY_OPEN = 105, | 898 | HPI_ERROR_OBJ_ALREADY_OPEN = 105, |
891 | /** PCI, ISA resource not valid. */ | 899 | /** PCI, ISA resource not valid. */ |
892 | HPI_ERROR_INVALID_RESOURCE = 106, | 900 | HPI_ERROR_INVALID_RESOURCE = 106, |
893 | /** GetInfo call from SubSysFindAdapters failed. */ | 901 | /* HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO= 107 */ |
894 | HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO = 107, | ||
895 | /** Default response was never updated with actual error code. */ | 902 | /** Default response was never updated with actual error code. */ |
896 | HPI_ERROR_INVALID_RESPONSE = 108, | 903 | HPI_ERROR_INVALID_RESPONSE = 108, |
897 | /** wSize field of response was not updated, | 904 | /** wSize field of response was not updated, |
@@ -899,38 +906,44 @@ enum HPI_ERROR_CODES { | |||
899 | HPI_ERROR_PROCESSING_MESSAGE = 109, | 906 | HPI_ERROR_PROCESSING_MESSAGE = 109, |
900 | /** The network did not respond in a timely manner. */ | 907 | /** The network did not respond in a timely manner. */ |
901 | HPI_ERROR_NETWORK_TIMEOUT = 110, | 908 | HPI_ERROR_NETWORK_TIMEOUT = 110, |
902 | /** An HPI handle is invalid (uninitialised?). */ | 909 | /* An HPI handle is invalid (uninitialised?). */ |
903 | HPI_ERROR_INVALID_HANDLE = 111, | 910 | HPI_ERROR_INVALID_HANDLE = 111, |
904 | /** A function or attribute has not been implemented yet. */ | 911 | /** A function or attribute has not been implemented yet. */ |
905 | HPI_ERROR_UNIMPLEMENTED = 112, | 912 | HPI_ERROR_UNIMPLEMENTED = 112, |
906 | /** There are too many clients attempting to access a network resource. */ | 913 | /** There are too many clients attempting |
914 | to access a network resource. */ | ||
907 | HPI_ERROR_NETWORK_TOO_MANY_CLIENTS = 113, | 915 | HPI_ERROR_NETWORK_TOO_MANY_CLIENTS = 113, |
908 | /** Response buffer passed to HPI_Message was smaller than returned response */ | 916 | /** Response buffer passed to HPI_Message |
917 | was smaller than returned response. | ||
918 | wSpecificError field of hpi response contains the required size. | ||
919 | */ | ||
909 | HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL = 114, | 920 | HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL = 114, |
910 | /** The returned response did not match the sent message */ | 921 | /** The returned response did not match the sent message */ |
911 | HPI_ERROR_RESPONSE_MISMATCH = 115, | 922 | HPI_ERROR_RESPONSE_MISMATCH = 115, |
923 | /** A control setting that should have been cached was not. */ | ||
924 | HPI_ERROR_CONTROL_CACHING = 116, | ||
925 | /** A message buffer in the path to the adapter was smaller | ||
926 | than the message size. | ||
927 | wSpecificError field of hpi response contains the actual size. | ||
928 | */ | ||
929 | HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL = 117, | ||
912 | 930 | ||
913 | /** Too many adapters.*/ | 931 | /* HPI_ERROR_TOO_MANY_ADAPTERS= 200 */ |
914 | HPI_ERROR_TOO_MANY_ADAPTERS = 200, | ||
915 | /** Bad adpater. */ | 932 | /** Bad adpater. */ |
916 | HPI_ERROR_BAD_ADAPTER = 201, | 933 | HPI_ERROR_BAD_ADAPTER = 201, |
917 | /** Adapter number out of range or not set properly. */ | 934 | /** Adapter number out of range or not set properly. */ |
918 | HPI_ERROR_BAD_ADAPTER_NUMBER = 202, | 935 | HPI_ERROR_BAD_ADAPTER_NUMBER = 202, |
919 | /** 2 adapters with the same adapter number. */ | 936 | /** 2 adapters with the same adapter number. */ |
920 | HPI_DUPLICATE_ADAPTER_NUMBER = 203, | 937 | HPI_ERROR_DUPLICATE_ADAPTER_NUMBER = 203, |
921 | /** DSP code failed to bootload. */ | 938 | /** DSP code failed to bootload. (unused?) */ |
922 | HPI_ERROR_DSP_BOOTLOAD = 204, | 939 | HPI_ERROR_DSP_BOOTLOAD = 204, |
923 | /** Adapter failed DSP code self test. */ | ||
924 | HPI_ERROR_DSP_SELFTEST = 205, | ||
925 | /** Couldn't find or open the DSP code file. */ | 940 | /** Couldn't find or open the DSP code file. */ |
926 | HPI_ERROR_DSP_FILE_NOT_FOUND = 206, | 941 | HPI_ERROR_DSP_FILE_NOT_FOUND = 206, |
927 | /** Internal DSP hardware error. */ | 942 | /** Internal DSP hardware error. */ |
928 | HPI_ERROR_DSP_HARDWARE = 207, | 943 | HPI_ERROR_DSP_HARDWARE = 207, |
929 | /** Could not allocate memory in DOS. */ | ||
930 | HPI_ERROR_DOS_MEMORY_ALLOC = 208, | ||
931 | /** Could not allocate memory */ | 944 | /** Could not allocate memory */ |
932 | HPI_ERROR_MEMORY_ALLOC = 208, | 945 | HPI_ERROR_MEMORY_ALLOC = 208, |
933 | /** Failed to correctly load/config PLD .*/ | 946 | /** Failed to correctly load/config PLD. (unused) */ |
934 | HPI_ERROR_PLD_LOAD = 209, | 947 | HPI_ERROR_PLD_LOAD = 209, |
935 | /** Unexpected end of file, block length too big etc. */ | 948 | /** Unexpected end of file, block length too big etc. */ |
936 | HPI_ERROR_DSP_FILE_FORMAT = 210, | 949 | HPI_ERROR_DSP_FILE_FORMAT = 210, |
@@ -939,8 +952,7 @@ enum HPI_ERROR_CODES { | |||
939 | HPI_ERROR_DSP_FILE_ACCESS_DENIED = 211, | 952 | HPI_ERROR_DSP_FILE_ACCESS_DENIED = 211, |
940 | /** First DSP code section header not found in DSP file. */ | 953 | /** First DSP code section header not found in DSP file. */ |
941 | HPI_ERROR_DSP_FILE_NO_HEADER = 212, | 954 | HPI_ERROR_DSP_FILE_NO_HEADER = 212, |
942 | /** File read operation on DSP code file failed. */ | 955 | /* HPI_ERROR_DSP_FILE_READ_ERROR= 213, */ |
943 | HPI_ERROR_DSP_FILE_READ_ERROR = 213, | ||
944 | /** DSP code for adapter family not found. */ | 956 | /** DSP code for adapter family not found. */ |
945 | HPI_ERROR_DSP_SECTION_NOT_FOUND = 214, | 957 | HPI_ERROR_DSP_SECTION_NOT_FOUND = 214, |
946 | /** Other OS specific error opening DSP file. */ | 958 | /** Other OS specific error opening DSP file. */ |
@@ -950,23 +962,21 @@ enum HPI_ERROR_CODES { | |||
950 | /** DSP code section header had size == 0. */ | 962 | /** DSP code section header had size == 0. */ |
951 | HPI_ERROR_DSP_FILE_NULL_HEADER = 217, | 963 | HPI_ERROR_DSP_FILE_NULL_HEADER = 217, |
952 | 964 | ||
953 | /** Base number for flash errors. */ | 965 | /* HPI_ERROR_FLASH = 220, */ |
954 | HPI_ERROR_FLASH = 220, | ||
955 | 966 | ||
956 | /** Flash has bad checksum */ | 967 | /** Flash has bad checksum */ |
957 | HPI_ERROR_BAD_CHECKSUM = (HPI_ERROR_FLASH + 1), | 968 | HPI_ERROR_BAD_CHECKSUM = 221, |
958 | HPI_ERROR_BAD_SEQUENCE = (HPI_ERROR_FLASH + 2), | 969 | HPI_ERROR_BAD_SEQUENCE = 222, |
959 | HPI_ERROR_FLASH_ERASE = (HPI_ERROR_FLASH + 3), | 970 | HPI_ERROR_FLASH_ERASE = 223, |
960 | HPI_ERROR_FLASH_PROGRAM = (HPI_ERROR_FLASH + 4), | 971 | HPI_ERROR_FLASH_PROGRAM = 224, |
961 | HPI_ERROR_FLASH_VERIFY = (HPI_ERROR_FLASH + 5), | 972 | HPI_ERROR_FLASH_VERIFY = 225, |
962 | HPI_ERROR_FLASH_TYPE = (HPI_ERROR_FLASH + 6), | 973 | HPI_ERROR_FLASH_TYPE = 226, |
963 | HPI_ERROR_FLASH_START = (HPI_ERROR_FLASH + 7), | 974 | HPI_ERROR_FLASH_START = 227, |
964 | 975 | ||
965 | /** Reserved for OEMs. */ | 976 | /** Reserved for OEMs. */ |
966 | HPI_ERROR_RESERVED_1 = 290, | 977 | HPI_ERROR_RESERVED_1 = 290, |
967 | 978 | ||
968 | /** Stream does not exist. */ | 979 | /* HPI_ERROR_INVALID_STREAM = 300 use HPI_ERROR_INVALID_OBJ_INDEX */ |
969 | HPI_ERROR_INVALID_STREAM = 300, | ||
970 | /** Invalid compression format. */ | 980 | /** Invalid compression format. */ |
971 | HPI_ERROR_INVALID_FORMAT = 301, | 981 | HPI_ERROR_INVALID_FORMAT = 301, |
972 | /** Invalid format samplerate */ | 982 | /** Invalid format samplerate */ |
@@ -977,21 +987,19 @@ enum HPI_ERROR_CODES { | |||
977 | HPI_ERROR_INVALID_BITRATE = 304, | 987 | HPI_ERROR_INVALID_BITRATE = 304, |
978 | /** Invalid datasize used for stream read/write. */ | 988 | /** Invalid datasize used for stream read/write. */ |
979 | HPI_ERROR_INVALID_DATASIZE = 305, | 989 | HPI_ERROR_INVALID_DATASIZE = 305, |
980 | /** Stream buffer is full during stream write. */ | 990 | /* HPI_ERROR_BUFFER_FULL = 306 use HPI_ERROR_INVALID_DATASIZE */ |
981 | HPI_ERROR_BUFFER_FULL = 306, | 991 | /* HPI_ERROR_BUFFER_EMPTY = 307 use HPI_ERROR_INVALID_DATASIZE */ |
982 | /** Stream buffer is empty during stream read. */ | 992 | /** Null data pointer used for stream read/write. */ |
983 | HPI_ERROR_BUFFER_EMPTY = 307, | 993 | HPI_ERROR_INVALID_DATA_POINTER = 308, |
984 | /** Invalid datasize used for stream read/write. */ | ||
985 | HPI_ERROR_INVALID_DATA_TRANSFER = 308, | ||
986 | /** Packet ordering error for stream read/write. */ | 994 | /** Packet ordering error for stream read/write. */ |
987 | HPI_ERROR_INVALID_PACKET_ORDER = 309, | 995 | HPI_ERROR_INVALID_PACKET_ORDER = 309, |
988 | 996 | ||
989 | /** Object can't do requested operation in its current | 997 | /** Object can't do requested operation in its current |
990 | state, eg set format, change rec mux state while recording.*/ | 998 | state, eg set format, change rec mux state while recording.*/ |
991 | HPI_ERROR_INVALID_OPERATION = 310, | 999 | HPI_ERROR_INVALID_OPERATION = 310, |
992 | 1000 | ||
993 | /** Where an SRG is shared amongst streams, an incompatible samplerate is one | 1001 | /** Where a SRG is shared amongst streams, an incompatible samplerate |
994 | that is different to any currently playing or recording stream. */ | 1002 | is one that is different to any currently active stream. */ |
995 | HPI_ERROR_INCOMPATIBLE_SAMPLERATE = 311, | 1003 | HPI_ERROR_INCOMPATIBLE_SAMPLERATE = 311, |
996 | /** Adapter mode is illegal.*/ | 1004 | /** Adapter mode is illegal.*/ |
997 | HPI_ERROR_BAD_ADAPTER_MODE = 312, | 1005 | HPI_ERROR_BAD_ADAPTER_MODE = 312, |
@@ -1004,6 +1012,8 @@ enum HPI_ERROR_CODES { | |||
1004 | HPI_ERROR_NO_INTERADAPTER_GROUPS = 314, | 1012 | HPI_ERROR_NO_INTERADAPTER_GROUPS = 314, |
1005 | /** Streams on different DSPs cannot be grouped. */ | 1013 | /** Streams on different DSPs cannot be grouped. */ |
1006 | HPI_ERROR_NO_INTERDSP_GROUPS = 315, | 1014 | HPI_ERROR_NO_INTERDSP_GROUPS = 315, |
1015 | /** Stream wait cancelled before threshold reached. */ | ||
1016 | HPI_ERROR_WAIT_CANCELLED = 316, | ||
1007 | 1017 | ||
1008 | /** Invalid mixer node for this adapter. */ | 1018 | /** Invalid mixer node for this adapter. */ |
1009 | HPI_ERROR_INVALID_NODE = 400, | 1019 | HPI_ERROR_INVALID_NODE = 400, |
@@ -1017,6 +1027,7 @@ enum HPI_ERROR_CODES { | |||
1017 | HPI_ERROR_CONTROL_DISABLED = 404, | 1027 | HPI_ERROR_CONTROL_DISABLED = 404, |
1018 | /** I2C transaction failed due to a missing ACK. */ | 1028 | /** I2C transaction failed due to a missing ACK. */ |
1019 | HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405, | 1029 | HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405, |
1030 | HPI_ERROR_I2C_MISSING_ACK = 405, | ||
1020 | /** Control is busy, or coming out of | 1031 | /** Control is busy, or coming out of |
1021 | reset and cannot be accessed at this time. */ | 1032 | reset and cannot be accessed at this time. */ |
1022 | HPI_ERROR_CONTROL_NOT_READY = 407, | 1033 | HPI_ERROR_CONTROL_NOT_READY = 407, |
@@ -1027,7 +1038,6 @@ enum HPI_ERROR_CODES { | |||
1027 | HPI_ERROR_NVMEM_FAIL = 452, | 1038 | HPI_ERROR_NVMEM_FAIL = 452, |
1028 | 1039 | ||
1029 | /** I2C */ | 1040 | /** I2C */ |
1030 | HPI_ERROR_I2C_MISSING_ACK = HPI_ERROR_CONTROL_I2C_MISSING_ACK, | ||
1031 | HPI_ERROR_I2C_BAD_ADR = 460, | 1041 | HPI_ERROR_I2C_BAD_ADR = 460, |
1032 | 1042 | ||
1033 | /** Entity errors */ | 1043 | /** Entity errors */ |
@@ -1035,6 +1045,7 @@ enum HPI_ERROR_CODES { | |||
1035 | HPI_ERROR_ENTITY_ITEM_COUNT = 471, | 1045 | HPI_ERROR_ENTITY_ITEM_COUNT = 471, |
1036 | HPI_ERROR_ENTITY_TYPE_INVALID = 472, | 1046 | HPI_ERROR_ENTITY_TYPE_INVALID = 472, |
1037 | HPI_ERROR_ENTITY_ROLE_INVALID = 473, | 1047 | HPI_ERROR_ENTITY_ROLE_INVALID = 473, |
1048 | HPI_ERROR_ENTITY_SIZE_MISMATCH = 474, | ||
1038 | 1049 | ||
1039 | /* AES18 specific errors were 500..507 */ | 1050 | /* AES18 specific errors were 500..507 */ |
1040 | 1051 | ||
@@ -1044,11 +1055,18 @@ enum HPI_ERROR_CODES { | |||
1044 | /** hpioct32.c can't obtain mutex */ | 1055 | /** hpioct32.c can't obtain mutex */ |
1045 | HPI_ERROR_MUTEX_TIMEOUT = 700, | 1056 | HPI_ERROR_MUTEX_TIMEOUT = 700, |
1046 | 1057 | ||
1047 | /** errors from HPI backends have values >= this */ | 1058 | /** Backend errors used to be greater than this. |
1059 | \deprecated Now, all backends return only errors defined here in hpi.h | ||
1060 | */ | ||
1048 | HPI_ERROR_BACKEND_BASE = 900, | 1061 | HPI_ERROR_BACKEND_BASE = 900, |
1049 | 1062 | ||
1050 | /** indicates a cached u16 value is invalid. */ | 1063 | /** Communication with DSP failed */ |
1051 | HPI_ERROR_ILLEGAL_CACHE_VALUE = 0xffff | 1064 | HPI_ERROR_DSP_COMMUNICATION = 900 |
1065 | /* Note that the dsp communication error is set to this value so that | ||
1066 | it remains compatible with any software that expects such errors | ||
1067 | to be backend errors i.e. >= 900. | ||
1068 | Do not define any new error codes with values > 900. | ||
1069 | */ | ||
1052 | }; | 1070 | }; |
1053 | 1071 | ||
1054 | /** \defgroup maximums HPI maximum values | 1072 | /** \defgroup maximums HPI maximum values |
@@ -1075,7 +1093,7 @@ enum HPI_ERROR_CODES { | |||
1075 | 1093 | ||
1076 | /**\}*/ | 1094 | /**\}*/ |
1077 | 1095 | ||
1078 | /* ////////////////////////////////////////////////////////////////////// */ | 1096 | /**************/ |
1079 | /* STRUCTURES */ | 1097 | /* STRUCTURES */ |
1080 | #ifndef DISABLE_PRAGMA_PACK1 | 1098 | #ifndef DISABLE_PRAGMA_PACK1 |
1081 | #pragma pack(push, 1) | 1099 | #pragma pack(push, 1) |
@@ -1092,7 +1110,7 @@ struct hpi_format { | |||
1092 | /**< Stereo/JointStereo/Mono */ | 1110 | /**< Stereo/JointStereo/Mono */ |
1093 | u16 mode_legacy; | 1111 | u16 mode_legacy; |
1094 | /**< Legacy ancillary mode or idle bit */ | 1112 | /**< Legacy ancillary mode or idle bit */ |
1095 | u16 unused; /**< unused */ | 1113 | u16 unused; /**< Unused */ |
1096 | u16 channels; /**< 1,2..., (or ancillary mode or idle bit */ | 1114 | u16 channels; /**< 1,2..., (or ancillary mode or idle bit */ |
1097 | u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */ | 1115 | u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */ |
1098 | }; | 1116 | }; |
@@ -1106,930 +1124,594 @@ struct hpi_anc_frame { | |||
1106 | */ | 1124 | */ |
1107 | struct hpi_async_event { | 1125 | struct hpi_async_event { |
1108 | u16 event_type; /**< type of event. \sa async_event */ | 1126 | u16 event_type; /**< type of event. \sa async_event */ |
1109 | u16 sequence; /**< sequence number, allows lost event detection */ | 1127 | u16 sequence; /**< Sequence number, allows lost event detection */ |
1110 | u32 state; /**< new state */ | 1128 | u32 state; /**< New state */ |
1111 | u32 h_object; /**< handle to the object returning the event. */ | 1129 | u32 h_object; /**< handle to the object returning the event. */ |
1112 | union { | 1130 | union { |
1113 | struct { | 1131 | struct { |
1114 | u16 index; /**< GPIO bit index. */ | 1132 | u16 index; /**< GPIO bit index. */ |
1115 | } gpio; | 1133 | } gpio; |
1116 | struct { | 1134 | struct { |
1117 | u16 node_index; /**< what node is the control on ? */ | 1135 | u16 node_index; /**< what node is the control on ? */ |
1118 | u16 node_type; /**< what type of node is the control on ? */ | 1136 | u16 node_type; /**< what type of node is the control on ? */ |
1119 | } control; | 1137 | } control; |
1120 | } u; | 1138 | } u; |
1121 | }; | 1139 | }; |
1122 | 1140 | ||
1123 | /*/////////////////////////////////////////////////////////////////////////// */ | ||
1124 | /* Public HPI Entity related definitions */ | ||
1125 | |||
1126 | struct hpi_entity; | ||
1127 | |||
1128 | enum e_entity_type { | ||
1129 | entity_type_null, | ||
1130 | entity_type_sequence, /* sequence of potentially heterogeneous TLV entities */ | ||
1131 | |||
1132 | entity_type_reference, /* refers to a TLV entity or NULL */ | ||
1133 | |||
1134 | entity_type_int, /* 32 bit */ | ||
1135 | entity_type_float, /* ieee754 binary 32 bit encoding */ | ||
1136 | entity_type_double, | ||
1137 | |||
1138 | entity_type_cstring, | ||
1139 | entity_type_octet, | ||
1140 | entity_type_ip4_address, | ||
1141 | entity_type_ip6_address, | ||
1142 | entity_type_mac_address, | ||
1143 | |||
1144 | LAST_ENTITY_TYPE | ||
1145 | }; | ||
1146 | |||
1147 | enum e_entity_role { | ||
1148 | entity_role_null, | ||
1149 | entity_role_value, | ||
1150 | entity_role_classname, | ||
1151 | |||
1152 | entity_role_units, | ||
1153 | entity_role_flags, | ||
1154 | entity_role_range, | ||
1155 | |||
1156 | entity_role_mapping, | ||
1157 | entity_role_enum, | ||
1158 | |||
1159 | entity_role_instance_of, | ||
1160 | entity_role_depends_on, | ||
1161 | entity_role_member_of_group, | ||
1162 | entity_role_value_constraint, | ||
1163 | entity_role_parameter_port, | ||
1164 | |||
1165 | entity_role_block, | ||
1166 | entity_role_node_group, | ||
1167 | entity_role_audio_port, | ||
1168 | entity_role_clock_port, | ||
1169 | LAST_ENTITY_ROLE | ||
1170 | }; | ||
1171 | |||
1172 | /* skip host side function declarations for | 1141 | /* skip host side function declarations for |
1173 | DSP compile and documentation extraction */ | 1142 | DSP compile and documentation extraction */ |
1174 | 1143 | ||
1175 | struct hpi_hsubsys { | ||
1176 | int not_really_used; | ||
1177 | }; | ||
1178 | |||
1179 | #ifndef DISABLE_PRAGMA_PACK1 | 1144 | #ifndef DISABLE_PRAGMA_PACK1 |
1180 | #pragma pack(pop) | 1145 | #pragma pack(pop) |
1181 | #endif | 1146 | #endif |
1182 | 1147 | ||
1183 | /*////////////////////////////////////////////////////////////////////////// */ | 1148 | /*****************/ |
1184 | /* HPI FUNCTIONS */ | 1149 | /* HPI FUNCTIONS */ |
1150 | /*****************/ | ||
1185 | 1151 | ||
1186 | /*/////////////////////////// */ | 1152 | /* Stream */ |
1187 | /* DATA and FORMAT and STREAM */ | ||
1188 | |||
1189 | u16 hpi_stream_estimate_buffer_size(struct hpi_format *pF, | 1153 | u16 hpi_stream_estimate_buffer_size(struct hpi_format *pF, |
1190 | u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size); | 1154 | u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size); |
1191 | 1155 | ||
1192 | /*/////////// */ | 1156 | /*************/ |
1193 | /* SUB SYSTEM */ | 1157 | /* SubSystem */ |
1194 | struct hpi_hsubsys *hpi_subsys_create(void | 1158 | /*************/ |
1195 | ); | ||
1196 | |||
1197 | void hpi_subsys_free(const struct hpi_hsubsys *ph_subsys); | ||
1198 | |||
1199 | u16 hpi_subsys_get_version(const struct hpi_hsubsys *ph_subsys, | ||
1200 | u32 *pversion); | ||
1201 | |||
1202 | u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys, | ||
1203 | u32 *pversion_ex); | ||
1204 | |||
1205 | u16 hpi_subsys_get_info(const struct hpi_hsubsys *ph_subsys, u32 *pversion, | ||
1206 | u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length); | ||
1207 | |||
1208 | u16 hpi_subsys_find_adapters(const struct hpi_hsubsys *ph_subsys, | ||
1209 | u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length); | ||
1210 | |||
1211 | u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys, | ||
1212 | int *pn_num_adapters); | ||
1213 | |||
1214 | u16 hpi_subsys_get_adapter(const struct hpi_hsubsys *ph_subsys, int iterator, | ||
1215 | u32 *padapter_index, u16 *pw_adapter_type); | ||
1216 | |||
1217 | u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass); | ||
1218 | 1159 | ||
1219 | u16 hpi_subsys_set_host_network_interface(const struct hpi_hsubsys *ph_subsys, | 1160 | u16 hpi_subsys_get_version_ex(u32 *pversion_ex); |
1220 | const char *sz_interface); | ||
1221 | 1161 | ||
1222 | /*///////// */ | 1162 | u16 hpi_subsys_get_num_adapters(int *pn_num_adapters); |
1223 | /* ADAPTER */ | ||
1224 | 1163 | ||
1225 | u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index); | 1164 | u16 hpi_subsys_get_adapter(int iterator, u32 *padapter_index, |
1165 | u16 *pw_adapter_type); | ||
1226 | 1166 | ||
1227 | u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index); | 1167 | /***********/ |
1168 | /* Adapter */ | ||
1169 | /***********/ | ||
1228 | 1170 | ||
1229 | u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys, | 1171 | u16 hpi_adapter_open(u16 adapter_index); |
1230 | u16 adapter_index, u16 *pw_num_outstreams, u16 *pw_num_instreams, | ||
1231 | u16 *pw_version, u32 *pserial_number, u16 *pw_adapter_type); | ||
1232 | 1172 | ||
1233 | u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys, | 1173 | u16 hpi_adapter_close(u16 adapter_index); |
1234 | u16 adapter_index, u16 module_index, u16 *pw_num_outputs, | ||
1235 | u16 *pw_num_inputs, u16 *pw_version, u32 *pserial_number, | ||
1236 | u16 *pw_module_type, u32 *ph_module); | ||
1237 | 1174 | ||
1238 | u16 hpi_adapter_set_mode(const struct hpi_hsubsys *ph_subsys, | 1175 | u16 hpi_adapter_get_info(u16 adapter_index, u16 *pw_num_outstreams, |
1239 | u16 adapter_index, u32 adapter_mode); | 1176 | u16 *pw_num_instreams, u16 *pw_version, u32 *pserial_number, |
1177 | u16 *pw_adapter_type); | ||
1240 | 1178 | ||
1241 | u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys, | 1179 | u16 hpi_adapter_get_module_by_index(u16 adapter_index, u16 module_index, |
1242 | u16 adapter_index, u32 adapter_mode, u16 query_or_set); | 1180 | u16 *pw_num_outputs, u16 *pw_num_inputs, u16 *pw_version, |
1243 | 1181 | u32 *pserial_number, u16 *pw_module_type, u32 *ph_module); | |
1244 | u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys, | ||
1245 | u16 adapter_index, u32 *padapter_mode); | ||
1246 | |||
1247 | u16 hpi_adapter_get_assert(const struct hpi_hsubsys *ph_subsys, | ||
1248 | u16 adapter_index, u16 *assert_present, char *psz_assert, | ||
1249 | u16 *pw_line_number); | ||
1250 | |||
1251 | u16 hpi_adapter_get_assert_ex(const struct hpi_hsubsys *ph_subsys, | ||
1252 | u16 adapter_index, u16 *assert_present, char *psz_assert, | ||
1253 | u32 *pline_number, u16 *pw_assert_on_dsp); | ||
1254 | |||
1255 | u16 hpi_adapter_test_assert(const struct hpi_hsubsys *ph_subsys, | ||
1256 | u16 adapter_index, u16 assert_id); | ||
1257 | |||
1258 | u16 hpi_adapter_enable_capability(const struct hpi_hsubsys *ph_subsys, | ||
1259 | u16 adapter_index, u16 capability, u32 key); | ||
1260 | |||
1261 | u16 hpi_adapter_self_test(const struct hpi_hsubsys *ph_subsys, | ||
1262 | u16 adapter_index); | ||
1263 | |||
1264 | u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys, | ||
1265 | u16 adapter_index, u32 dsp_address, char *p_bytes, int *count_bytes); | ||
1266 | |||
1267 | u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys, | ||
1268 | u16 adapter_index, u16 property, u16 paramter1, u16 paramter2); | ||
1269 | |||
1270 | u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys, | ||
1271 | u16 adapter_index, u16 property, u16 *pw_paramter1, | ||
1272 | u16 *pw_paramter2); | ||
1273 | |||
1274 | u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys, | ||
1275 | u16 adapter_index, u16 index, u16 what_to_enumerate, | ||
1276 | u16 property_index, u32 *psetting); | ||
1277 | |||
1278 | /*////////////// */ | ||
1279 | /* NonVol Memory */ | ||
1280 | u16 hpi_nv_memory_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | ||
1281 | u32 *ph_nv_memory, u16 *pw_size_in_bytes); | ||
1282 | |||
1283 | u16 hpi_nv_memory_read_byte(const struct hpi_hsubsys *ph_subsys, | ||
1284 | u32 h_nv_memory, u16 index, u16 *pw_data); | ||
1285 | |||
1286 | u16 hpi_nv_memory_write_byte(const struct hpi_hsubsys *ph_subsys, | ||
1287 | u32 h_nv_memory, u16 index, u16 data); | ||
1288 | |||
1289 | /*////////////// */ | ||
1290 | /* Digital I/O */ | ||
1291 | u16 hpi_gpio_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | ||
1292 | u32 *ph_gpio, u16 *pw_number_input_bits, u16 *pw_number_output_bits); | ||
1293 | |||
1294 | u16 hpi_gpio_read_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | ||
1295 | u16 bit_index, u16 *pw_bit_data); | ||
1296 | |||
1297 | u16 hpi_gpio_read_all_bits(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | ||
1298 | u16 aw_all_bit_data[4] | ||
1299 | ); | ||
1300 | 1182 | ||
1301 | u16 hpi_gpio_write_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | 1183 | u16 hpi_adapter_set_mode(u16 adapter_index, u32 adapter_mode); |
1302 | u16 bit_index, u16 bit_data); | ||
1303 | 1184 | ||
1304 | u16 hpi_gpio_write_status(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | 1185 | u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode, |
1305 | u16 aw_all_bit_data[4] | 1186 | u16 query_or_set); |
1306 | ); | ||
1307 | 1187 | ||
1308 | /**********************/ | 1188 | u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode); |
1309 | /* Async Event Object */ | ||
1310 | /**********************/ | ||
1311 | u16 hpi_async_event_open(const struct hpi_hsubsys *ph_subsys, | ||
1312 | u16 adapter_index, u32 *ph_async); | ||
1313 | 1189 | ||
1314 | u16 hpi_async_event_close(const struct hpi_hsubsys *ph_subsys, u32 h_async); | 1190 | u16 hpi_adapter_get_assert2(u16 adapter_index, u16 *p_assert_count, |
1191 | char *psz_assert, u32 *p_param1, u32 *p_param2, | ||
1192 | u32 *p_dsp_string_addr, u16 *p_processor_id); | ||
1315 | 1193 | ||
1316 | u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async, | 1194 | u16 hpi_adapter_test_assert(u16 adapter_index, u16 assert_id); |
1317 | u16 maximum_events, struct hpi_async_event *p_events, | ||
1318 | u16 *pw_number_returned); | ||
1319 | 1195 | ||
1320 | u16 hpi_async_event_get_count(const struct hpi_hsubsys *ph_subsys, | 1196 | u16 hpi_adapter_enable_capability(u16 adapter_index, u16 capability, u32 key); |
1321 | u32 h_async, u16 *pw_count); | ||
1322 | 1197 | ||
1323 | u16 hpi_async_event_get(const struct hpi_hsubsys *ph_subsys, u32 h_async, | 1198 | u16 hpi_adapter_self_test(u16 adapter_index); |
1324 | u16 maximum_events, struct hpi_async_event *p_events, | ||
1325 | u16 *pw_number_returned); | ||
1326 | 1199 | ||
1327 | /*/////////// */ | 1200 | u16 hpi_adapter_debug_read(u16 adapter_index, u32 dsp_address, char *p_bytes, |
1328 | /* WATCH-DOG */ | 1201 | int *count_bytes); |
1329 | u16 hpi_watchdog_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | ||
1330 | u32 *ph_watchdog); | ||
1331 | 1202 | ||
1332 | u16 hpi_watchdog_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog, | 1203 | u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 paramter1, |
1333 | u32 time_millisec); | 1204 | u16 paramter2); |
1334 | 1205 | ||
1335 | u16 hpi_watchdog_ping(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog); | 1206 | u16 hpi_adapter_get_property(u16 adapter_index, u16 property, |
1207 | u16 *pw_paramter1, u16 *pw_paramter2); | ||
1336 | 1208 | ||
1337 | /**************/ | 1209 | u16 hpi_adapter_enumerate_property(u16 adapter_index, u16 index, |
1338 | /* OUT STREAM */ | 1210 | u16 what_to_enumerate, u16 property_index, u32 *psetting); |
1339 | /**************/ | 1211 | /*************/ |
1340 | u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | 1212 | /* OutStream */ |
1341 | u16 outstream_index, u32 *ph_outstream); | 1213 | /*************/ |
1214 | u16 hpi_outstream_open(u16 adapter_index, u16 outstream_index, | ||
1215 | u32 *ph_outstream); | ||
1342 | 1216 | ||
1343 | u16 hpi_outstream_close(const struct hpi_hsubsys *ph_subsys, u32 h_outstream); | 1217 | u16 hpi_outstream_close(u32 h_outstream); |
1344 | 1218 | ||
1345 | u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys, | 1219 | u16 hpi_outstream_get_info_ex(u32 h_outstream, u16 *pw_state, |
1346 | u32 h_outstream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_to_play, | 1220 | u32 *pbuffer_size, u32 *pdata_to_play, u32 *psamples_played, |
1347 | u32 *psamples_played, u32 *pauxiliary_data_to_play); | 1221 | u32 *pauxiliary_data_to_play); |
1348 | 1222 | ||
1349 | u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys, | 1223 | u16 hpi_outstream_write_buf(u32 h_outstream, const u8 *pb_write_buf, |
1350 | u32 h_outstream, const u8 *pb_write_buf, u32 bytes_to_write, | 1224 | u32 bytes_to_write, const struct hpi_format *p_format); |
1351 | const struct hpi_format *p_format); | ||
1352 | 1225 | ||
1353 | u16 hpi_outstream_start(const struct hpi_hsubsys *ph_subsys, u32 h_outstream); | 1226 | u16 hpi_outstream_start(u32 h_outstream); |
1354 | 1227 | ||
1355 | u16 hpi_outstream_wait_start(const struct hpi_hsubsys *ph_subsys, | 1228 | u16 hpi_outstream_wait_start(u32 h_outstream); |
1356 | u32 h_outstream); | ||
1357 | 1229 | ||
1358 | u16 hpi_outstream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_outstream); | 1230 | u16 hpi_outstream_stop(u32 h_outstream); |
1359 | 1231 | ||
1360 | u16 hpi_outstream_sinegen(const struct hpi_hsubsys *ph_subsys, | 1232 | u16 hpi_outstream_sinegen(u32 h_outstream); |
1361 | u32 h_outstream); | ||
1362 | 1233 | ||
1363 | u16 hpi_outstream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_outstream); | 1234 | u16 hpi_outstream_reset(u32 h_outstream); |
1364 | 1235 | ||
1365 | u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys, | 1236 | u16 hpi_outstream_query_format(u32 h_outstream, struct hpi_format *p_format); |
1366 | u32 h_outstream, struct hpi_format *p_format); | ||
1367 | 1237 | ||
1368 | u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys, | 1238 | u16 hpi_outstream_set_format(u32 h_outstream, struct hpi_format *p_format); |
1369 | u32 h_outstream, struct hpi_format *p_format); | ||
1370 | 1239 | ||
1371 | u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys, | 1240 | u16 hpi_outstream_set_punch_in_out(u32 h_outstream, u32 punch_in_sample, |
1372 | u32 h_outstream, u32 punch_in_sample, u32 punch_out_sample); | 1241 | u32 punch_out_sample); |
1373 | 1242 | ||
1374 | u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys, | 1243 | u16 hpi_outstream_set_velocity(u32 h_outstream, short velocity); |
1375 | u32 h_outstream, short velocity); | ||
1376 | 1244 | ||
1377 | u16 hpi_outstream_ancillary_reset(const struct hpi_hsubsys *ph_subsys, | 1245 | u16 hpi_outstream_ancillary_reset(u32 h_outstream, u16 mode); |
1378 | u32 h_outstream, u16 mode); | ||
1379 | 1246 | ||
1380 | u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys, | 1247 | u16 hpi_outstream_ancillary_get_info(u32 h_outstream, u32 *pframes_available); |
1381 | u32 h_outstream, u32 *pframes_available); | ||
1382 | 1248 | ||
1383 | u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys, | 1249 | u16 hpi_outstream_ancillary_read(u32 h_outstream, |
1384 | u32 h_outstream, struct hpi_anc_frame *p_anc_frame_buffer, | 1250 | struct hpi_anc_frame *p_anc_frame_buffer, |
1385 | u32 anc_frame_buffer_size_in_bytes, | 1251 | u32 anc_frame_buffer_size_in_bytes, |
1386 | u32 number_of_ancillary_frames_to_read); | 1252 | u32 number_of_ancillary_frames_to_read); |
1387 | 1253 | ||
1388 | u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys, | 1254 | u16 hpi_outstream_set_time_scale(u32 h_outstream, u32 time_scaleX10000); |
1389 | u32 h_outstream, u32 time_scaleX10000); | ||
1390 | 1255 | ||
1391 | u16 hpi_outstream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys, | 1256 | u16 hpi_outstream_host_buffer_allocate(u32 h_outstream, u32 size_in_bytes); |
1392 | u32 h_outstream, u32 size_in_bytes); | ||
1393 | 1257 | ||
1394 | u16 hpi_outstream_host_buffer_free(const struct hpi_hsubsys *ph_subsys, | 1258 | u16 hpi_outstream_host_buffer_free(u32 h_outstream); |
1395 | u32 h_outstream); | ||
1396 | 1259 | ||
1397 | u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys, | 1260 | u16 hpi_outstream_group_add(u32 h_outstream, u32 h_stream); |
1398 | u32 h_outstream, u32 h_stream); | ||
1399 | 1261 | ||
1400 | u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys, | 1262 | u16 hpi_outstream_group_get_map(u32 h_outstream, u32 *poutstream_map, |
1401 | u32 h_outstream, u32 *poutstream_map, u32 *pinstream_map); | 1263 | u32 *pinstream_map); |
1402 | 1264 | ||
1403 | u16 hpi_outstream_group_reset(const struct hpi_hsubsys *ph_subsys, | 1265 | u16 hpi_outstream_group_reset(u32 h_outstream); |
1404 | u32 h_outstream); | ||
1405 | 1266 | ||
1406 | /*////////// */ | 1267 | /************/ |
1407 | /* IN_STREAM */ | 1268 | /* InStream */ |
1408 | u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | 1269 | /************/ |
1409 | u16 instream_index, u32 *ph_instream); | 1270 | u16 hpi_instream_open(u16 adapter_index, u16 instream_index, |
1271 | u32 *ph_instream); | ||
1410 | 1272 | ||
1411 | u16 hpi_instream_close(const struct hpi_hsubsys *ph_subsys, u32 h_instream); | 1273 | u16 hpi_instream_close(u32 h_instream); |
1412 | 1274 | ||
1413 | u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys, | 1275 | u16 hpi_instream_query_format(u32 h_instream, |
1414 | u32 h_instream, const struct hpi_format *p_format); | 1276 | const struct hpi_format *p_format); |
1415 | 1277 | ||
1416 | u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys, | 1278 | u16 hpi_instream_set_format(u32 h_instream, |
1417 | u32 h_instream, const struct hpi_format *p_format); | 1279 | const struct hpi_format *p_format); |
1418 | 1280 | ||
1419 | u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream, | 1281 | u16 hpi_instream_read_buf(u32 h_instream, u8 *pb_read_buf, u32 bytes_to_read); |
1420 | u8 *pb_read_buf, u32 bytes_to_read); | ||
1421 | 1282 | ||
1422 | u16 hpi_instream_start(const struct hpi_hsubsys *ph_subsys, u32 h_instream); | 1283 | u16 hpi_instream_start(u32 h_instream); |
1423 | 1284 | ||
1424 | u16 hpi_instream_wait_start(const struct hpi_hsubsys *ph_subsys, | 1285 | u16 hpi_instream_wait_start(u32 h_instream); |
1425 | u32 h_instream); | ||
1426 | 1286 | ||
1427 | u16 hpi_instream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_instream); | 1287 | u16 hpi_instream_stop(u32 h_instream); |
1428 | 1288 | ||
1429 | u16 hpi_instream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_instream); | 1289 | u16 hpi_instream_reset(u32 h_instream); |
1430 | 1290 | ||
1431 | u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys, | 1291 | u16 hpi_instream_get_info_ex(u32 h_instream, u16 *pw_state, u32 *pbuffer_size, |
1432 | u32 h_instream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_recorded, | 1292 | u32 *pdata_recorded, u32 *psamples_recorded, |
1433 | u32 *psamples_recorded, u32 *pauxiliary_data_recorded); | 1293 | u32 *pauxiliary_data_recorded); |
1434 | 1294 | ||
1435 | u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys, | 1295 | u16 hpi_instream_ancillary_reset(u32 h_instream, u16 bytes_per_frame, |
1436 | u32 h_instream, u16 bytes_per_frame, u16 mode, u16 alignment, | 1296 | u16 mode, u16 alignment, u16 idle_bit); |
1437 | u16 idle_bit); | ||
1438 | 1297 | ||
1439 | u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys, | 1298 | u16 hpi_instream_ancillary_get_info(u32 h_instream, u32 *pframe_space); |
1440 | u32 h_instream, u32 *pframe_space); | ||
1441 | 1299 | ||
1442 | u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys, | 1300 | u16 hpi_instream_ancillary_write(u32 h_instream, |
1443 | u32 h_instream, const struct hpi_anc_frame *p_anc_frame_buffer, | 1301 | const struct hpi_anc_frame *p_anc_frame_buffer, |
1444 | u32 anc_frame_buffer_size_in_bytes, | 1302 | u32 anc_frame_buffer_size_in_bytes, |
1445 | u32 number_of_ancillary_frames_to_write); | 1303 | u32 number_of_ancillary_frames_to_write); |
1446 | 1304 | ||
1447 | u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys, | 1305 | u16 hpi_instream_host_buffer_allocate(u32 h_instream, u32 size_in_bytes); |
1448 | u32 h_instream, u32 size_in_bytes); | ||
1449 | 1306 | ||
1450 | u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys, | 1307 | u16 hpi_instream_host_buffer_free(u32 h_instream); |
1451 | u32 h_instream); | ||
1452 | 1308 | ||
1453 | u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys, | 1309 | u16 hpi_instream_group_add(u32 h_instream, u32 h_stream); |
1454 | u32 h_instream, u32 h_stream); | ||
1455 | 1310 | ||
1456 | u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys, | 1311 | u16 hpi_instream_group_get_map(u32 h_instream, u32 *poutstream_map, |
1457 | u32 h_instream, u32 *poutstream_map, u32 *pinstream_map); | 1312 | u32 *pinstream_map); |
1458 | 1313 | ||
1459 | u16 hpi_instream_group_reset(const struct hpi_hsubsys *ph_subsys, | 1314 | u16 hpi_instream_group_reset(u32 h_instream); |
1460 | u32 h_instream); | ||
1461 | 1315 | ||
1462 | /*********/ | 1316 | /*********/ |
1463 | /* MIXER */ | 1317 | /* Mixer */ |
1464 | /*********/ | 1318 | /*********/ |
1465 | u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | 1319 | u16 hpi_mixer_open(u16 adapter_index, u32 *ph_mixer); |
1466 | u32 *ph_mixer); | 1320 | |
1467 | 1321 | u16 hpi_mixer_close(u32 h_mixer); | |
1468 | u16 hpi_mixer_close(const struct hpi_hsubsys *ph_subsys, u32 h_mixer); | 1322 | |
1469 | 1323 | u16 hpi_mixer_get_control(u32 h_mixer, u16 src_node_type, | |
1470 | u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer, | 1324 | u16 src_node_type_index, u16 dst_node_type, u16 dst_node_type_index, |
1471 | u16 src_node_type, u16 src_node_type_index, u16 dst_node_type, | 1325 | u16 control_type, u32 *ph_control); |
1472 | u16 dst_node_type_index, u16 control_type, u32 *ph_control); | 1326 | |
1473 | 1327 | u16 hpi_mixer_get_control_by_index(u32 h_mixer, u16 control_index, | |
1474 | u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys, | 1328 | u16 *pw_src_node_type, u16 *pw_src_node_index, u16 *pw_dst_node_type, |
1475 | u32 h_mixer, u16 control_index, u16 *pw_src_node_type, | 1329 | u16 *pw_dst_node_index, u16 *pw_control_type, u32 *ph_control); |
1476 | u16 *pw_src_node_index, u16 *pw_dst_node_type, u16 *pw_dst_node_index, | 1330 | |
1477 | u16 *pw_control_type, u32 *ph_control); | 1331 | u16 hpi_mixer_store(u32 h_mixer, enum HPI_MIXER_STORE_COMMAND command, |
1478 | 1332 | u16 index); | |
1479 | u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer, | 1333 | /************/ |
1480 | enum HPI_MIXER_STORE_COMMAND command, u16 index); | 1334 | /* Controls */ |
1481 | /*************************/ | 1335 | /************/ |
1482 | /* mixer CONTROLS */ | 1336 | /******************/ |
1483 | /*************************/ | 1337 | /* Volume control */ |
1484 | /*************************/ | 1338 | /******************/ |
1485 | /* volume control */ | 1339 | u16 hpi_volume_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] |
1486 | /*************************/ | ||
1487 | u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | ||
1488 | short an_gain0_01dB[HPI_MAX_CHANNELS] | ||
1489 | ); | 1340 | ); |
1490 | 1341 | ||
1491 | u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1342 | u16 hpi_volume_get_gain(u32 h_control, |
1492 | short an_gain0_01dB_out[HPI_MAX_CHANNELS] | 1343 | short an_gain0_01dB_out[HPI_MAX_CHANNELS] |
1493 | ); | 1344 | ); |
1494 | 1345 | ||
1346 | u16 hpi_volume_set_mute(u32 h_control, u32 mute); | ||
1347 | |||
1348 | u16 hpi_volume_get_mute(u32 h_control, u32 *mute); | ||
1349 | |||
1495 | #define hpi_volume_get_range hpi_volume_query_range | 1350 | #define hpi_volume_get_range hpi_volume_query_range |
1496 | u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1351 | u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB, |
1497 | short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB); | 1352 | short *max_gain_01dB, short *step_gain_01dB); |
1498 | 1353 | ||
1499 | u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys, | 1354 | u16 hpi_volume_query_channels(const u32 h_volume, u32 *p_channels); |
1500 | const u32 h_volume, u32 *p_channels); | ||
1501 | 1355 | ||
1502 | u16 hpi_volume_auto_fade(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1356 | u16 hpi_volume_auto_fade(u32 h_control, |
1503 | short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms); | 1357 | short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms); |
1504 | 1358 | ||
1505 | u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys, | 1359 | u16 hpi_volume_auto_fade_profile(u32 h_control, |
1506 | u32 h_control, short an_stop_gain0_01dB[HPI_MAX_CHANNELS], | 1360 | short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms, |
1507 | u32 duration_ms, u16 profile); | 1361 | u16 profile); |
1508 | 1362 | ||
1509 | /*************************/ | 1363 | /*****************/ |
1510 | /* level control */ | 1364 | /* Level control */ |
1511 | /*************************/ | 1365 | /*****************/ |
1512 | u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1366 | u16 hpi_level_query_range(u32 h_control, short *min_gain_01dB, |
1513 | short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB); | 1367 | short *max_gain_01dB, short *step_gain_01dB); |
1514 | 1368 | ||
1515 | u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1369 | u16 hpi_level_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] |
1516 | short an_gain0_01dB[HPI_MAX_CHANNELS] | ||
1517 | ); | 1370 | ); |
1518 | 1371 | ||
1519 | u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1372 | u16 hpi_level_get_gain(u32 h_control, |
1520 | short an_gain0_01dB_out[HPI_MAX_CHANNELS] | 1373 | short an_gain0_01dB_out[HPI_MAX_CHANNELS] |
1521 | ); | 1374 | ); |
1522 | 1375 | ||
1523 | /*************************/ | 1376 | /*****************/ |
1524 | /* meter control */ | 1377 | /* Meter control */ |
1525 | /*************************/ | 1378 | /*****************/ |
1526 | u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys, | 1379 | u16 hpi_meter_query_channels(const u32 h_meter, u32 *p_channels); |
1527 | const u32 h_meter, u32 *p_channels); | ||
1528 | 1380 | ||
1529 | u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1381 | u16 hpi_meter_get_peak(u32 h_control, |
1530 | short an_peak0_01dB_out[HPI_MAX_CHANNELS] | 1382 | short an_peak0_01dB_out[HPI_MAX_CHANNELS] |
1531 | ); | 1383 | ); |
1532 | 1384 | ||
1533 | u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1385 | u16 hpi_meter_get_rms(u32 h_control, short an_peak0_01dB_out[HPI_MAX_CHANNELS] |
1534 | short an_peak0_01dB_out[HPI_MAX_CHANNELS] | ||
1535 | ); | 1386 | ); |
1536 | 1387 | ||
1537 | u16 hpi_meter_set_peak_ballistics(const struct hpi_hsubsys *ph_subsys, | 1388 | u16 hpi_meter_set_peak_ballistics(u32 h_control, u16 attack, u16 decay); |
1538 | u32 h_control, u16 attack, u16 decay); | ||
1539 | 1389 | ||
1540 | u16 hpi_meter_set_rms_ballistics(const struct hpi_hsubsys *ph_subsys, | 1390 | u16 hpi_meter_set_rms_ballistics(u32 h_control, u16 attack, u16 decay); |
1541 | u32 h_control, u16 attack, u16 decay); | ||
1542 | 1391 | ||
1543 | u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys, | 1392 | u16 hpi_meter_get_peak_ballistics(u32 h_control, u16 *attack, u16 *decay); |
1544 | u32 h_control, u16 *attack, u16 *decay); | ||
1545 | 1393 | ||
1546 | u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys, | 1394 | u16 hpi_meter_get_rms_ballistics(u32 h_control, u16 *attack, u16 *decay); |
1547 | u32 h_control, u16 *attack, u16 *decay); | ||
1548 | 1395 | ||
1549 | /*************************/ | 1396 | /************************/ |
1550 | /* channel mode control */ | 1397 | /* ChannelMode control */ |
1551 | /*************************/ | 1398 | /************************/ |
1552 | u16 hpi_channel_mode_query_mode(const struct hpi_hsubsys *ph_subsys, | 1399 | u16 hpi_channel_mode_query_mode(const u32 h_mode, const u32 index, |
1553 | const u32 h_mode, const u32 index, u16 *pw_mode); | 1400 | u16 *pw_mode); |
1554 | 1401 | ||
1555 | u16 hpi_channel_mode_set(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1402 | u16 hpi_channel_mode_set(u32 h_control, u16 mode); |
1556 | u16 mode); | ||
1557 | 1403 | ||
1558 | u16 hpi_channel_mode_get(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1404 | u16 hpi_channel_mode_get(u32 h_control, u16 *mode); |
1559 | u16 *mode); | ||
1560 | 1405 | ||
1561 | /*************************/ | 1406 | /*****************/ |
1562 | /* Tuner control */ | 1407 | /* Tuner control */ |
1563 | /*************************/ | 1408 | /*****************/ |
1564 | u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys, | 1409 | u16 hpi_tuner_query_band(const u32 h_tuner, const u32 index, u16 *pw_band); |
1565 | const u32 h_tuner, const u32 index, u16 *pw_band); | ||
1566 | 1410 | ||
1567 | u16 hpi_tuner_set_band(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1411 | u16 hpi_tuner_set_band(u32 h_control, u16 band); |
1568 | u16 band); | ||
1569 | 1412 | ||
1570 | u16 hpi_tuner_get_band(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1413 | u16 hpi_tuner_get_band(u32 h_control, u16 *pw_band); |
1571 | u16 *pw_band); | ||
1572 | 1414 | ||
1573 | u16 hpi_tuner_query_frequency(const struct hpi_hsubsys *ph_subsys, | 1415 | u16 hpi_tuner_query_frequency(const u32 h_tuner, const u32 index, |
1574 | const u32 h_tuner, const u32 index, const u16 band, u32 *pfreq); | 1416 | const u16 band, u32 *pfreq); |
1575 | 1417 | ||
1576 | u16 hpi_tuner_set_frequency(const struct hpi_hsubsys *ph_subsys, | 1418 | u16 hpi_tuner_set_frequency(u32 h_control, u32 freq_ink_hz); |
1577 | u32 h_control, u32 freq_ink_hz); | ||
1578 | 1419 | ||
1579 | u16 hpi_tuner_get_frequency(const struct hpi_hsubsys *ph_subsys, | 1420 | u16 hpi_tuner_get_frequency(u32 h_control, u32 *pw_freq_ink_hz); |
1580 | u32 h_control, u32 *pw_freq_ink_hz); | ||
1581 | 1421 | ||
1582 | u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1422 | u16 hpi_tuner_get_rf_level(u32 h_control, short *pw_level); |
1583 | short *pw_level); | ||
1584 | 1423 | ||
1585 | u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys, | 1424 | u16 hpi_tuner_get_raw_rf_level(u32 h_control, short *pw_level); |
1586 | u32 h_control, short *pw_level); | ||
1587 | 1425 | ||
1588 | u16 hpi_tuner_query_gain(const struct hpi_hsubsys *ph_subsys, | 1426 | u16 hpi_tuner_query_gain(const u32 h_tuner, const u32 index, u16 *pw_gain); |
1589 | const u32 h_tuner, const u32 index, u16 *pw_gain); | ||
1590 | 1427 | ||
1591 | u16 hpi_tuner_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1428 | u16 hpi_tuner_set_gain(u32 h_control, short gain); |
1592 | short gain); | ||
1593 | 1429 | ||
1594 | u16 hpi_tuner_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1430 | u16 hpi_tuner_get_gain(u32 h_control, short *pn_gain); |
1595 | short *pn_gain); | ||
1596 | 1431 | ||
1597 | u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1432 | u16 hpi_tuner_get_status(u32 h_control, u16 *pw_status_mask, u16 *pw_status); |
1598 | u16 *pw_status_mask, u16 *pw_status); | ||
1599 | 1433 | ||
1600 | u16 hpi_tuner_set_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1434 | u16 hpi_tuner_set_mode(u32 h_control, u32 mode, u32 value); |
1601 | u32 mode, u32 value); | ||
1602 | 1435 | ||
1603 | u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1436 | u16 hpi_tuner_get_mode(u32 h_control, u32 mode, u32 *pn_value); |
1604 | u32 mode, u32 *pn_value); | ||
1605 | 1437 | ||
1606 | u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1438 | u16 hpi_tuner_get_rds(u32 h_control, char *p_rds_data); |
1607 | char *p_rds_data); | ||
1608 | 1439 | ||
1609 | u16 hpi_tuner_query_deemphasis(const struct hpi_hsubsys *ph_subsys, | 1440 | u16 hpi_tuner_query_deemphasis(const u32 h_tuner, const u32 index, |
1610 | const u32 h_tuner, const u32 index, const u16 band, u32 *pdeemphasis); | 1441 | const u16 band, u32 *pdeemphasis); |
1611 | 1442 | ||
1612 | u16 hpi_tuner_set_deemphasis(const struct hpi_hsubsys *ph_subsys, | 1443 | u16 hpi_tuner_set_deemphasis(u32 h_control, u32 deemphasis); |
1613 | u32 h_control, u32 deemphasis); | 1444 | u16 hpi_tuner_get_deemphasis(u32 h_control, u32 *pdeemphasis); |
1614 | u16 hpi_tuner_get_deemphasis(const struct hpi_hsubsys *ph_subsys, | ||
1615 | u32 h_control, u32 *pdeemphasis); | ||
1616 | 1445 | ||
1617 | u16 hpi_tuner_query_program(const struct hpi_hsubsys *ph_subsys, | 1446 | u16 hpi_tuner_query_program(const u32 h_tuner, u32 *pbitmap_program); |
1618 | const u32 h_tuner, u32 *pbitmap_program); | ||
1619 | 1447 | ||
1620 | u16 hpi_tuner_set_program(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1448 | u16 hpi_tuner_set_program(u32 h_control, u32 program); |
1621 | u32 program); | ||
1622 | 1449 | ||
1623 | u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1450 | u16 hpi_tuner_get_program(u32 h_control, u32 *pprogram); |
1624 | u32 *pprogram); | ||
1625 | 1451 | ||
1626 | u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys, | 1452 | u16 hpi_tuner_get_hd_radio_dsp_version(u32 h_control, char *psz_dsp_version, |
1627 | u32 h_control, char *psz_dsp_version, const u32 string_size); | 1453 | const u32 string_size); |
1628 | 1454 | ||
1629 | u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys, | 1455 | u16 hpi_tuner_get_hd_radio_sdk_version(u32 h_control, char *psz_sdk_version, |
1630 | u32 h_control, char *psz_sdk_version, const u32 string_size); | 1456 | const u32 string_size); |
1631 | 1457 | ||
1632 | u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys, | 1458 | u16 hpi_tuner_get_hd_radio_signal_quality(u32 h_control, u32 *pquality); |
1633 | u32 h_control, u32 *pquality); | ||
1634 | 1459 | ||
1635 | u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, | 1460 | u16 hpi_tuner_get_hd_radio_signal_blend(u32 h_control, u32 *pblend); |
1636 | u32 h_control, u32 *pblend); | ||
1637 | 1461 | ||
1638 | u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, | 1462 | u16 hpi_tuner_set_hd_radio_signal_blend(u32 h_control, const u32 blend); |
1639 | u32 h_control, const u32 blend); | ||
1640 | 1463 | ||
1641 | /****************************/ | 1464 | /***************/ |
1642 | /* PADs control */ | 1465 | /* PAD control */ |
1643 | /****************************/ | 1466 | /***************/ |
1644 | 1467 | ||
1645 | u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys, | 1468 | u16 hpi_pad_get_channel_name(u32 h_control, char *psz_string, |
1646 | u32 h_control, char *psz_string, const u32 string_length); | 1469 | const u32 string_length); |
1647 | 1470 | ||
1648 | u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1471 | u16 hpi_pad_get_artist(u32 h_control, char *psz_string, |
1649 | char *psz_string, const u32 string_length); | 1472 | const u32 string_length); |
1650 | 1473 | ||
1651 | u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1474 | u16 hpi_pad_get_title(u32 h_control, char *psz_string, |
1652 | char *psz_string, const u32 string_length); | 1475 | const u32 string_length); |
1653 | 1476 | ||
1654 | u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1477 | u16 hpi_pad_get_comment(u32 h_control, char *psz_string, |
1655 | char *psz_string, const u32 string_length); | 1478 | const u32 string_length); |
1656 | 1479 | ||
1657 | u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys, | 1480 | u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY); |
1658 | u32 h_control, u32 *ppTY); | ||
1659 | 1481 | ||
1660 | u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1482 | u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI); |
1661 | u32 *ppI); | ||
1662 | 1483 | ||
1663 | u16 HPI_PAD__get_program_type_string(const struct hpi_hsubsys *ph_subsys, | 1484 | u16 hpi_pad_get_program_type_string(u32 h_control, const u32 data_type, |
1664 | u32 h_control, const u32 data_type, const u32 pTY, char *psz_string, | 1485 | const u32 pTY, char *psz_string, const u32 string_length); |
1665 | const u32 string_length); | ||
1666 | 1486 | ||
1667 | /****************************/ | 1487 | /****************************/ |
1668 | /* AES/EBU Receiver control */ | 1488 | /* AES/EBU Receiver control */ |
1669 | /****************************/ | 1489 | /****************************/ |
1670 | u16 HPI_AESEBU__receiver_query_format(const struct hpi_hsubsys *ph_subsys, | 1490 | u16 hpi_aesebu_receiver_query_format(const u32 h_aes_rx, const u32 index, |
1671 | const u32 h_aes_rx, const u32 index, u16 *pw_format); | 1491 | u16 *pw_format); |
1672 | 1492 | ||
1673 | u16 HPI_AESEBU__receiver_set_format(const struct hpi_hsubsys *ph_subsys, | 1493 | u16 hpi_aesebu_receiver_set_format(u32 h_control, u16 source); |
1674 | u32 h_control, u16 source); | ||
1675 | 1494 | ||
1676 | u16 HPI_AESEBU__receiver_get_format(const struct hpi_hsubsys *ph_subsys, | 1495 | u16 hpi_aesebu_receiver_get_format(u32 h_control, u16 *pw_source); |
1677 | u32 h_control, u16 *pw_source); | ||
1678 | 1496 | ||
1679 | u16 HPI_AESEBU__receiver_get_sample_rate(const struct hpi_hsubsys *ph_subsys, | 1497 | u16 hpi_aesebu_receiver_get_sample_rate(u32 h_control, u32 *psample_rate); |
1680 | u32 h_control, u32 *psample_rate); | ||
1681 | 1498 | ||
1682 | u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys, | 1499 | u16 hpi_aesebu_receiver_get_user_data(u32 h_control, u16 index, u16 *pw_data); |
1683 | u32 h_control, u16 index, u16 *pw_data); | ||
1684 | 1500 | ||
1685 | u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys | 1501 | u16 hpi_aesebu_receiver_get_channel_status(u32 h_control, u16 index, |
1686 | *ph_subsys, u32 h_control, u16 index, u16 *pw_data); | 1502 | u16 *pw_data); |
1687 | 1503 | ||
1688 | u16 HPI_AESEBU__receiver_get_error_status(const struct hpi_hsubsys *ph_subsys, | 1504 | u16 hpi_aesebu_receiver_get_error_status(u32 h_control, u16 *pw_error_data); |
1689 | u32 h_control, u16 *pw_error_data); | ||
1690 | 1505 | ||
1691 | /*******************************/ | 1506 | /*******************************/ |
1692 | /* AES/EBU Transmitter control */ | 1507 | /* AES/EBU Transmitter control */ |
1693 | /*******************************/ | 1508 | /*******************************/ |
1694 | u16 HPI_AESEBU__transmitter_set_sample_rate(const struct hpi_hsubsys | 1509 | u16 hpi_aesebu_transmitter_set_sample_rate(u32 h_control, u32 sample_rate); |
1695 | *ph_subsys, u32 h_control, u32 sample_rate); | ||
1696 | 1510 | ||
1697 | u16 HPI_AESEBU__transmitter_set_user_data(const struct hpi_hsubsys *ph_subsys, | 1511 | u16 hpi_aesebu_transmitter_set_user_data(u32 h_control, u16 index, u16 data); |
1698 | u32 h_control, u16 index, u16 data); | ||
1699 | 1512 | ||
1700 | u16 HPI_AESEBU__transmitter_set_channel_status(const struct hpi_hsubsys | 1513 | u16 hpi_aesebu_transmitter_set_channel_status(u32 h_control, u16 index, |
1701 | *ph_subsys, u32 h_control, u16 index, u16 data); | 1514 | u16 data); |
1702 | 1515 | ||
1703 | u16 HPI_AESEBU__transmitter_get_channel_status(const struct hpi_hsubsys | 1516 | u16 hpi_aesebu_transmitter_get_channel_status(u32 h_control, u16 index, |
1704 | *ph_subsys, u32 h_control, u16 index, u16 *pw_data); | 1517 | u16 *pw_data); |
1705 | 1518 | ||
1706 | u16 HPI_AESEBU__transmitter_query_format(const struct hpi_hsubsys *ph_subsys, | 1519 | u16 hpi_aesebu_transmitter_query_format(const u32 h_aes_tx, const u32 index, |
1707 | const u32 h_aes_tx, const u32 index, u16 *pw_format); | 1520 | u16 *pw_format); |
1708 | 1521 | ||
1709 | u16 HPI_AESEBU__transmitter_set_format(const struct hpi_hsubsys *ph_subsys, | 1522 | u16 hpi_aesebu_transmitter_set_format(u32 h_control, u16 output_format); |
1710 | u32 h_control, u16 output_format); | ||
1711 | 1523 | ||
1712 | u16 HPI_AESEBU__transmitter_get_format(const struct hpi_hsubsys *ph_subsys, | 1524 | u16 hpi_aesebu_transmitter_get_format(u32 h_control, u16 *pw_output_format); |
1713 | u32 h_control, u16 *pw_output_format); | ||
1714 | 1525 | ||
1715 | /***********************/ | 1526 | /***********************/ |
1716 | /* multiplexer control */ | 1527 | /* Multiplexer control */ |
1717 | /***********************/ | 1528 | /***********************/ |
1718 | u16 hpi_multiplexer_set_source(const struct hpi_hsubsys *ph_subsys, | 1529 | u16 hpi_multiplexer_set_source(u32 h_control, u16 source_node_type, |
1719 | u32 h_control, u16 source_node_type, u16 source_node_index); | 1530 | u16 source_node_index); |
1720 | |||
1721 | u16 hpi_multiplexer_get_source(const struct hpi_hsubsys *ph_subsys, | ||
1722 | u32 h_control, u16 *source_node_type, u16 *source_node_index); | ||
1723 | 1531 | ||
1724 | u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys, | 1532 | u16 hpi_multiplexer_get_source(u32 h_control, u16 *source_node_type, |
1725 | u32 h_control, u16 index, u16 *source_node_type, | ||
1726 | u16 *source_node_index); | 1533 | u16 *source_node_index); |
1727 | 1534 | ||
1535 | u16 hpi_multiplexer_query_source(u32 h_control, u16 index, | ||
1536 | u16 *source_node_type, u16 *source_node_index); | ||
1537 | |||
1728 | /***************/ | 1538 | /***************/ |
1729 | /* VOX control */ | 1539 | /* Vox control */ |
1730 | /***************/ | 1540 | /***************/ |
1731 | u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1541 | u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB); |
1732 | short an_gain0_01dB); | ||
1733 | 1542 | ||
1734 | u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1543 | u16 hpi_vox_get_threshold(u32 h_control, short *an_gain0_01dB); |
1735 | short *an_gain0_01dB); | ||
1736 | 1544 | ||
1737 | /*********************/ | 1545 | /*********************/ |
1738 | /* Bitstream control */ | 1546 | /* Bitstream control */ |
1739 | /*********************/ | 1547 | /*********************/ |
1740 | u16 hpi_bitstream_set_clock_edge(const struct hpi_hsubsys *ph_subsys, | 1548 | u16 hpi_bitstream_set_clock_edge(u32 h_control, u16 edge_type); |
1741 | u32 h_control, u16 edge_type); | ||
1742 | 1549 | ||
1743 | u16 hpi_bitstream_set_data_polarity(const struct hpi_hsubsys *ph_subsys, | 1550 | u16 hpi_bitstream_set_data_polarity(u32 h_control, u16 polarity); |
1744 | u32 h_control, u16 polarity); | ||
1745 | 1551 | ||
1746 | u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys, | 1552 | u16 hpi_bitstream_get_activity(u32 h_control, u16 *pw_clk_activity, |
1747 | u32 h_control, u16 *pw_clk_activity, u16 *pw_data_activity); | 1553 | u16 *pw_data_activity); |
1748 | 1554 | ||
1749 | /***********************/ | 1555 | /***********************/ |
1750 | /* SampleClock control */ | 1556 | /* SampleClock control */ |
1751 | /***********************/ | 1557 | /***********************/ |
1752 | 1558 | ||
1753 | u16 hpi_sample_clock_query_source(const struct hpi_hsubsys *ph_subsys, | 1559 | u16 hpi_sample_clock_query_source(const u32 h_clock, const u32 index, |
1754 | const u32 h_clock, const u32 index, u16 *pw_source); | 1560 | u16 *pw_source); |
1755 | 1561 | ||
1756 | u16 hpi_sample_clock_set_source(const struct hpi_hsubsys *ph_subsys, | 1562 | u16 hpi_sample_clock_set_source(u32 h_control, u16 source); |
1757 | u32 h_control, u16 source); | ||
1758 | 1563 | ||
1759 | u16 hpi_sample_clock_get_source(const struct hpi_hsubsys *ph_subsys, | 1564 | u16 hpi_sample_clock_get_source(u32 h_control, u16 *pw_source); |
1760 | u32 h_control, u16 *pw_source); | ||
1761 | 1565 | ||
1762 | u16 hpi_sample_clock_query_source_index(const struct hpi_hsubsys *ph_subsys, | 1566 | u16 hpi_sample_clock_query_source_index(const u32 h_clock, const u32 index, |
1763 | const u32 h_clock, const u32 index, const u32 source, | 1567 | const u32 source, u16 *pw_source_index); |
1764 | u16 *pw_source_index); | ||
1765 | 1568 | ||
1766 | u16 hpi_sample_clock_set_source_index(const struct hpi_hsubsys *ph_subsys, | 1569 | u16 hpi_sample_clock_set_source_index(u32 h_control, u16 source_index); |
1767 | u32 h_control, u16 source_index); | ||
1768 | 1570 | ||
1769 | u16 hpi_sample_clock_get_source_index(const struct hpi_hsubsys *ph_subsys, | 1571 | u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index); |
1770 | u32 h_control, u16 *pw_source_index); | ||
1771 | 1572 | ||
1772 | u16 hpi_sample_clock_get_sample_rate(const struct hpi_hsubsys *ph_subsys, | 1573 | u16 hpi_sample_clock_get_sample_rate(u32 h_control, u32 *psample_rate); |
1773 | u32 h_control, u32 *psample_rate); | ||
1774 | 1574 | ||
1775 | u16 hpi_sample_clock_query_local_rate(const struct hpi_hsubsys *ph_subsys, | 1575 | u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index, |
1776 | const u32 h_clock, const u32 index, u32 *psource); | 1576 | u32 *psource); |
1777 | 1577 | ||
1778 | u16 hpi_sample_clock_set_local_rate(const struct hpi_hsubsys *ph_subsys, | 1578 | u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate); |
1779 | u32 h_control, u32 sample_rate); | ||
1780 | 1579 | ||
1781 | u16 hpi_sample_clock_get_local_rate(const struct hpi_hsubsys *ph_subsys, | 1580 | u16 hpi_sample_clock_get_local_rate(u32 h_control, u32 *psample_rate); |
1782 | u32 h_control, u32 *psample_rate); | ||
1783 | 1581 | ||
1784 | u16 hpi_sample_clock_set_auto(const struct hpi_hsubsys *ph_subsys, | 1582 | u16 hpi_sample_clock_set_auto(u32 h_control, u32 enable); |
1785 | u32 h_control, u32 enable); | ||
1786 | 1583 | ||
1787 | u16 hpi_sample_clock_get_auto(const struct hpi_hsubsys *ph_subsys, | 1584 | u16 hpi_sample_clock_get_auto(u32 h_control, u32 *penable); |
1788 | u32 h_control, u32 *penable); | ||
1789 | 1585 | ||
1790 | u16 hpi_sample_clock_set_local_rate_lock(const struct hpi_hsubsys *ph_subsys, | 1586 | u16 hpi_sample_clock_set_local_rate_lock(u32 h_control, u32 lock); |
1791 | u32 h_control, u32 lock); | ||
1792 | 1587 | ||
1793 | u16 hpi_sample_clock_get_local_rate_lock(const struct hpi_hsubsys *ph_subsys, | 1588 | u16 hpi_sample_clock_get_local_rate_lock(u32 h_control, u32 *plock); |
1794 | u32 h_control, u32 *plock); | ||
1795 | 1589 | ||
1796 | /***********************/ | 1590 | /***********************/ |
1797 | /* Microphone control */ | 1591 | /* Microphone control */ |
1798 | /***********************/ | 1592 | /***********************/ |
1799 | u16 hpi_microphone_set_phantom_power(const struct hpi_hsubsys *ph_subsys, | 1593 | u16 hpi_microphone_set_phantom_power(u32 h_control, u16 on_off); |
1800 | u32 h_control, u16 on_off); | ||
1801 | 1594 | ||
1802 | u16 hpi_microphone_get_phantom_power(const struct hpi_hsubsys *ph_subsys, | 1595 | u16 hpi_microphone_get_phantom_power(u32 h_control, u16 *pw_on_off); |
1803 | u32 h_control, u16 *pw_on_off); | ||
1804 | 1596 | ||
1805 | /******************************* | 1597 | /********************************/ |
1806 | Parametric Equalizer control | 1598 | /* Parametric Equalizer control */ |
1807 | *******************************/ | 1599 | /********************************/ |
1808 | u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys, | 1600 | u16 hpi_parametric_eq_get_info(u32 h_control, u16 *pw_number_of_bands, |
1809 | u32 h_control, u16 *pw_number_of_bands, u16 *pw_enabled); | 1601 | u16 *pw_enabled); |
1810 | 1602 | ||
1811 | u16 hpi_parametricEQ__set_state(const struct hpi_hsubsys *ph_subsys, | 1603 | u16 hpi_parametric_eq_set_state(u32 h_control, u16 on_off); |
1812 | u32 h_control, u16 on_off); | ||
1813 | 1604 | ||
1814 | u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys, | 1605 | u16 hpi_parametric_eq_set_band(u32 h_control, u16 index, u16 type, |
1815 | u32 h_control, u16 index, u16 type, u32 frequency_hz, short q100, | 1606 | u32 frequency_hz, short q100, short gain0_01dB); |
1816 | short gain0_01dB); | ||
1817 | 1607 | ||
1818 | u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys, | 1608 | u16 hpi_parametric_eq_get_band(u32 h_control, u16 index, u16 *pn_type, |
1819 | u32 h_control, u16 index, u16 *pn_type, u32 *pfrequency_hz, | 1609 | u32 *pfrequency_hz, short *pnQ100, short *pn_gain0_01dB); |
1820 | short *pnQ100, short *pn_gain0_01dB); | ||
1821 | 1610 | ||
1822 | u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys, | 1611 | u16 hpi_parametric_eq_get_coeffs(u32 h_control, u16 index, short coeffs[5] |
1823 | u32 h_control, u16 index, short coeffs[5] | ||
1824 | ); | 1612 | ); |
1825 | 1613 | ||
1826 | /******************************* | 1614 | /*******************************/ |
1827 | Compressor Expander control | 1615 | /* Compressor Expander control */ |
1828 | *******************************/ | 1616 | /*******************************/ |
1829 | |||
1830 | u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys, | ||
1831 | u32 h_control, u32 on); | ||
1832 | |||
1833 | u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys, | ||
1834 | u32 h_control, u32 *pon); | ||
1835 | |||
1836 | u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys, | ||
1837 | u32 h_control, short makeup_gain0_01dB); | ||
1838 | |||
1839 | u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys, | ||
1840 | u32 h_control, short *pn_makeup_gain0_01dB); | ||
1841 | |||
1842 | u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys | ||
1843 | *ph_subsys, u32 h_control, u32 index, u32 attack); | ||
1844 | |||
1845 | u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys | ||
1846 | *ph_subsys, u32 h_control, u32 index, u32 *pw_attack); | ||
1847 | |||
1848 | u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys, | ||
1849 | u32 h_control, u32 index, u32 decay); | ||
1850 | |||
1851 | u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys, | ||
1852 | u32 h_control, u32 index, u32 *pw_decay); | ||
1853 | |||
1854 | u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys, | ||
1855 | u32 h_control, u32 index, short threshold0_01dB); | ||
1856 | |||
1857 | u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys, | ||
1858 | u32 h_control, u32 index, short *pn_threshold0_01dB); | ||
1859 | |||
1860 | u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys, | ||
1861 | u32 h_control, u32 index, u32 ratio100); | ||
1862 | |||
1863 | u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys, | ||
1864 | u32 h_control, u32 index, u32 *pw_ratio100); | ||
1865 | |||
1866 | /******************************* | ||
1867 | Cobranet HMI control | ||
1868 | *******************************/ | ||
1869 | u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control, | ||
1870 | u32 hmi_address, u32 byte_count, u8 *pb_data); | ||
1871 | |||
1872 | u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control, | ||
1873 | u32 hmi_address, u32 max_byte_count, u32 *pbyte_count, u8 *pb_data); | ||
1874 | |||
1875 | u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys, | ||
1876 | u32 h_control, u32 *pstatus, u32 *preadable_size, | ||
1877 | u32 *pwriteable_size); | ||
1878 | |||
1879 | /*Read the current IP address | ||
1880 | */ | ||
1881 | u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys, | ||
1882 | u32 h_control, u32 *pi_paddress); | ||
1883 | |||
1884 | /* Write the current IP address | ||
1885 | */ | ||
1886 | u16 hpi_cobranet_setI_paddress(const struct hpi_hsubsys *ph_subsys, | ||
1887 | u32 h_control, u32 i_paddress); | ||
1888 | |||
1889 | /* Read the static IP address | ||
1890 | */ | ||
1891 | u16 hpi_cobranet_get_staticI_paddress(const struct hpi_hsubsys *ph_subsys, | ||
1892 | u32 h_control, u32 *pi_paddress); | ||
1893 | 1617 | ||
1894 | /* Write the static IP address | 1618 | u16 hpi_compander_set_enable(u32 h_control, u32 on); |
1895 | */ | ||
1896 | u16 hpi_cobranet_set_staticI_paddress(const struct hpi_hsubsys *ph_subsys, | ||
1897 | u32 h_control, u32 i_paddress); | ||
1898 | 1619 | ||
1899 | /* Read the MAC address | 1620 | u16 hpi_compander_get_enable(u32 h_control, u32 *pon); |
1900 | */ | ||
1901 | u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys, | ||
1902 | u32 h_control, u32 *pmAC_MS_bs, u32 *pmAC_LS_bs); | ||
1903 | 1621 | ||
1904 | /******************************* | 1622 | u16 hpi_compander_set_makeup_gain(u32 h_control, short makeup_gain0_01dB); |
1905 | Tone Detector control | ||
1906 | *******************************/ | ||
1907 | u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys, u32 hC, | ||
1908 | u32 *state); | ||
1909 | 1623 | ||
1910 | u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys, u32 hC, | 1624 | u16 hpi_compander_get_makeup_gain(u32 h_control, short *pn_makeup_gain0_01dB); |
1911 | u32 enable); | ||
1912 | 1625 | ||
1913 | u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys, u32 hC, | 1626 | u16 hpi_compander_set_attack_time_constant(u32 h_control, u32 index, |
1914 | u32 *enable); | 1627 | u32 attack); |
1915 | 1628 | ||
1916 | u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, | 1629 | u16 hpi_compander_get_attack_time_constant(u32 h_control, u32 index, |
1917 | u32 hC, u32 event_enable); | 1630 | u32 *pw_attack); |
1918 | 1631 | ||
1919 | u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, | 1632 | u16 hpi_compander_set_decay_time_constant(u32 h_control, u32 index, |
1920 | u32 hC, u32 *event_enable); | 1633 | u32 decay); |
1921 | 1634 | ||
1922 | u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, | 1635 | u16 hpi_compander_get_decay_time_constant(u32 h_control, u32 index, |
1923 | u32 hC, int threshold); | 1636 | u32 *pw_decay); |
1924 | 1637 | ||
1925 | u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, | 1638 | u16 hpi_compander_set_threshold(u32 h_control, u32 index, |
1926 | u32 hC, int *threshold); | 1639 | short threshold0_01dB); |
1927 | 1640 | ||
1928 | u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys, | 1641 | u16 hpi_compander_get_threshold(u32 h_control, u32 index, |
1929 | u32 hC, u32 index, u32 *frequency); | 1642 | short *pn_threshold0_01dB); |
1930 | 1643 | ||
1931 | /******************************* | 1644 | u16 hpi_compander_set_ratio(u32 h_control, u32 index, u32 ratio100); |
1932 | Silence Detector control | ||
1933 | *******************************/ | ||
1934 | u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys, | ||
1935 | u32 hC, u32 *state); | ||
1936 | 1645 | ||
1937 | u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys, | 1646 | u16 hpi_compander_get_ratio(u32 h_control, u32 index, u32 *pw_ratio100); |
1938 | u32 hC, u32 enable); | ||
1939 | 1647 | ||
1940 | u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys, | 1648 | /********************/ |
1941 | u32 hC, u32 *enable); | 1649 | /* Cobranet control */ |
1650 | /********************/ | ||
1651 | u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count, | ||
1652 | u8 *pb_data); | ||
1942 | 1653 | ||
1943 | u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, | 1654 | u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count, |
1944 | u32 hC, u32 event_enable); | 1655 | u32 *pbyte_count, u8 *pb_data); |
1945 | 1656 | ||
1946 | u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, | 1657 | u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus, |
1947 | u32 hC, u32 *event_enable); | 1658 | u32 *preadable_size, u32 *pwriteable_size); |
1948 | 1659 | ||
1949 | u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys, | 1660 | u16 hpi_cobranet_get_ip_address(u32 h_control, u32 *pdw_ip_address); |
1950 | u32 hC, u32 delay); | ||
1951 | 1661 | ||
1952 | u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys, | 1662 | u16 hpi_cobranet_set_ip_address(u32 h_control, u32 dw_ip_address); |
1953 | u32 hC, u32 *delay); | ||
1954 | 1663 | ||
1955 | u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, | 1664 | u16 hpi_cobranet_get_static_ip_address(u32 h_control, u32 *pdw_ip_address); |
1956 | u32 hC, int threshold); | ||
1957 | 1665 | ||
1958 | u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, | 1666 | u16 hpi_cobranet_set_static_ip_address(u32 h_control, u32 dw_ip_address); |
1959 | u32 hC, int *threshold); | ||
1960 | 1667 | ||
1961 | /******************************* | 1668 | u16 hpi_cobranet_get_macaddress(u32 h_control, u32 *p_mac_msbs, |
1962 | Universal control | 1669 | u32 *p_mac_lsbs); |
1963 | *******************************/ | ||
1964 | u16 hpi_entity_find_next(struct hpi_entity *container_entity, | ||
1965 | enum e_entity_type type, enum e_entity_role role, int recursive_flag, | ||
1966 | struct hpi_entity **current_match); | ||
1967 | 1670 | ||
1968 | u16 hpi_entity_copy_value_from(struct hpi_entity *entity, | 1671 | /*************************/ |
1969 | enum e_entity_type type, size_t item_count, void *value_dst_p); | 1672 | /* Tone Detector control */ |
1673 | /*************************/ | ||
1674 | u16 hpi_tone_detector_get_state(u32 hC, u32 *state); | ||
1970 | 1675 | ||
1971 | u16 hpi_entity_unpack(struct hpi_entity *entity, enum e_entity_type *type, | 1676 | u16 hpi_tone_detector_set_enable(u32 hC, u32 enable); |
1972 | size_t *items, enum e_entity_role *role, void **value); | ||
1973 | 1677 | ||
1974 | u16 hpi_entity_alloc_and_pack(const enum e_entity_type type, | 1678 | u16 hpi_tone_detector_get_enable(u32 hC, u32 *enable); |
1975 | const size_t item_count, const enum e_entity_role role, void *value, | ||
1976 | struct hpi_entity **entity); | ||
1977 | 1679 | ||
1978 | void hpi_entity_free(struct hpi_entity *entity); | 1680 | u16 hpi_tone_detector_set_event_enable(u32 hC, u32 event_enable); |
1979 | 1681 | ||
1980 | u16 hpi_universal_info(const struct hpi_hsubsys *ph_subsys, u32 hC, | 1682 | u16 hpi_tone_detector_get_event_enable(u32 hC, u32 *event_enable); |
1981 | struct hpi_entity **info); | ||
1982 | 1683 | ||
1983 | u16 hpi_universal_get(const struct hpi_hsubsys *ph_subsys, u32 hC, | 1684 | u16 hpi_tone_detector_set_threshold(u32 hC, int threshold); |
1984 | struct hpi_entity **value); | ||
1985 | 1685 | ||
1986 | u16 hpi_universal_set(const struct hpi_hsubsys *ph_subsys, u32 hC, | 1686 | u16 hpi_tone_detector_get_threshold(u32 hC, int *threshold); |
1987 | struct hpi_entity *value); | ||
1988 | 1687 | ||
1989 | /*/////////// */ | 1688 | u16 hpi_tone_detector_get_frequency(u32 hC, u32 index, u32 *frequency); |
1990 | /* DSP CLOCK */ | ||
1991 | /*/////////// */ | ||
1992 | u16 hpi_clock_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | ||
1993 | u32 *ph_dsp_clock); | ||
1994 | 1689 | ||
1995 | u16 hpi_clock_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock, | 1690 | /****************************/ |
1996 | u16 hour, u16 minute, u16 second, u16 milli_second); | 1691 | /* Silence Detector control */ |
1692 | /****************************/ | ||
1693 | u16 hpi_silence_detector_get_state(u32 hC, u32 *state); | ||
1997 | 1694 | ||
1998 | u16 hpi_clock_get_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock, | 1695 | u16 hpi_silence_detector_set_enable(u32 hC, u32 enable); |
1999 | u16 *pw_hour, u16 *pw_minute, u16 *pw_second, u16 *pw_milli_second); | ||
2000 | 1696 | ||
2001 | /*/////////// */ | 1697 | u16 hpi_silence_detector_get_enable(u32 hC, u32 *enable); |
2002 | /* PROFILE */ | ||
2003 | /*/////////// */ | ||
2004 | u16 hpi_profile_open_all(const struct hpi_hsubsys *ph_subsys, | ||
2005 | u16 adapter_index, u16 profile_index, u32 *ph_profile, | ||
2006 | u16 *pw_max_profiles); | ||
2007 | 1698 | ||
2008 | u16 hpi_profile_get(const struct hpi_hsubsys *ph_subsys, u32 h_profile, | 1699 | u16 hpi_silence_detector_set_event_enable(u32 hC, u32 event_enable); |
2009 | u16 index, u16 *pw_seconds, u32 *pmicro_seconds, u32 *pcall_count, | ||
2010 | u32 *pmax_micro_seconds, u32 *pmin_micro_seconds); | ||
2011 | 1700 | ||
2012 | u16 hpi_profile_start_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile); | 1701 | u16 hpi_silence_detector_get_event_enable(u32 hC, u32 *event_enable); |
2013 | 1702 | ||
2014 | u16 hpi_profile_stop_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile); | 1703 | u16 hpi_silence_detector_set_delay(u32 hC, u32 delay); |
2015 | 1704 | ||
2016 | u16 hpi_profile_get_name(const struct hpi_hsubsys *ph_subsys, u32 h_profile, | 1705 | u16 hpi_silence_detector_get_delay(u32 hC, u32 *delay); |
2017 | u16 index, char *sz_profile_name, u16 profile_name_length); | ||
2018 | 1706 | ||
2019 | u16 hpi_profile_get_utilization(const struct hpi_hsubsys *ph_subsys, | 1707 | u16 hpi_silence_detector_set_threshold(u32 hC, int threshold); |
2020 | u32 h_profile, u32 *putilization); | ||
2021 | 1708 | ||
2022 | /*//////////////////// */ | 1709 | u16 hpi_silence_detector_get_threshold(u32 hC, int *threshold); |
2023 | /* UTILITY functions */ | 1710 | /*********************/ |
1711 | /* Utility functions */ | ||
1712 | /*********************/ | ||
2024 | 1713 | ||
2025 | u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, | 1714 | u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, |
2026 | u32 sample_rate, u32 bit_rate, u32 attributes); | 1715 | u32 sample_rate, u32 bit_rate, u32 attributes); |
2027 | 1716 | ||
2028 | /* Until it's verified, this function is for Windows OSs only */ | 1717 | #endif /*_HPI_H_ */ |
2029 | |||
2030 | #endif /*_H_HPI_ */ | ||
2031 | /* | ||
2032 | /////////////////////////////////////////////////////////////////////////////// | ||
2033 | // See CVS for history. Last complete set in rev 1.146 | ||
2034 | //////////////////////////////////////////////////////////////////////////////// | ||
2035 | */ | ||
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c index 1b9bf9395cfe..3e3c2ef6efd8 100644 --- a/sound/pci/asihpi/hpi6000.c +++ b/sound/pci/asihpi/hpi6000.c | |||
@@ -43,16 +43,17 @@ | |||
43 | #define HPI_HIF_ERROR_MASK 0x4000 | 43 | #define HPI_HIF_ERROR_MASK 0x4000 |
44 | 44 | ||
45 | /* HPI6000 specific error codes */ | 45 | /* HPI6000 specific error codes */ |
46 | #define HPI6000_ERROR_BASE 900 /* not actually used anywhere */ | ||
46 | 47 | ||
47 | #define HPI6000_ERROR_BASE 900 | 48 | /* operational/messaging errors */ |
48 | #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 | 49 | #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT 901 |
49 | #define HPI6000_ERROR_MSG_RESP_SEND_MSG_ACK 902 | 50 | |
50 | #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 | 51 | #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK 903 |
51 | #define HPI6000_ERROR_MSG_GET_ADR 904 | 52 | #define HPI6000_ERROR_MSG_GET_ADR 904 |
52 | #define HPI6000_ERROR_RESP_GET_ADR 905 | 53 | #define HPI6000_ERROR_RESP_GET_ADR 905 |
53 | #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906 | 54 | #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32 906 |
54 | #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907 | 55 | #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32 907 |
55 | #define HPI6000_ERROR_MSG_INVALID_DSP_INDEX 908 | 56 | |
56 | #define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909 | 57 | #define HPI6000_ERROR_CONTROL_CACHE_PARAMS 909 |
57 | 58 | ||
58 | #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911 | 59 | #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT 911 |
@@ -62,7 +63,6 @@ | |||
62 | #define HPI6000_ERROR_SEND_DATA_CMD 915 | 63 | #define HPI6000_ERROR_SEND_DATA_CMD 915 |
63 | #define HPI6000_ERROR_SEND_DATA_WRITE 916 | 64 | #define HPI6000_ERROR_SEND_DATA_WRITE 916 |
64 | #define HPI6000_ERROR_SEND_DATA_IDLECMD 917 | 65 | #define HPI6000_ERROR_SEND_DATA_IDLECMD 917 |
65 | #define HPI6000_ERROR_SEND_DATA_VERIFY 918 | ||
66 | 66 | ||
67 | #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921 | 67 | #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT 921 |
68 | #define HPI6000_ERROR_GET_DATA_ACK 922 | 68 | #define HPI6000_ERROR_GET_DATA_ACK 922 |
@@ -76,9 +76,8 @@ | |||
76 | 76 | ||
77 | #define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961 | 77 | #define HPI6000_ERROR_MSG_RESP_GETRESPCMD 961 |
78 | #define HPI6000_ERROR_MSG_RESP_IDLECMD 962 | 78 | #define HPI6000_ERROR_MSG_RESP_IDLECMD 962 |
79 | #define HPI6000_ERROR_MSG_RESP_BLOCKVERIFY32 963 | ||
80 | 79 | ||
81 | /* adapter init errors */ | 80 | /* Initialisation/bootload errors */ |
82 | #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930 | 81 | #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID 930 |
83 | 82 | ||
84 | /* can't access PCI2040 */ | 83 | /* can't access PCI2040 */ |
@@ -210,6 +209,8 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao, | |||
210 | static short create_adapter_obj(struct hpi_adapter_obj *pao, | 209 | static short create_adapter_obj(struct hpi_adapter_obj *pao, |
211 | u32 *pos_error_code); | 210 | u32 *pos_error_code); |
212 | 211 | ||
212 | static void delete_adapter_obj(struct hpi_adapter_obj *pao); | ||
213 | |||
213 | /* local globals */ | 214 | /* local globals */ |
214 | 215 | ||
215 | static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */ | 216 | static u16 gw_pci_read_asserts; /* used to count PCI2040 errors */ |
@@ -217,17 +218,7 @@ static u16 gw_pci_write_asserts; /* used to count PCI2040 errors */ | |||
217 | 218 | ||
218 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | 219 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) |
219 | { | 220 | { |
220 | |||
221 | switch (phm->function) { | 221 | switch (phm->function) { |
222 | case HPI_SUBSYS_OPEN: | ||
223 | case HPI_SUBSYS_CLOSE: | ||
224 | case HPI_SUBSYS_GET_INFO: | ||
225 | case HPI_SUBSYS_DRIVER_UNLOAD: | ||
226 | case HPI_SUBSYS_DRIVER_LOAD: | ||
227 | case HPI_SUBSYS_FIND_ADAPTERS: | ||
228 | /* messages that should not get here */ | ||
229 | phr->error = HPI_ERROR_UNIMPLEMENTED; | ||
230 | break; | ||
231 | case HPI_SUBSYS_CREATE_ADAPTER: | 222 | case HPI_SUBSYS_CREATE_ADAPTER: |
232 | subsys_create_adapter(phm, phr); | 223 | subsys_create_adapter(phm, phr); |
233 | break; | 224 | break; |
@@ -243,7 +234,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | |||
243 | static void control_message(struct hpi_adapter_obj *pao, | 234 | static void control_message(struct hpi_adapter_obj *pao, |
244 | struct hpi_message *phm, struct hpi_response *phr) | 235 | struct hpi_message *phm, struct hpi_response *phr) |
245 | { | 236 | { |
246 | |||
247 | switch (phm->function) { | 237 | switch (phm->function) { |
248 | case HPI_CONTROL_GET_STATE: | 238 | case HPI_CONTROL_GET_STATE: |
249 | if (pao->has_control_cache) { | 239 | if (pao->has_control_cache) { |
@@ -251,7 +241,13 @@ static void control_message(struct hpi_adapter_obj *pao, | |||
251 | err = hpi6000_update_control_cache(pao, phm); | 241 | err = hpi6000_update_control_cache(pao, phm); |
252 | 242 | ||
253 | if (err) { | 243 | if (err) { |
254 | phr->error = err; | 244 | if (err >= HPI_ERROR_BACKEND_BASE) { |
245 | phr->error = | ||
246 | HPI_ERROR_CONTROL_CACHING; | ||
247 | phr->specific_error = err; | ||
248 | } else { | ||
249 | phr->error = err; | ||
250 | } | ||
255 | break; | 251 | break; |
256 | } | 252 | } |
257 | 253 | ||
@@ -262,16 +258,15 @@ static void control_message(struct hpi_adapter_obj *pao, | |||
262 | } | 258 | } |
263 | hw_message(pao, phm, phr); | 259 | hw_message(pao, phm, phr); |
264 | break; | 260 | break; |
265 | case HPI_CONTROL_GET_INFO: | ||
266 | hw_message(pao, phm, phr); | ||
267 | break; | ||
268 | case HPI_CONTROL_SET_STATE: | 261 | case HPI_CONTROL_SET_STATE: |
269 | hw_message(pao, phm, phr); | 262 | hw_message(pao, phm, phr); |
270 | hpi_sync_control_cache(((struct hpi_hw_obj *)pao->priv)-> | 263 | hpi_cmn_control_cache_sync_to_msg(((struct hpi_hw_obj *)pao-> |
271 | p_cache, phm, phr); | 264 | priv)->p_cache, phm, phr); |
272 | break; | 265 | break; |
266 | |||
267 | case HPI_CONTROL_GET_INFO: | ||
273 | default: | 268 | default: |
274 | phr->error = HPI_ERROR_INVALID_FUNC; | 269 | hw_message(pao, phm, phr); |
275 | break; | 270 | break; |
276 | } | 271 | } |
277 | } | 272 | } |
@@ -280,26 +275,12 @@ static void adapter_message(struct hpi_adapter_obj *pao, | |||
280 | struct hpi_message *phm, struct hpi_response *phr) | 275 | struct hpi_message *phm, struct hpi_response *phr) |
281 | { | 276 | { |
282 | switch (phm->function) { | 277 | switch (phm->function) { |
283 | case HPI_ADAPTER_GET_INFO: | ||
284 | hw_message(pao, phm, phr); | ||
285 | break; | ||
286 | case HPI_ADAPTER_GET_ASSERT: | 278 | case HPI_ADAPTER_GET_ASSERT: |
287 | adapter_get_asserts(pao, phm, phr); | 279 | adapter_get_asserts(pao, phm, phr); |
288 | break; | 280 | break; |
289 | case HPI_ADAPTER_OPEN: | 281 | |
290 | case HPI_ADAPTER_CLOSE: | ||
291 | case HPI_ADAPTER_TEST_ASSERT: | ||
292 | case HPI_ADAPTER_SELFTEST: | ||
293 | case HPI_ADAPTER_GET_MODE: | ||
294 | case HPI_ADAPTER_SET_MODE: | ||
295 | case HPI_ADAPTER_FIND_OBJECT: | ||
296 | case HPI_ADAPTER_GET_PROPERTY: | ||
297 | case HPI_ADAPTER_SET_PROPERTY: | ||
298 | case HPI_ADAPTER_ENUM_PROPERTY: | ||
299 | hw_message(pao, phm, phr); | ||
300 | break; | ||
301 | default: | 282 | default: |
302 | phr->error = HPI_ERROR_INVALID_FUNC; | 283 | hw_message(pao, phm, phr); |
303 | break; | 284 | break; |
304 | } | 285 | } |
305 | } | 286 | } |
@@ -311,7 +292,7 @@ static void outstream_message(struct hpi_adapter_obj *pao, | |||
311 | case HPI_OSTREAM_HOSTBUFFER_ALLOC: | 292 | case HPI_OSTREAM_HOSTBUFFER_ALLOC: |
312 | case HPI_OSTREAM_HOSTBUFFER_FREE: | 293 | case HPI_OSTREAM_HOSTBUFFER_FREE: |
313 | /* Don't let these messages go to the HW function because | 294 | /* Don't let these messages go to the HW function because |
314 | * they're called without allocating the spinlock. | 295 | * they're called without locking the spinlock. |
315 | * For the HPI6000 adapters the HW would return | 296 | * For the HPI6000 adapters the HW would return |
316 | * HPI_ERROR_INVALID_FUNC anyway. | 297 | * HPI_ERROR_INVALID_FUNC anyway. |
317 | */ | 298 | */ |
@@ -331,7 +312,7 @@ static void instream_message(struct hpi_adapter_obj *pao, | |||
331 | case HPI_ISTREAM_HOSTBUFFER_ALLOC: | 312 | case HPI_ISTREAM_HOSTBUFFER_ALLOC: |
332 | case HPI_ISTREAM_HOSTBUFFER_FREE: | 313 | case HPI_ISTREAM_HOSTBUFFER_FREE: |
333 | /* Don't let these messages go to the HW function because | 314 | /* Don't let these messages go to the HW function because |
334 | * they're called without allocating the spinlock. | 315 | * they're called without locking the spinlock. |
335 | * For the HPI6000 adapters the HW would return | 316 | * For the HPI6000 adapters the HW would return |
336 | * HPI_ERROR_INVALID_FUNC anyway. | 317 | * HPI_ERROR_INVALID_FUNC anyway. |
337 | */ | 318 | */ |
@@ -355,7 +336,7 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr) | |||
355 | /* subsytem messages get executed by every HPI. */ | 336 | /* subsytem messages get executed by every HPI. */ |
356 | /* All other messages are ignored unless the adapter index matches */ | 337 | /* All other messages are ignored unless the adapter index matches */ |
357 | /* an adapter in the HPI */ | 338 | /* an adapter in the HPI */ |
358 | HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->object, phm->function); | 339 | /*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */ |
359 | 340 | ||
360 | /* if Dsp has crashed then do not communicate with it any more */ | 341 | /* if Dsp has crashed then do not communicate with it any more */ |
361 | if (phm->object != HPI_OBJ_SUBSYSTEM) { | 342 | if (phm->object != HPI_OBJ_SUBSYSTEM) { |
@@ -433,21 +414,13 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
433 | struct hpi_adapter_obj ao; | 414 | struct hpi_adapter_obj ao; |
434 | struct hpi_adapter_obj *pao; | 415 | struct hpi_adapter_obj *pao; |
435 | u32 os_error_code; | 416 | u32 os_error_code; |
436 | short error = 0; | 417 | u16 err = 0; |
437 | u32 dsp_index = 0; | 418 | u32 dsp_index = 0; |
438 | 419 | ||
439 | HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); | 420 | HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n"); |
440 | 421 | ||
441 | memset(&ao, 0, sizeof(ao)); | 422 | memset(&ao, 0, sizeof(ao)); |
442 | 423 | ||
443 | /* this HPI only creates adapters for TI/PCI2040 based devices */ | ||
444 | if (phm->u.s.resource.bus_type != HPI_BUS_PCI) | ||
445 | return; | ||
446 | if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI) | ||
447 | return; | ||
448 | if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_PCI2040) | ||
449 | return; | ||
450 | |||
451 | ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); | 424 | ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); |
452 | if (!ao.priv) { | 425 | if (!ao.priv) { |
453 | HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); | 426 | HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); |
@@ -456,16 +429,19 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
456 | } | 429 | } |
457 | 430 | ||
458 | /* create the adapter object based on the resource information */ | 431 | /* create the adapter object based on the resource information */ |
459 | /*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */ | ||
460 | ao.pci = *phm->u.s.resource.r.pci; | 432 | ao.pci = *phm->u.s.resource.r.pci; |
461 | 433 | ||
462 | error = create_adapter_obj(&ao, &os_error_code); | 434 | err = create_adapter_obj(&ao, &os_error_code); |
463 | if (!error) | 435 | if (err) { |
464 | error = hpi_add_adapter(&ao); | 436 | delete_adapter_obj(&ao); |
465 | if (error) { | 437 | if (err >= HPI_ERROR_BACKEND_BASE) { |
438 | phr->error = HPI_ERROR_DSP_BOOTLOAD; | ||
439 | phr->specific_error = err; | ||
440 | } else { | ||
441 | phr->error = err; | ||
442 | } | ||
443 | |||
466 | phr->u.s.data = os_error_code; | 444 | phr->u.s.data = os_error_code; |
467 | kfree(ao.priv); | ||
468 | phr->error = error; | ||
469 | return; | 445 | return; |
470 | } | 446 | } |
471 | /* need to update paParentAdapter */ | 447 | /* need to update paParentAdapter */ |
@@ -473,7 +449,7 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
473 | if (!pao) { | 449 | if (!pao) { |
474 | /* We just added this adapter, why can't we find it!? */ | 450 | /* We just added this adapter, why can't we find it!? */ |
475 | HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); | 451 | HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n"); |
476 | phr->error = 950; | 452 | phr->error = HPI_ERROR_BAD_ADAPTER; |
477 | return; | 453 | return; |
478 | } | 454 | } |
479 | 455 | ||
@@ -482,9 +458,8 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
482 | phw->ado[dsp_index].pa_parent_adapter = pao; | 458 | phw->ado[dsp_index].pa_parent_adapter = pao; |
483 | } | 459 | } |
484 | 460 | ||
485 | phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type; | 461 | phr->u.s.adapter_type = ao.adapter_type; |
486 | phr->u.s.adapter_index = ao.index; | 462 | phr->u.s.adapter_index = ao.index; |
487 | phr->u.s.num_adapters++; | ||
488 | phr->error = 0; | 463 | phr->error = 0; |
489 | } | 464 | } |
490 | 465 | ||
@@ -492,20 +467,13 @@ static void subsys_delete_adapter(struct hpi_message *phm, | |||
492 | struct hpi_response *phr) | 467 | struct hpi_response *phr) |
493 | { | 468 | { |
494 | struct hpi_adapter_obj *pao = NULL; | 469 | struct hpi_adapter_obj *pao = NULL; |
495 | struct hpi_hw_obj *phw; | ||
496 | 470 | ||
497 | pao = hpi_find_adapter(phm->adapter_index); | 471 | pao = hpi_find_adapter(phm->obj_index); |
498 | if (!pao) | 472 | if (!pao) |
499 | return; | 473 | return; |
500 | 474 | ||
501 | phw = (struct hpi_hw_obj *)pao->priv; | 475 | delete_adapter_obj(pao); |
502 | |||
503 | if (pao->has_control_cache) | ||
504 | hpi_free_control_cache(phw->p_cache); | ||
505 | |||
506 | hpi_delete_adapter(pao); | 476 | hpi_delete_adapter(pao); |
507 | kfree(phw); | ||
508 | |||
509 | phr->error = 0; | 477 | phr->error = 0; |
510 | } | 478 | } |
511 | 479 | ||
@@ -519,9 +487,6 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, | |||
519 | u32 control_cache_count = 0; | 487 | u32 control_cache_count = 0; |
520 | struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv; | 488 | struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv; |
521 | 489 | ||
522 | /* init error reporting */ | ||
523 | pao->dsp_crashed = 0; | ||
524 | |||
525 | /* The PCI2040 has the following address map */ | 490 | /* The PCI2040 has the following address map */ |
526 | /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */ | 491 | /* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */ |
527 | /* BAR1 - 32K = HPI registers on DSP */ | 492 | /* BAR1 - 32K = HPI registers on DSP */ |
@@ -575,36 +540,36 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, | |||
575 | /* get info about the adapter by asking the adapter */ | 540 | /* get info about the adapter by asking the adapter */ |
576 | /* send a HPI_ADAPTER_GET_INFO message */ | 541 | /* send a HPI_ADAPTER_GET_INFO message */ |
577 | { | 542 | { |
578 | struct hpi_message hM; | 543 | struct hpi_message hm; |
579 | struct hpi_response hR0; /* response from DSP 0 */ | 544 | struct hpi_response hr0; /* response from DSP 0 */ |
580 | struct hpi_response hR1; /* response from DSP 1 */ | 545 | struct hpi_response hr1; /* response from DSP 1 */ |
581 | u16 error = 0; | 546 | u16 error = 0; |
582 | 547 | ||
583 | HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); | 548 | HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n"); |
584 | memset(&hM, 0, sizeof(hM)); | 549 | memset(&hm, 0, sizeof(hm)); |
585 | hM.type = HPI_TYPE_MESSAGE; | 550 | hm.type = HPI_TYPE_MESSAGE; |
586 | hM.size = sizeof(struct hpi_message); | 551 | hm.size = sizeof(struct hpi_message); |
587 | hM.object = HPI_OBJ_ADAPTER; | 552 | hm.object = HPI_OBJ_ADAPTER; |
588 | hM.function = HPI_ADAPTER_GET_INFO; | 553 | hm.function = HPI_ADAPTER_GET_INFO; |
589 | hM.adapter_index = 0; | 554 | hm.adapter_index = 0; |
590 | memset(&hR0, 0, sizeof(hR0)); | 555 | memset(&hr0, 0, sizeof(hr0)); |
591 | memset(&hR1, 0, sizeof(hR1)); | 556 | memset(&hr1, 0, sizeof(hr1)); |
592 | hR0.size = sizeof(hR0); | 557 | hr0.size = sizeof(hr0); |
593 | hR1.size = sizeof(hR1); | 558 | hr1.size = sizeof(hr1); |
594 | 559 | ||
595 | error = hpi6000_message_response_sequence(pao, 0, &hM, &hR0); | 560 | error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0); |
596 | if (hR0.error) { | 561 | if (hr0.error) { |
597 | HPI_DEBUG_LOG(DEBUG, "message error %d\n", hR0.error); | 562 | HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error); |
598 | return hR0.error; | 563 | return hr0.error; |
599 | } | 564 | } |
600 | if (phw->num_dsp == 2) { | 565 | if (phw->num_dsp == 2) { |
601 | error = hpi6000_message_response_sequence(pao, 1, &hM, | 566 | error = hpi6000_message_response_sequence(pao, 1, &hm, |
602 | &hR1); | 567 | &hr1); |
603 | if (error) | 568 | if (error) |
604 | return error; | 569 | return error; |
605 | } | 570 | } |
606 | pao->adapter_type = hR0.u.a.adapter_type; | 571 | pao->adapter_type = hr0.u.ax.info.adapter_type; |
607 | pao->index = hR0.u.a.adapter_index; | 572 | pao->index = hr0.u.ax.info.adapter_index; |
608 | } | 573 | } |
609 | 574 | ||
610 | memset(&phw->control_cache[0], 0, | 575 | memset(&phw->control_cache[0], 0, |
@@ -618,22 +583,37 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao, | |||
618 | control_cache_count = | 583 | control_cache_count = |
619 | hpi_read_word(&phw->ado[0], | 584 | hpi_read_word(&phw->ado[0], |
620 | HPI_HIF_ADDR(control_cache_count)); | 585 | HPI_HIF_ADDR(control_cache_count)); |
621 | pao->has_control_cache = 1; | ||
622 | 586 | ||
623 | phw->p_cache = | 587 | phw->p_cache = |
624 | hpi_alloc_control_cache(control_cache_count, | 588 | hpi_alloc_control_cache(control_cache_count, |
625 | control_cache_size, (struct hpi_control_cache_info *) | 589 | control_cache_size, (unsigned char *) |
626 | &phw->control_cache[0] | 590 | &phw->control_cache[0] |
627 | ); | 591 | ); |
628 | if (!phw->p_cache) | 592 | if (phw->p_cache) |
629 | pao->has_control_cache = 0; | 593 | pao->has_control_cache = 1; |
630 | } else | 594 | } |
631 | pao->has_control_cache = 0; | ||
632 | 595 | ||
633 | HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", | 596 | HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", |
634 | pao->adapter_type, pao->index); | 597 | pao->adapter_type, pao->index); |
635 | pao->open = 0; /* upon creation the adapter is closed */ | 598 | pao->open = 0; /* upon creation the adapter is closed */ |
636 | return 0; | 599 | |
600 | if (phw->p_cache) | ||
601 | phw->p_cache->adap_idx = pao->index; | ||
602 | |||
603 | return hpi_add_adapter(pao); | ||
604 | } | ||
605 | |||
606 | static void delete_adapter_obj(struct hpi_adapter_obj *pao) | ||
607 | { | ||
608 | struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv; | ||
609 | |||
610 | if (pao->has_control_cache) | ||
611 | hpi_free_control_cache(phw->p_cache); | ||
612 | |||
613 | /* reset DSPs on adapter */ | ||
614 | iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET); | ||
615 | |||
616 | kfree(phw); | ||
637 | } | 617 | } |
638 | 618 | ||
639 | /************************************************************************/ | 619 | /************************************************************************/ |
@@ -645,11 +625,13 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao, | |||
645 | #ifndef HIDE_PCI_ASSERTS | 625 | #ifndef HIDE_PCI_ASSERTS |
646 | /* if we have PCI2040 asserts then collect them */ | 626 | /* if we have PCI2040 asserts then collect them */ |
647 | if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) { | 627 | if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) { |
648 | phr->u.a.serial_number = | 628 | phr->u.ax.assert.p1 = |
649 | gw_pci_read_asserts * 100 + gw_pci_write_asserts; | 629 | gw_pci_read_asserts * 100 + gw_pci_write_asserts; |
650 | phr->u.a.adapter_index = 1; /* assert count */ | 630 | phr->u.ax.assert.p2 = 0; |
651 | phr->u.a.adapter_type = -1; /* "dsp index" */ | 631 | phr->u.ax.assert.count = 1; /* assert count */ |
652 | strcpy(phr->u.a.sz_adapter_assert, "PCI2040 error"); | 632 | phr->u.ax.assert.dsp_index = -1; /* "dsp index" */ |
633 | strcpy(phr->u.ax.assert.sz_message, "PCI2040 error"); | ||
634 | phr->u.ax.assert.dsp_msg_addr = 0; | ||
653 | gw_pci_read_asserts = 0; | 635 | gw_pci_read_asserts = 0; |
654 | gw_pci_write_asserts = 0; | 636 | gw_pci_write_asserts = 0; |
655 | phr->error = 0; | 637 | phr->error = 0; |
@@ -686,10 +668,10 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
686 | 668 | ||
687 | /* NOTE don't use wAdapterType in this routine. It is not setup yet */ | 669 | /* NOTE don't use wAdapterType in this routine. It is not setup yet */ |
688 | 670 | ||
689 | switch (pao->pci.subsys_device_id) { | 671 | switch (pao->pci.pci_dev->subsystem_device) { |
690 | case 0x5100: | 672 | case 0x5100: |
691 | case 0x5110: /* ASI5100 revB or higher with C6711D */ | 673 | case 0x5110: /* ASI5100 revB or higher with C6711D */ |
692 | case 0x5200: /* ASI5200 PC_ie version of ASI5100 */ | 674 | case 0x5200: /* ASI5200 PCIe version of ASI5100 */ |
693 | case 0x6100: | 675 | case 0x6100: |
694 | case 0x6200: | 676 | case 0x6200: |
695 | boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); | 677 | boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200); |
@@ -709,8 +691,9 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
709 | * note that bits 4..15 are read-only and so should always return zero, | 691 | * note that bits 4..15 are read-only and so should always return zero, |
710 | * even though we wrote 1 to them | 692 | * even though we wrote 1 to them |
711 | */ | 693 | */ |
712 | for (i = 0; i < 1000; i++) | 694 | hpios_delay_micro_seconds(1000); |
713 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | 695 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); |
696 | |||
714 | if (delay != dw2040_reset) { | 697 | if (delay != dw2040_reset) { |
715 | HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset, | 698 | HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset, |
716 | delay); | 699 | delay); |
@@ -743,8 +726,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
743 | dw2040_reset = dw2040_reset & (~0x00000008); | 726 | dw2040_reset = dw2040_reset & (~0x00000008); |
744 | iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); | 727 | iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET); |
745 | /*delay to allow DSP to get going */ | 728 | /*delay to allow DSP to get going */ |
746 | for (i = 0; i < 100; i++) | 729 | hpios_delay_micro_seconds(100); |
747 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | ||
748 | 730 | ||
749 | /* loop through all DSPs, downloading DSP code */ | 731 | /* loop through all DSPs, downloading DSP code */ |
750 | for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) { | 732 | for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) { |
@@ -783,27 +765,27 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
783 | */ | 765 | */ |
784 | /* bypass PLL */ | 766 | /* bypass PLL */ |
785 | hpi_write_word(pdo, 0x01B7C100, 0x0000); | 767 | hpi_write_word(pdo, 0x01B7C100, 0x0000); |
786 | for (i = 0; i < 100; i++) | 768 | hpios_delay_micro_seconds(100); |
787 | delay = ioread32(phw->dw2040_HPICSR + | ||
788 | HPI_RESET); | ||
789 | 769 | ||
790 | /* ** use default of PLL x7 ** */ | 770 | /* ** use default of PLL x7 ** */ |
791 | /* EMIF = 225/3=75MHz */ | 771 | /* EMIF = 225/3=75MHz */ |
792 | hpi_write_word(pdo, 0x01B7C120, 0x8002); | 772 | hpi_write_word(pdo, 0x01B7C120, 0x8002); |
773 | hpios_delay_micro_seconds(100); | ||
774 | |||
793 | /* peri = 225/2 */ | 775 | /* peri = 225/2 */ |
794 | hpi_write_word(pdo, 0x01B7C11C, 0x8001); | 776 | hpi_write_word(pdo, 0x01B7C11C, 0x8001); |
777 | hpios_delay_micro_seconds(100); | ||
778 | |||
795 | /* cpu = 225/1 */ | 779 | /* cpu = 225/1 */ |
796 | hpi_write_word(pdo, 0x01B7C118, 0x8000); | 780 | hpi_write_word(pdo, 0x01B7C118, 0x8000); |
797 | /* ~200us delay */ | 781 | |
798 | for (i = 0; i < 2000; i++) | 782 | /* ~2ms delay */ |
799 | delay = ioread32(phw->dw2040_HPICSR + | 783 | hpios_delay_micro_seconds(2000); |
800 | HPI_RESET); | 784 | |
801 | /* PLL not bypassed */ | 785 | /* PLL not bypassed */ |
802 | hpi_write_word(pdo, 0x01B7C100, 0x0001); | 786 | hpi_write_word(pdo, 0x01B7C100, 0x0001); |
803 | /* ~200us delay */ | 787 | /* ~2ms delay */ |
804 | for (i = 0; i < 2000; i++) | 788 | hpios_delay_micro_seconds(2000); |
805 | delay = ioread32(phw->dw2040_HPICSR + | ||
806 | HPI_RESET); | ||
807 | } | 789 | } |
808 | 790 | ||
809 | /* test r/w to internal DSP memory | 791 | /* test r/w to internal DSP memory |
@@ -927,9 +909,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
927 | } | 909 | } |
928 | 910 | ||
929 | /* delay a little to allow SDRAM and DSP to "get going" */ | 911 | /* delay a little to allow SDRAM and DSP to "get going" */ |
930 | 912 | hpios_delay_micro_seconds(1000); | |
931 | for (i = 0; i < 1000; i++) | ||
932 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | ||
933 | 913 | ||
934 | /* test access to SDRAM */ | 914 | /* test access to SDRAM */ |
935 | { | 915 | { |
@@ -976,7 +956,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
976 | 956 | ||
977 | /* write the DSP code down into the DSPs memory */ | 957 | /* write the DSP code down into the DSPs memory */ |
978 | /*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */ | 958 | /*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */ |
979 | dsp_code.ps_dev = pao->pci.p_os_data; | 959 | dsp_code.ps_dev = pao->pci.pci_dev; |
980 | 960 | ||
981 | error = hpi_dsp_code_open(boot_load_family, &dsp_code, | 961 | error = hpi_dsp_code_open(boot_load_family, &dsp_code, |
982 | pos_error_code); | 962 | pos_error_code); |
@@ -1073,8 +1053,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1073 | 1053 | ||
1074 | /* step 3. Start code by sending interrupt */ | 1054 | /* step 3. Start code by sending interrupt */ |
1075 | iowrite32(0x00030003, pdo->prHPI_control); | 1055 | iowrite32(0x00030003, pdo->prHPI_control); |
1076 | for (i = 0; i < 10000; i++) | 1056 | hpios_delay_micro_seconds(10000); |
1077 | delay = ioread32(phw->dw2040_HPICSR + HPI_RESET); | ||
1078 | 1057 | ||
1079 | /* wait for a non-zero value in hostcmd - | 1058 | /* wait for a non-zero value in hostcmd - |
1080 | * indicating initialization is complete | 1059 | * indicating initialization is complete |
@@ -1101,7 +1080,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1101 | * locks up with a bluescreen (NOT GPF or pagefault). | 1080 | * locks up with a bluescreen (NOT GPF or pagefault). |
1102 | */ | 1081 | */ |
1103 | else | 1082 | else |
1104 | hpios_delay_micro_seconds(1000); | 1083 | hpios_delay_micro_seconds(10000); |
1105 | } | 1084 | } |
1106 | if (timeout == 0) | 1085 | if (timeout == 0) |
1107 | return HPI6000_ERROR_INIT_NOACK; | 1086 | return HPI6000_ERROR_INIT_NOACK; |
@@ -1132,14 +1111,14 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1132 | mask = 0xFFFFFF00L; | 1111 | mask = 0xFFFFFF00L; |
1133 | /* ASI5100 uses AX6 code, */ | 1112 | /* ASI5100 uses AX6 code, */ |
1134 | /* but has no PLD r/w register to test */ | 1113 | /* but has no PLD r/w register to test */ |
1135 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci. | 1114 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> |
1136 | subsys_device_id) == | 1115 | subsystem_device) == |
1137 | HPI_ADAPTER_FAMILY_ASI(0x5100)) | 1116 | HPI_ADAPTER_FAMILY_ASI(0x5100)) |
1138 | mask = 0x00000000L; | 1117 | mask = 0x00000000L; |
1139 | /* ASI5200 uses AX6 code, */ | 1118 | /* ASI5200 uses AX6 code, */ |
1140 | /* but has no PLD r/w register to test */ | 1119 | /* but has no PLD r/w register to test */ |
1141 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci. | 1120 | if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev-> |
1142 | subsys_device_id) == | 1121 | subsystem_device) == |
1143 | HPI_ADAPTER_FAMILY_ASI(0x5200)) | 1122 | HPI_ADAPTER_FAMILY_ASI(0x5200)) |
1144 | mask = 0x00000000L; | 1123 | mask = 0x00000000L; |
1145 | break; | 1124 | break; |
@@ -1204,7 +1183,7 @@ static u32 hpi_read_word(struct dsp_obj *pdo, u32 address) | |||
1204 | u32 data = 0; | 1183 | u32 data = 0; |
1205 | 1184 | ||
1206 | if (hpi_set_address(pdo, address)) | 1185 | if (hpi_set_address(pdo, address)) |
1207 | return 0; /*? no way to return error */ | 1186 | return 0; /*? No way to return error */ |
1208 | 1187 | ||
1209 | /* take care of errata in revB DSP (2.0.1) */ | 1188 | /* take care of errata in revB DSP (2.0.1) */ |
1210 | data = ioread32(pdo->prHPI_data); | 1189 | data = ioread32(pdo->prHPI_data); |
@@ -1340,10 +1319,6 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1340 | u32 *p_data; | 1319 | u32 *p_data; |
1341 | u16 error = 0; | 1320 | u16 error = 0; |
1342 | 1321 | ||
1343 | /* does the DSP we are referencing exist? */ | ||
1344 | if (dsp_index >= phw->num_dsp) | ||
1345 | return HPI6000_ERROR_MSG_INVALID_DSP_INDEX; | ||
1346 | |||
1347 | ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); | 1322 | ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE); |
1348 | if (ack & HPI_HIF_ERROR_MASK) { | 1323 | if (ack & HPI_HIF_ERROR_MASK) { |
1349 | pao->dsp_crashed++; | 1324 | pao->dsp_crashed++; |
@@ -1351,9 +1326,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1351 | } | 1326 | } |
1352 | pao->dsp_crashed = 0; | 1327 | pao->dsp_crashed = 0; |
1353 | 1328 | ||
1354 | /* send the message */ | 1329 | /* get the message address and size */ |
1355 | |||
1356 | /* get the address and size */ | ||
1357 | if (phw->message_buffer_address_on_dsp == 0) { | 1330 | if (phw->message_buffer_address_on_dsp == 0) { |
1358 | timeout = TIMEOUT; | 1331 | timeout = TIMEOUT; |
1359 | do { | 1332 | do { |
@@ -1368,10 +1341,9 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1368 | } else | 1341 | } else |
1369 | address = phw->message_buffer_address_on_dsp; | 1342 | address = phw->message_buffer_address_on_dsp; |
1370 | 1343 | ||
1371 | /* dwLength = sizeof(struct hpi_message); */ | ||
1372 | length = phm->size; | 1344 | length = phm->size; |
1373 | 1345 | ||
1374 | /* send it */ | 1346 | /* send the message */ |
1375 | p_data = (u32 *)phm; | 1347 | p_data = (u32 *)phm; |
1376 | if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data, | 1348 | if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data, |
1377 | (u16)length / 4)) | 1349 | (u16)length / 4)) |
@@ -1385,7 +1357,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1385 | if (ack & HPI_HIF_ERROR_MASK) | 1357 | if (ack & HPI_HIF_ERROR_MASK) |
1386 | return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK; | 1358 | return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK; |
1387 | 1359 | ||
1388 | /* get the address and size */ | 1360 | /* get the response address */ |
1389 | if (phw->response_buffer_address_on_dsp == 0) { | 1361 | if (phw->response_buffer_address_on_dsp == 0) { |
1390 | timeout = TIMEOUT; | 1362 | timeout = TIMEOUT; |
1391 | do { | 1363 | do { |
@@ -1409,7 +1381,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao, | |||
1409 | if (!timeout) | 1381 | if (!timeout) |
1410 | length = sizeof(struct hpi_response); | 1382 | length = sizeof(struct hpi_response); |
1411 | 1383 | ||
1412 | /* get it */ | 1384 | /* get the response */ |
1413 | p_data = (u32 *)phr; | 1385 | p_data = (u32 *)phr; |
1414 | if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data, | 1386 | if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data, |
1415 | (u16)length / 4)) | 1387 | (u16)length / 4)) |
@@ -1805,17 +1777,11 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
1805 | hpios_dsplock_lock(pao); | 1777 | hpios_dsplock_lock(pao); |
1806 | error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr); | 1778 | error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr); |
1807 | 1779 | ||
1808 | /* maybe an error response */ | 1780 | if (error) /* something failed in the HPI/DSP interface */ |
1809 | if (error) { | ||
1810 | /* something failed in the HPI/DSP interface */ | ||
1811 | phr->error = error; | ||
1812 | /* just the header of the response is valid */ | ||
1813 | phr->size = sizeof(struct hpi_response_header); | ||
1814 | goto err; | 1781 | goto err; |
1815 | } | ||
1816 | 1782 | ||
1817 | if (phr->error != 0) /* something failed in the DSP */ | 1783 | if (phr->error) /* something failed in the DSP */ |
1818 | goto err; | 1784 | goto out; |
1819 | 1785 | ||
1820 | switch (phm->function) { | 1786 | switch (phm->function) { |
1821 | case HPI_OSTREAM_WRITE: | 1787 | case HPI_OSTREAM_WRITE: |
@@ -1827,21 +1793,30 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
1827 | error = hpi6000_get_data(pao, dsp_index, phm, phr); | 1793 | error = hpi6000_get_data(pao, dsp_index, phm, phr); |
1828 | break; | 1794 | break; |
1829 | case HPI_ADAPTER_GET_ASSERT: | 1795 | case HPI_ADAPTER_GET_ASSERT: |
1830 | phr->u.a.adapter_index = 0; /* dsp 0 default */ | 1796 | phr->u.ax.assert.dsp_index = 0; /* dsp 0 default */ |
1831 | if (num_dsp == 2) { | 1797 | if (num_dsp == 2) { |
1832 | if (!phr->u.a.adapter_type) { | 1798 | if (!phr->u.ax.assert.count) { |
1833 | /* no assert from dsp 0, check dsp 1 */ | 1799 | /* no assert from dsp 0, check dsp 1 */ |
1834 | error = hpi6000_message_response_sequence(pao, | 1800 | error = hpi6000_message_response_sequence(pao, |
1835 | 1, phm, phr); | 1801 | 1, phm, phr); |
1836 | phr->u.a.adapter_index = 1; | 1802 | phr->u.ax.assert.dsp_index = 1; |
1837 | } | 1803 | } |
1838 | } | 1804 | } |
1839 | } | 1805 | } |
1840 | 1806 | ||
1841 | if (error) | ||
1842 | phr->error = error; | ||
1843 | |||
1844 | err: | 1807 | err: |
1808 | if (error) { | ||
1809 | if (error >= HPI_ERROR_BACKEND_BASE) { | ||
1810 | phr->error = HPI_ERROR_DSP_COMMUNICATION; | ||
1811 | phr->specific_error = error; | ||
1812 | } else { | ||
1813 | phr->error = error; | ||
1814 | } | ||
1815 | |||
1816 | /* just the header of the response is valid */ | ||
1817 | phr->size = sizeof(struct hpi_response_header); | ||
1818 | } | ||
1819 | out: | ||
1845 | hpios_dsplock_unlock(pao); | 1820 | hpios_dsplock_unlock(pao); |
1846 | return; | 1821 | return; |
1847 | } | 1822 | } |
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c index 2672f6591ceb..620525bdac59 100644 --- a/sound/pci/asihpi/hpi6205.c +++ b/sound/pci/asihpi/hpi6205.c | |||
@@ -38,27 +38,26 @@ | |||
38 | 38 | ||
39 | /*****************************************************************************/ | 39 | /*****************************************************************************/ |
40 | /* HPI6205 specific error codes */ | 40 | /* HPI6205 specific error codes */ |
41 | #define HPI6205_ERROR_BASE 1000 | 41 | #define HPI6205_ERROR_BASE 1000 /* not actually used anywhere */ |
42 | /*#define HPI6205_ERROR_MEM_ALLOC 1001 */ | 42 | |
43 | /* operational/messaging errors */ | ||
44 | #define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT 1015 | ||
45 | #define HPI6205_ERROR_MSG_RESP_TIMEOUT 1016 | ||
46 | |||
47 | /* initialization/bootload errors */ | ||
43 | #define HPI6205_ERROR_6205_NO_IRQ 1002 | 48 | #define HPI6205_ERROR_6205_NO_IRQ 1002 |
44 | #define HPI6205_ERROR_6205_INIT_FAILED 1003 | 49 | #define HPI6205_ERROR_6205_INIT_FAILED 1003 |
45 | /*#define HPI6205_ERROR_MISSING_DSPCODE 1004 */ | ||
46 | #define HPI6205_ERROR_UNKNOWN_PCI_DEVICE 1005 | ||
47 | #define HPI6205_ERROR_6205_REG 1006 | 50 | #define HPI6205_ERROR_6205_REG 1006 |
48 | #define HPI6205_ERROR_6205_DSPPAGE 1007 | 51 | #define HPI6205_ERROR_6205_DSPPAGE 1007 |
49 | #define HPI6205_ERROR_BAD_DSPINDEX 1008 | ||
50 | #define HPI6205_ERROR_C6713_HPIC 1009 | 52 | #define HPI6205_ERROR_C6713_HPIC 1009 |
51 | #define HPI6205_ERROR_C6713_HPIA 1010 | 53 | #define HPI6205_ERROR_C6713_HPIA 1010 |
52 | #define HPI6205_ERROR_C6713_PLL 1011 | 54 | #define HPI6205_ERROR_C6713_PLL 1011 |
53 | #define HPI6205_ERROR_DSP_INTMEM 1012 | 55 | #define HPI6205_ERROR_DSP_INTMEM 1012 |
54 | #define HPI6205_ERROR_DSP_EXTMEM 1013 | 56 | #define HPI6205_ERROR_DSP_EXTMEM 1013 |
55 | #define HPI6205_ERROR_DSP_PLD 1014 | 57 | #define HPI6205_ERROR_DSP_PLD 1014 |
56 | #define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT 1015 | ||
57 | #define HPI6205_ERROR_MSG_RESP_TIMEOUT 1016 | ||
58 | #define HPI6205_ERROR_6205_EEPROM 1017 | 58 | #define HPI6205_ERROR_6205_EEPROM 1017 |
59 | #define HPI6205_ERROR_DSP_EMIF 1018 | 59 | #define HPI6205_ERROR_DSP_EMIF 1018 |
60 | 60 | ||
61 | #define hpi6205_error(dsp_index, err) (err) | ||
62 | /*****************************************************************************/ | 61 | /*****************************************************************************/ |
63 | /* for C6205 PCI i/f */ | 62 | /* for C6205 PCI i/f */ |
64 | /* Host Status Register (HSR) bitfields */ | 63 | /* Host Status Register (HSR) bitfields */ |
@@ -128,9 +127,6 @@ struct hpi_hw_obj { | |||
128 | u32 outstream_host_buffer_size[HPI_MAX_STREAMS]; | 127 | u32 outstream_host_buffer_size[HPI_MAX_STREAMS]; |
129 | 128 | ||
130 | struct consistent_dma_area h_control_cache; | 129 | struct consistent_dma_area h_control_cache; |
131 | struct consistent_dma_area h_async_event_buffer; | ||
132 | /* struct hpi_control_cache_single *pControlCache; */ | ||
133 | struct hpi_async_event *p_async_event_buffer; | ||
134 | struct hpi_control_cache *p_cache; | 130 | struct hpi_control_cache *p_cache; |
135 | }; | 131 | }; |
136 | 132 | ||
@@ -208,8 +204,8 @@ static void instream_start(struct hpi_adapter_obj *pao, | |||
208 | static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index, | 204 | static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index, |
209 | u32 address); | 205 | u32 address); |
210 | 206 | ||
211 | static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index, | 207 | static void boot_loader_write_mem32(struct hpi_adapter_obj *pao, |
212 | u32 address, u32 data); | 208 | int dsp_index, u32 address, u32 data); |
213 | 209 | ||
214 | static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, | 210 | static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, |
215 | int dsp_index); | 211 | int dsp_index); |
@@ -229,17 +225,7 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index); | |||
229 | 225 | ||
230 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | 226 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) |
231 | { | 227 | { |
232 | |||
233 | switch (phm->function) { | 228 | switch (phm->function) { |
234 | case HPI_SUBSYS_OPEN: | ||
235 | case HPI_SUBSYS_CLOSE: | ||
236 | case HPI_SUBSYS_GET_INFO: | ||
237 | case HPI_SUBSYS_DRIVER_UNLOAD: | ||
238 | case HPI_SUBSYS_DRIVER_LOAD: | ||
239 | case HPI_SUBSYS_FIND_ADAPTERS: | ||
240 | /* messages that should not get here */ | ||
241 | phr->error = HPI_ERROR_UNIMPLEMENTED; | ||
242 | break; | ||
243 | case HPI_SUBSYS_CREATE_ADAPTER: | 229 | case HPI_SUBSYS_CREATE_ADAPTER: |
244 | subsys_create_adapter(phm, phr); | 230 | subsys_create_adapter(phm, phr); |
245 | break; | 231 | break; |
@@ -257,15 +243,22 @@ static void control_message(struct hpi_adapter_obj *pao, | |||
257 | { | 243 | { |
258 | 244 | ||
259 | struct hpi_hw_obj *phw = pao->priv; | 245 | struct hpi_hw_obj *phw = pao->priv; |
246 | u16 pending_cache_error = 0; | ||
260 | 247 | ||
261 | switch (phm->function) { | 248 | switch (phm->function) { |
262 | case HPI_CONTROL_GET_STATE: | 249 | case HPI_CONTROL_GET_STATE: |
263 | if (pao->has_control_cache) { | 250 | if (pao->has_control_cache) { |
264 | rmb(); /* make sure we see updates DM_aed from DSP */ | 251 | rmb(); /* make sure we see updates DMAed from DSP */ |
265 | if (hpi_check_control_cache(phw->p_cache, phm, phr)) | 252 | if (hpi_check_control_cache(phw->p_cache, phm, phr)) { |
266 | break; | 253 | break; |
254 | } else if (phm->u.c.attribute == HPI_METER_PEAK) { | ||
255 | pending_cache_error = | ||
256 | HPI_ERROR_CONTROL_CACHING; | ||
257 | } | ||
267 | } | 258 | } |
268 | hw_message(pao, phm, phr); | 259 | hw_message(pao, phm, phr); |
260 | if (pending_cache_error && !phr->error) | ||
261 | phr->error = pending_cache_error; | ||
269 | break; | 262 | break; |
270 | case HPI_CONTROL_GET_INFO: | 263 | case HPI_CONTROL_GET_INFO: |
271 | hw_message(pao, phm, phr); | 264 | hw_message(pao, phm, phr); |
@@ -273,7 +266,8 @@ static void control_message(struct hpi_adapter_obj *pao, | |||
273 | case HPI_CONTROL_SET_STATE: | 266 | case HPI_CONTROL_SET_STATE: |
274 | hw_message(pao, phm, phr); | 267 | hw_message(pao, phm, phr); |
275 | if (pao->has_control_cache) | 268 | if (pao->has_control_cache) |
276 | hpi_sync_control_cache(phw->p_cache, phm, phr); | 269 | hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, |
270 | phr); | ||
277 | break; | 271 | break; |
278 | default: | 272 | default: |
279 | phr->error = HPI_ERROR_INVALID_FUNC; | 273 | phr->error = HPI_ERROR_INVALID_FUNC; |
@@ -296,9 +290,9 @@ static void outstream_message(struct hpi_adapter_obj *pao, | |||
296 | { | 290 | { |
297 | 291 | ||
298 | if (phm->obj_index >= HPI_MAX_STREAMS) { | 292 | if (phm->obj_index >= HPI_MAX_STREAMS) { |
299 | phr->error = HPI_ERROR_INVALID_STREAM; | 293 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; |
300 | HPI_DEBUG_LOG(WARNING, | 294 | HPI_DEBUG_LOG(WARNING, |
301 | "message referencing invalid stream %d " | 295 | "Message referencing invalid stream %d " |
302 | "on adapter index %d\n", phm->obj_index, | 296 | "on adapter index %d\n", phm->obj_index, |
303 | phm->adapter_index); | 297 | phm->adapter_index); |
304 | return; | 298 | return; |
@@ -340,9 +334,9 @@ static void instream_message(struct hpi_adapter_obj *pao, | |||
340 | { | 334 | { |
341 | 335 | ||
342 | if (phm->obj_index >= HPI_MAX_STREAMS) { | 336 | if (phm->obj_index >= HPI_MAX_STREAMS) { |
343 | phr->error = HPI_ERROR_INVALID_STREAM; | 337 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; |
344 | HPI_DEBUG_LOG(WARNING, | 338 | HPI_DEBUG_LOG(WARNING, |
345 | "message referencing invalid stream %d " | 339 | "Message referencing invalid stream %d " |
346 | "on adapter index %d\n", phm->obj_index, | 340 | "on adapter index %d\n", phm->obj_index, |
347 | phm->adapter_index); | 341 | phm->adapter_index); |
348 | return; | 342 | return; |
@@ -385,8 +379,8 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) | |||
385 | * All other messages are ignored unless the adapter index matches | 379 | * All other messages are ignored unless the adapter index matches |
386 | * an adapter in the HPI | 380 | * an adapter in the HPI |
387 | */ | 381 | */ |
388 | HPI_DEBUG_LOG(DEBUG, "HPI obj=%d, func=%d\n", phm->object, | 382 | /* HPI_DEBUG_LOG(DEBUG, "HPI Obj=%d, Func=%d\n", phm->wObject, |
389 | phm->function); | 383 | phm->wFunction); */ |
390 | 384 | ||
391 | /* if Dsp has crashed then do not communicate with it any more */ | 385 | /* if Dsp has crashed then do not communicate with it any more */ |
392 | if (phm->object != HPI_OBJ_SUBSYSTEM) { | 386 | if (phm->object != HPI_OBJ_SUBSYSTEM) { |
@@ -411,8 +405,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) | |||
411 | 405 | ||
412 | /* Init default response */ | 406 | /* Init default response */ |
413 | if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) | 407 | if (phm->function != HPI_SUBSYS_CREATE_ADAPTER) |
414 | hpi_init_response(phr, phm->object, phm->function, | 408 | phr->error = HPI_ERROR_PROCESSING_MESSAGE; |
415 | HPI_ERROR_PROCESSING_MESSAGE); | ||
416 | 409 | ||
417 | HPI_DEBUG_LOG(VERBOSE, "start of switch\n"); | 410 | HPI_DEBUG_LOG(VERBOSE, "start of switch\n"); |
418 | switch (phm->type) { | 411 | switch (phm->type) { |
@@ -423,9 +416,6 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr) | |||
423 | break; | 416 | break; |
424 | 417 | ||
425 | case HPI_OBJ_ADAPTER: | 418 | case HPI_OBJ_ADAPTER: |
426 | phr->size = | ||
427 | sizeof(struct hpi_response_header) + | ||
428 | sizeof(struct hpi_adapter_res); | ||
429 | adapter_message(pao, phm, phr); | 419 | adapter_message(pao, phm, phr); |
430 | break; | 420 | break; |
431 | 421 | ||
@@ -474,14 +464,6 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
474 | 464 | ||
475 | memset(&ao, 0, sizeof(ao)); | 465 | memset(&ao, 0, sizeof(ao)); |
476 | 466 | ||
477 | /* this HPI only creates adapters for TI/PCI devices */ | ||
478 | if (phm->u.s.resource.bus_type != HPI_BUS_PCI) | ||
479 | return; | ||
480 | if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI) | ||
481 | return; | ||
482 | if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_DSP6205) | ||
483 | return; | ||
484 | |||
485 | ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); | 467 | ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL); |
486 | if (!ao.priv) { | 468 | if (!ao.priv) { |
487 | HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); | 469 | HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n"); |
@@ -491,18 +473,20 @@ static void subsys_create_adapter(struct hpi_message *phm, | |||
491 | 473 | ||
492 | ao.pci = *phm->u.s.resource.r.pci; | 474 | ao.pci = *phm->u.s.resource.r.pci; |
493 | err = create_adapter_obj(&ao, &os_error_code); | 475 | err = create_adapter_obj(&ao, &os_error_code); |
494 | if (!err) | ||
495 | err = hpi_add_adapter(&ao); | ||
496 | if (err) { | 476 | if (err) { |
497 | phr->u.s.data = os_error_code; | ||
498 | delete_adapter_obj(&ao); | 477 | delete_adapter_obj(&ao); |
499 | phr->error = err; | 478 | if (err >= HPI_ERROR_BACKEND_BASE) { |
479 | phr->error = HPI_ERROR_DSP_BOOTLOAD; | ||
480 | phr->specific_error = err; | ||
481 | } else { | ||
482 | phr->error = err; | ||
483 | } | ||
484 | phr->u.s.data = os_error_code; | ||
500 | return; | 485 | return; |
501 | } | 486 | } |
502 | 487 | ||
503 | phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type; | 488 | phr->u.s.adapter_type = ao.adapter_type; |
504 | phr->u.s.adapter_index = ao.index; | 489 | phr->u.s.adapter_index = ao.index; |
505 | phr->u.s.num_adapters++; | ||
506 | phr->error = 0; | 490 | phr->error = 0; |
507 | } | 491 | } |
508 | 492 | ||
@@ -513,7 +497,7 @@ static void subsys_delete_adapter(struct hpi_message *phm, | |||
513 | struct hpi_adapter_obj *pao; | 497 | struct hpi_adapter_obj *pao; |
514 | struct hpi_hw_obj *phw; | 498 | struct hpi_hw_obj *phw; |
515 | 499 | ||
516 | pao = hpi_find_adapter(phm->adapter_index); | 500 | pao = hpi_find_adapter(phm->obj_index); |
517 | if (!pao) { | 501 | if (!pao) { |
518 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; | 502 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; |
519 | return; | 503 | return; |
@@ -526,6 +510,7 @@ static void subsys_delete_adapter(struct hpi_message *phm, | |||
526 | iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR); | 510 | iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR); |
527 | 511 | ||
528 | delete_adapter_obj(pao); | 512 | delete_adapter_obj(pao); |
513 | hpi_delete_adapter(pao); | ||
529 | phr->error = 0; | 514 | phr->error = 0; |
530 | } | 515 | } |
531 | 516 | ||
@@ -538,10 +523,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
538 | struct hpi_hw_obj *phw = pao->priv; | 523 | struct hpi_hw_obj *phw = pao->priv; |
539 | struct bus_master_interface *interface; | 524 | struct bus_master_interface *interface; |
540 | u32 phys_addr; | 525 | u32 phys_addr; |
541 | #ifndef HPI6205_NO_HSR_POLL | ||
542 | u32 time_out = HPI6205_TIMEOUT; | ||
543 | u32 temp1; | ||
544 | #endif | ||
545 | int i; | 526 | int i; |
546 | u16 err; | 527 | u16 err; |
547 | 528 | ||
@@ -566,7 +547,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
566 | 547 | ||
567 | if (hpios_locked_mem_alloc(&phw->h_locked_mem, | 548 | if (hpios_locked_mem_alloc(&phw->h_locked_mem, |
568 | sizeof(struct bus_master_interface), | 549 | sizeof(struct bus_master_interface), |
569 | pao->pci.p_os_data)) | 550 | pao->pci.pci_dev)) |
570 | phw->p_interface_buffer = NULL; | 551 | phw->p_interface_buffer = NULL; |
571 | else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem, | 552 | else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem, |
572 | (void *)&phw->p_interface_buffer)) | 553 | (void *)&phw->p_interface_buffer)) |
@@ -591,49 +572,29 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
591 | 572 | ||
592 | /* allow boot load even if mem alloc wont work */ | 573 | /* allow boot load even if mem alloc wont work */ |
593 | if (!phw->p_interface_buffer) | 574 | if (!phw->p_interface_buffer) |
594 | return hpi6205_error(0, HPI_ERROR_MEMORY_ALLOC); | 575 | return HPI_ERROR_MEMORY_ALLOC; |
595 | 576 | ||
596 | interface = phw->p_interface_buffer; | 577 | interface = phw->p_interface_buffer; |
597 | 578 | ||
598 | #ifndef HPI6205_NO_HSR_POLL | ||
599 | /* wait for first interrupt indicating the DSP init is done */ | ||
600 | time_out = HPI6205_TIMEOUT * 10; | ||
601 | temp1 = 0; | ||
602 | while (((temp1 & C6205_HSR_INTSRC) == 0) && --time_out) | ||
603 | temp1 = ioread32(phw->prHSR); | ||
604 | |||
605 | if (temp1 & C6205_HSR_INTSRC) | ||
606 | HPI_DEBUG_LOG(INFO, | ||
607 | "interrupt confirming DSP code running OK\n"); | ||
608 | else { | ||
609 | HPI_DEBUG_LOG(ERROR, | ||
610 | "timed out waiting for interrupt " | ||
611 | "confirming DSP code running\n"); | ||
612 | return hpi6205_error(0, HPI6205_ERROR_6205_NO_IRQ); | ||
613 | } | ||
614 | |||
615 | /* reset the interrupt */ | ||
616 | iowrite32(C6205_HSR_INTSRC, phw->prHSR); | ||
617 | #endif | ||
618 | |||
619 | /* make sure the DSP has started ok */ | 579 | /* make sure the DSP has started ok */ |
620 | if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) { | 580 | if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) { |
621 | HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n"); | 581 | HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n"); |
622 | return hpi6205_error(0, HPI6205_ERROR_6205_INIT_FAILED); | 582 | return HPI6205_ERROR_6205_INIT_FAILED; |
623 | } | 583 | } |
624 | /* Note that *pao, *phw are zeroed after allocation, | 584 | /* Note that *pao, *phw are zeroed after allocation, |
625 | * so pointers and flags are NULL by default. | 585 | * so pointers and flags are NULL by default. |
626 | * Allocate bus mastering control cache buffer and tell the DSP about it | 586 | * Allocate bus mastering control cache buffer and tell the DSP about it |
627 | */ | 587 | */ |
628 | if (interface->control_cache.number_of_controls) { | 588 | if (interface->control_cache.number_of_controls) { |
629 | void *p_control_cache_virtual; | 589 | u8 *p_control_cache_virtual; |
630 | 590 | ||
631 | err = hpios_locked_mem_alloc(&phw->h_control_cache, | 591 | err = hpios_locked_mem_alloc(&phw->h_control_cache, |
632 | interface->control_cache.size_in_bytes, | 592 | interface->control_cache.size_in_bytes, |
633 | pao->pci.p_os_data); | 593 | pao->pci.pci_dev); |
634 | if (!err) | 594 | if (!err) |
635 | err = hpios_locked_mem_get_virt_addr(&phw-> | 595 | err = hpios_locked_mem_get_virt_addr(&phw-> |
636 | h_control_cache, &p_control_cache_virtual); | 596 | h_control_cache, |
597 | (void *)&p_control_cache_virtual); | ||
637 | if (!err) { | 598 | if (!err) { |
638 | memset(p_control_cache_virtual, 0, | 599 | memset(p_control_cache_virtual, 0, |
639 | interface->control_cache.size_in_bytes); | 600 | interface->control_cache.size_in_bytes); |
@@ -642,7 +603,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
642 | hpi_alloc_control_cache(interface-> | 603 | hpi_alloc_control_cache(interface-> |
643 | control_cache.number_of_controls, | 604 | control_cache.number_of_controls, |
644 | interface->control_cache.size_in_bytes, | 605 | interface->control_cache.size_in_bytes, |
645 | (struct hpi_control_cache_info *) | ||
646 | p_control_cache_virtual); | 606 | p_control_cache_virtual); |
647 | if (!phw->p_cache) | 607 | if (!phw->p_cache) |
648 | err = HPI_ERROR_MEMORY_ALLOC; | 608 | err = HPI_ERROR_MEMORY_ALLOC; |
@@ -662,78 +622,56 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao, | |||
662 | pao->has_control_cache = 0; | 622 | pao->has_control_cache = 0; |
663 | } | 623 | } |
664 | } | 624 | } |
665 | /* allocate bus mastering async buffer and tell the DSP about it */ | ||
666 | if (interface->async_buffer.b.size) { | ||
667 | err = hpios_locked_mem_alloc(&phw->h_async_event_buffer, | ||
668 | interface->async_buffer.b.size * | ||
669 | sizeof(struct hpi_async_event), pao->pci.p_os_data); | ||
670 | if (!err) | ||
671 | err = hpios_locked_mem_get_virt_addr | ||
672 | (&phw->h_async_event_buffer, (void *) | ||
673 | &phw->p_async_event_buffer); | ||
674 | if (!err) | ||
675 | memset((void *)phw->p_async_event_buffer, 0, | ||
676 | interface->async_buffer.b.size * | ||
677 | sizeof(struct hpi_async_event)); | ||
678 | if (!err) { | ||
679 | err = hpios_locked_mem_get_phys_addr | ||
680 | (&phw->h_async_event_buffer, &phys_addr); | ||
681 | interface->async_buffer.physical_address32 = | ||
682 | phys_addr; | ||
683 | } | ||
684 | if (err) { | ||
685 | if (hpios_locked_mem_valid(&phw-> | ||
686 | h_async_event_buffer)) { | ||
687 | hpios_locked_mem_free | ||
688 | (&phw->h_async_event_buffer); | ||
689 | phw->p_async_event_buffer = NULL; | ||
690 | } | ||
691 | } | ||
692 | } | ||
693 | send_dsp_command(phw, H620_HIF_IDLE); | 625 | send_dsp_command(phw, H620_HIF_IDLE); |
694 | 626 | ||
695 | { | 627 | { |
696 | struct hpi_message hM; | 628 | struct hpi_message hm; |
697 | struct hpi_response hR; | 629 | struct hpi_response hr; |
698 | u32 max_streams; | 630 | u32 max_streams; |
699 | 631 | ||
700 | HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n"); | 632 | HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n"); |
701 | memset(&hM, 0, sizeof(hM)); | 633 | memset(&hm, 0, sizeof(hm)); |
702 | hM.type = HPI_TYPE_MESSAGE; | 634 | hm.type = HPI_TYPE_MESSAGE; |
703 | hM.size = sizeof(hM); | 635 | hm.size = sizeof(hm); |
704 | hM.object = HPI_OBJ_ADAPTER; | 636 | hm.object = HPI_OBJ_ADAPTER; |
705 | hM.function = HPI_ADAPTER_GET_INFO; | 637 | hm.function = HPI_ADAPTER_GET_INFO; |
706 | hM.adapter_index = 0; | 638 | hm.adapter_index = 0; |
707 | memset(&hR, 0, sizeof(hR)); | 639 | memset(&hr, 0, sizeof(hr)); |
708 | hR.size = sizeof(hR); | 640 | hr.size = sizeof(hr); |
709 | 641 | ||
710 | err = message_response_sequence(pao, &hM, &hR); | 642 | err = message_response_sequence(pao, &hm, &hr); |
711 | if (err) { | 643 | if (err) { |
712 | HPI_DEBUG_LOG(ERROR, "message transport error %d\n", | 644 | HPI_DEBUG_LOG(ERROR, "message transport error %d\n", |
713 | err); | 645 | err); |
714 | return err; | 646 | return err; |
715 | } | 647 | } |
716 | if (hR.error) | 648 | if (hr.error) |
717 | return hR.error; | 649 | return hr.error; |
718 | 650 | ||
719 | pao->adapter_type = hR.u.a.adapter_type; | 651 | pao->adapter_type = hr.u.ax.info.adapter_type; |
720 | pao->index = hR.u.a.adapter_index; | 652 | pao->index = hr.u.ax.info.adapter_index; |
721 | 653 | ||
722 | max_streams = hR.u.a.num_outstreams + hR.u.a.num_instreams; | 654 | max_streams = |
655 | hr.u.ax.info.num_outstreams + | ||
656 | hr.u.ax.info.num_instreams; | ||
723 | 657 | ||
724 | hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams, | 658 | hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams, |
725 | 65536, pao->pci.p_os_data); | 659 | 65536, pao->pci.pci_dev); |
726 | 660 | ||
727 | HPI_DEBUG_LOG(VERBOSE, | 661 | HPI_DEBUG_LOG(VERBOSE, |
728 | "got adapter info type %x index %d serial %d\n", | 662 | "got adapter info type %x index %d serial %d\n", |
729 | hR.u.a.adapter_type, hR.u.a.adapter_index, | 663 | hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index, |
730 | hR.u.a.serial_number); | 664 | hr.u.ax.info.serial_number); |
731 | } | 665 | } |
732 | 666 | ||
733 | pao->open = 0; /* upon creation the adapter is closed */ | 667 | pao->open = 0; /* upon creation the adapter is closed */ |
734 | 668 | ||
669 | if (phw->p_cache) | ||
670 | phw->p_cache->adap_idx = pao->index; | ||
671 | |||
735 | HPI_DEBUG_LOG(INFO, "bootload DSP OK\n"); | 672 | HPI_DEBUG_LOG(INFO, "bootload DSP OK\n"); |
736 | return 0; | 673 | |
674 | return hpi_add_adapter(pao); | ||
737 | } | 675 | } |
738 | 676 | ||
739 | /** Free memory areas allocated by adapter | 677 | /** Free memory areas allocated by adapter |
@@ -747,11 +685,6 @@ static void delete_adapter_obj(struct hpi_adapter_obj *pao) | |||
747 | 685 | ||
748 | phw = pao->priv; | 686 | phw = pao->priv; |
749 | 687 | ||
750 | if (hpios_locked_mem_valid(&phw->h_async_event_buffer)) { | ||
751 | hpios_locked_mem_free(&phw->h_async_event_buffer); | ||
752 | phw->p_async_event_buffer = NULL; | ||
753 | } | ||
754 | |||
755 | if (hpios_locked_mem_valid(&phw->h_control_cache)) { | 688 | if (hpios_locked_mem_valid(&phw->h_control_cache)) { |
756 | hpios_locked_mem_free(&phw->h_control_cache); | 689 | hpios_locked_mem_free(&phw->h_control_cache); |
757 | hpi_free_control_cache(phw->p_cache); | 690 | hpi_free_control_cache(phw->p_cache); |
@@ -776,13 +709,15 @@ static void delete_adapter_obj(struct hpi_adapter_obj *pao) | |||
776 | phw->outstream_host_buffer_size[i] = 0; | 709 | phw->outstream_host_buffer_size[i] = 0; |
777 | } | 710 | } |
778 | 711 | ||
779 | hpios_locked_mem_unprepare(pao->pci.p_os_data); | 712 | hpios_locked_mem_unprepare(pao->pci.pci_dev); |
780 | 713 | ||
781 | hpi_delete_adapter(pao); | ||
782 | kfree(phw); | 714 | kfree(phw); |
783 | } | 715 | } |
784 | 716 | ||
785 | /*****************************************************************************/ | 717 | /*****************************************************************************/ |
718 | /* Adapter functions */ | ||
719 | |||
720 | /*****************************************************************************/ | ||
786 | /* OutStream Host buffer functions */ | 721 | /* OutStream Host buffer functions */ |
787 | 722 | ||
788 | /** Allocate or attach buffer for busmastering | 723 | /** Allocate or attach buffer for busmastering |
@@ -824,7 +759,7 @@ static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao, | |||
824 | 759 | ||
825 | err = hpios_locked_mem_alloc(&phw->outstream_host_buffers | 760 | err = hpios_locked_mem_alloc(&phw->outstream_host_buffers |
826 | [phm->obj_index], phm->u.d.u.buffer.buffer_size, | 761 | [phm->obj_index], phm->u.d.u.buffer.buffer_size, |
827 | pao->pci.p_os_data); | 762 | pao->pci.pci_dev); |
828 | 763 | ||
829 | if (err) { | 764 | if (err) { |
830 | phr->error = HPI_ERROR_INVALID_DATASIZE; | 765 | phr->error = HPI_ERROR_INVALID_DATASIZE; |
@@ -861,7 +796,7 @@ static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao, | |||
861 | if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. | 796 | if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. |
862 | buffer_size - 1)) { | 797 | buffer_size - 1)) { |
863 | HPI_DEBUG_LOG(ERROR, | 798 | HPI_DEBUG_LOG(ERROR, |
864 | "buffer size must be 2^N not %d\n", | 799 | "Buffer size must be 2^N not %d\n", |
865 | phm->u.d.u.buffer.buffer_size); | 800 | phm->u.d.u.buffer.buffer_size); |
866 | phr->error = HPI_ERROR_INVALID_DATASIZE; | 801 | phr->error = HPI_ERROR_INVALID_DATASIZE; |
867 | return; | 802 | return; |
@@ -875,6 +810,7 @@ static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao, | |||
875 | status->dSP_index = 0; | 810 | status->dSP_index = 0; |
876 | status->host_index = status->dSP_index; | 811 | status->host_index = status->dSP_index; |
877 | status->size_in_bytes = phm->u.d.u.buffer.buffer_size; | 812 | status->size_in_bytes = phm->u.d.u.buffer.buffer_size; |
813 | status->auxiliary_data_available = 0; | ||
878 | 814 | ||
879 | hw_message(pao, phm, phr); | 815 | hw_message(pao, phm, phr); |
880 | 816 | ||
@@ -966,51 +902,6 @@ static void outstream_write(struct hpi_adapter_obj *pao, | |||
966 | hpi_init_response(phr, phm->object, phm->function, 0); | 902 | hpi_init_response(phr, phm->object, phm->function, 0); |
967 | status = &interface->outstream_host_buffer_status[phm->obj_index]; | 903 | status = &interface->outstream_host_buffer_status[phm->obj_index]; |
968 | 904 | ||
969 | if (phw->flag_outstream_just_reset[phm->obj_index]) { | ||
970 | /* First OutStremWrite() call following reset will write data to the | ||
971 | adapter's buffers, reducing delay before stream can start. The DSP | ||
972 | takes care of setting the stream data format using format information | ||
973 | embedded in phm. | ||
974 | */ | ||
975 | int partial_write = 0; | ||
976 | unsigned int original_size = 0; | ||
977 | |||
978 | phw->flag_outstream_just_reset[phm->obj_index] = 0; | ||
979 | |||
980 | /* Send the first buffer to the DSP the old way. */ | ||
981 | /* Limit size of first transfer - */ | ||
982 | /* expect that this will not usually be triggered. */ | ||
983 | if (phm->u.d.u.data.data_size > HPI6205_SIZEOF_DATA) { | ||
984 | partial_write = 1; | ||
985 | original_size = phm->u.d.u.data.data_size; | ||
986 | phm->u.d.u.data.data_size = HPI6205_SIZEOF_DATA; | ||
987 | } | ||
988 | /* write it */ | ||
989 | phm->function = HPI_OSTREAM_WRITE; | ||
990 | hw_message(pao, phm, phr); | ||
991 | |||
992 | if (phr->error) | ||
993 | return; | ||
994 | |||
995 | /* update status information that the DSP would typically | ||
996 | * update (and will update next time the DSP | ||
997 | * buffer update task reads data from the host BBM buffer) | ||
998 | */ | ||
999 | status->auxiliary_data_available = phm->u.d.u.data.data_size; | ||
1000 | status->host_index += phm->u.d.u.data.data_size; | ||
1001 | status->dSP_index += phm->u.d.u.data.data_size; | ||
1002 | |||
1003 | /* if we did a full write, we can return from here. */ | ||
1004 | if (!partial_write) | ||
1005 | return; | ||
1006 | |||
1007 | /* tweak buffer parameters and let the rest of the */ | ||
1008 | /* buffer land in internal BBM buffer */ | ||
1009 | phm->u.d.u.data.data_size = | ||
1010 | original_size - HPI6205_SIZEOF_DATA; | ||
1011 | phm->u.d.u.data.pb_data += HPI6205_SIZEOF_DATA; | ||
1012 | } | ||
1013 | |||
1014 | space_available = outstream_get_space_available(status); | 905 | space_available = outstream_get_space_available(status); |
1015 | if (space_available < phm->u.d.u.data.data_size) { | 906 | if (space_available < phm->u.d.u.data.data_size) { |
1016 | phr->error = HPI_ERROR_INVALID_DATASIZE; | 907 | phr->error = HPI_ERROR_INVALID_DATASIZE; |
@@ -1047,6 +938,24 @@ static void outstream_write(struct hpi_adapter_obj *pao, | |||
1047 | memcpy(p_bbm_data, p_app_data + l_first_write, | 938 | memcpy(p_bbm_data, p_app_data + l_first_write, |
1048 | phm->u.d.u.data.data_size - l_first_write); | 939 | phm->u.d.u.data.data_size - l_first_write); |
1049 | } | 940 | } |
941 | |||
942 | /* | ||
943 | * This version relies on the DSP code triggering an OStream buffer | ||
944 | * update immediately following a SET_FORMAT call. The host has | ||
945 | * already written data into the BBM buffer, but the DSP won't know | ||
946 | * about it until dwHostIndex is adjusted. | ||
947 | */ | ||
948 | if (phw->flag_outstream_just_reset[phm->obj_index]) { | ||
949 | /* Format can only change after reset. Must tell DSP. */ | ||
950 | u16 function = phm->function; | ||
951 | phw->flag_outstream_just_reset[phm->obj_index] = 0; | ||
952 | phm->function = HPI_OSTREAM_SET_FORMAT; | ||
953 | hw_message(pao, phm, phr); /* send the format to the DSP */ | ||
954 | phm->function = function; | ||
955 | if (phr->error) | ||
956 | return; | ||
957 | } | ||
958 | |||
1050 | status->host_index += phm->u.d.u.data.data_size; | 959 | status->host_index += phm->u.d.u.data.data_size; |
1051 | } | 960 | } |
1052 | 961 | ||
@@ -1132,7 +1041,7 @@ static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao, | |||
1132 | 1041 | ||
1133 | err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm-> | 1042 | err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm-> |
1134 | obj_index], phm->u.d.u.buffer.buffer_size, | 1043 | obj_index], phm->u.d.u.buffer.buffer_size, |
1135 | pao->pci.p_os_data); | 1044 | pao->pci.pci_dev); |
1136 | 1045 | ||
1137 | if (err) { | 1046 | if (err) { |
1138 | phr->error = HPI_ERROR_INVALID_DATASIZE; | 1047 | phr->error = HPI_ERROR_INVALID_DATASIZE; |
@@ -1163,7 +1072,7 @@ static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao, | |||
1163 | if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. | 1072 | if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer. |
1164 | buffer_size - 1)) { | 1073 | buffer_size - 1)) { |
1165 | HPI_DEBUG_LOG(ERROR, | 1074 | HPI_DEBUG_LOG(ERROR, |
1166 | "buffer size must be 2^N not %d\n", | 1075 | "Buffer size must be 2^N not %d\n", |
1167 | phm->u.d.u.buffer.buffer_size); | 1076 | phm->u.d.u.buffer.buffer_size); |
1168 | phr->error = HPI_ERROR_INVALID_DATASIZE; | 1077 | phr->error = HPI_ERROR_INVALID_DATASIZE; |
1169 | return; | 1078 | return; |
@@ -1178,8 +1087,10 @@ static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao, | |||
1178 | status->dSP_index = 0; | 1087 | status->dSP_index = 0; |
1179 | status->host_index = status->dSP_index; | 1088 | status->host_index = status->dSP_index; |
1180 | status->size_in_bytes = phm->u.d.u.buffer.buffer_size; | 1089 | status->size_in_bytes = phm->u.d.u.buffer.buffer_size; |
1090 | status->auxiliary_data_available = 0; | ||
1181 | 1091 | ||
1182 | hw_message(pao, phm, phr); | 1092 | hw_message(pao, phm, phr); |
1093 | |||
1183 | if (phr->error | 1094 | if (phr->error |
1184 | && hpios_locked_mem_valid(&phw-> | 1095 | && hpios_locked_mem_valid(&phw-> |
1185 | instream_host_buffers[phm->obj_index])) { | 1096 | instream_host_buffers[phm->obj_index])) { |
@@ -1344,33 +1255,36 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1344 | struct hpi_hw_obj *phw = pao->priv; | 1255 | struct hpi_hw_obj *phw = pao->priv; |
1345 | struct dsp_code dsp_code; | 1256 | struct dsp_code dsp_code; |
1346 | u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD]; | 1257 | u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD]; |
1347 | u16 firmware_id = pao->pci.subsys_device_id; | ||
1348 | u32 temp; | 1258 | u32 temp; |
1349 | int dsp = 0, i = 0; | 1259 | int dsp = 0, i = 0; |
1350 | u16 err = 0; | 1260 | u16 err = 0; |
1351 | 1261 | ||
1352 | boot_code_id[0] = HPI_ADAPTER_ASI(0x6205); | 1262 | boot_code_id[0] = HPI_ADAPTER_ASI(0x6205); |
1353 | 1263 | ||
1354 | /* special cases where firmware_id != subsys ID */ | 1264 | boot_code_id[1] = pao->pci.pci_dev->subsystem_device; |
1355 | switch (firmware_id) { | 1265 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(boot_code_id[1]); |
1266 | |||
1267 | /* fix up cases where bootcode id[1] != subsys id */ | ||
1268 | switch (boot_code_id[1]) { | ||
1356 | case HPI_ADAPTER_FAMILY_ASI(0x5000): | 1269 | case HPI_ADAPTER_FAMILY_ASI(0x5000): |
1357 | boot_code_id[0] = firmware_id; | 1270 | boot_code_id[0] = boot_code_id[1]; |
1358 | firmware_id = 0; | 1271 | boot_code_id[1] = 0; |
1359 | break; | 1272 | break; |
1360 | case HPI_ADAPTER_FAMILY_ASI(0x5300): | 1273 | case HPI_ADAPTER_FAMILY_ASI(0x5300): |
1361 | case HPI_ADAPTER_FAMILY_ASI(0x5400): | 1274 | case HPI_ADAPTER_FAMILY_ASI(0x5400): |
1362 | case HPI_ADAPTER_FAMILY_ASI(0x6300): | 1275 | case HPI_ADAPTER_FAMILY_ASI(0x6300): |
1363 | firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6400); | 1276 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400); |
1364 | break; | 1277 | break; |
1365 | case HPI_ADAPTER_FAMILY_ASI(0x5600): | 1278 | case HPI_ADAPTER_FAMILY_ASI(0x5600): |
1366 | case HPI_ADAPTER_FAMILY_ASI(0x6500): | 1279 | case HPI_ADAPTER_FAMILY_ASI(0x6500): |
1367 | firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600); | 1280 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600); |
1368 | break; | 1281 | break; |
1369 | case HPI_ADAPTER_FAMILY_ASI(0x8800): | 1282 | case HPI_ADAPTER_FAMILY_ASI(0x8800): |
1370 | firmware_id = HPI_ADAPTER_FAMILY_ASI(0x8900); | 1283 | boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x8900); |
1284 | break; | ||
1285 | default: | ||
1371 | break; | 1286 | break; |
1372 | } | 1287 | } |
1373 | boot_code_id[1] = firmware_id; | ||
1374 | 1288 | ||
1375 | /* reset DSP by writing a 1 to the WARMRESET bit */ | 1289 | /* reset DSP by writing a 1 to the WARMRESET bit */ |
1376 | temp = C6205_HDCR_WARMRESET; | 1290 | temp = C6205_HDCR_WARMRESET; |
@@ -1381,7 +1295,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1381 | temp = ioread32(phw->prHSR); | 1295 | temp = ioread32(phw->prHSR); |
1382 | if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) != | 1296 | if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) != |
1383 | C6205_HSR_EEREAD) | 1297 | C6205_HSR_EEREAD) |
1384 | return hpi6205_error(0, HPI6205_ERROR_6205_EEPROM); | 1298 | return HPI6205_ERROR_6205_EEPROM; |
1385 | temp |= 0x04; | 1299 | temp |= 0x04; |
1386 | /* disable PINTA interrupt */ | 1300 | /* disable PINTA interrupt */ |
1387 | iowrite32(temp, phw->prHSR); | 1301 | iowrite32(temp, phw->prHSR); |
@@ -1389,27 +1303,27 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1389 | /* check control register reports PCI boot mode */ | 1303 | /* check control register reports PCI boot mode */ |
1390 | temp = ioread32(phw->prHDCR); | 1304 | temp = ioread32(phw->prHDCR); |
1391 | if (!(temp & C6205_HDCR_PCIBOOT)) | 1305 | if (!(temp & C6205_HDCR_PCIBOOT)) |
1392 | return hpi6205_error(0, HPI6205_ERROR_6205_REG); | 1306 | return HPI6205_ERROR_6205_REG; |
1393 | 1307 | ||
1394 | /* try writing a couple of numbers to the DSP page register */ | 1308 | /* try writing a few numbers to the DSP page register */ |
1395 | /* and reading them back. */ | 1309 | /* and reading them back. */ |
1396 | temp = 1; | 1310 | temp = 3; |
1397 | iowrite32(temp, phw->prDSPP); | 1311 | iowrite32(temp, phw->prDSPP); |
1398 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) | 1312 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) |
1399 | return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE); | 1313 | return HPI6205_ERROR_6205_DSPPAGE; |
1400 | temp = 2; | 1314 | temp = 2; |
1401 | iowrite32(temp, phw->prDSPP); | 1315 | iowrite32(temp, phw->prDSPP); |
1402 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) | 1316 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) |
1403 | return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE); | 1317 | return HPI6205_ERROR_6205_DSPPAGE; |
1404 | temp = 3; | 1318 | temp = 1; |
1405 | iowrite32(temp, phw->prDSPP); | 1319 | iowrite32(temp, phw->prDSPP); |
1406 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) | 1320 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) |
1407 | return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE); | 1321 | return HPI6205_ERROR_6205_DSPPAGE; |
1408 | /* reset DSP page to the correct number */ | 1322 | /* reset DSP page to the correct number */ |
1409 | temp = 0; | 1323 | temp = 0; |
1410 | iowrite32(temp, phw->prDSPP); | 1324 | iowrite32(temp, phw->prDSPP); |
1411 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) | 1325 | if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP)) |
1412 | return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE); | 1326 | return HPI6205_ERROR_6205_DSPPAGE; |
1413 | phw->dsp_page = 0; | 1327 | phw->dsp_page = 0; |
1414 | 1328 | ||
1415 | /* release 6713 from reset before 6205 is bootloaded. | 1329 | /* release 6713 from reset before 6205 is bootloaded. |
@@ -1455,7 +1369,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1455 | return err; | 1369 | return err; |
1456 | 1370 | ||
1457 | /* write the DSP code down into the DSPs memory */ | 1371 | /* write the DSP code down into the DSPs memory */ |
1458 | dsp_code.ps_dev = pao->pci.p_os_data; | 1372 | dsp_code.ps_dev = pao->pci.pci_dev; |
1459 | err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code, | 1373 | err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code, |
1460 | pos_error_code); | 1374 | pos_error_code); |
1461 | if (err) | 1375 | if (err) |
@@ -1484,10 +1398,8 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1484 | if (err) | 1398 | if (err) |
1485 | break; | 1399 | break; |
1486 | for (i = 0; i < (int)length; i++) { | 1400 | for (i = 0; i < (int)length; i++) { |
1487 | err = boot_loader_write_mem32(pao, dsp, | 1401 | boot_loader_write_mem32(pao, dsp, address, |
1488 | address, *pcode); | 1402 | *pcode); |
1489 | if (err) | ||
1490 | break; | ||
1491 | /* dummy read every 4 words */ | 1403 | /* dummy read every 4 words */ |
1492 | /* for 6205 advisory 1.4.4 */ | 1404 | /* for 6205 advisory 1.4.4 */ |
1493 | if (i % 4 == 0) | 1405 | if (i % 4 == 0) |
@@ -1561,7 +1473,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao, | |||
1561 | host_mailbox_address_on_dsp = 0x80000000; | 1473 | host_mailbox_address_on_dsp = 0x80000000; |
1562 | while ((physicalPC_iaddress != physicalPC_iaddress_verify) | 1474 | while ((physicalPC_iaddress != physicalPC_iaddress_verify) |
1563 | && time_out--) { | 1475 | && time_out--) { |
1564 | err = boot_loader_write_mem32(pao, 0, | 1476 | boot_loader_write_mem32(pao, 0, |
1565 | host_mailbox_address_on_dsp, | 1477 | host_mailbox_address_on_dsp, |
1566 | physicalPC_iaddress); | 1478 | physicalPC_iaddress); |
1567 | physicalPC_iaddress_verify = | 1479 | physicalPC_iaddress_verify = |
@@ -1631,11 +1543,10 @@ static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index, | |||
1631 | return data; | 1543 | return data; |
1632 | } | 1544 | } |
1633 | 1545 | ||
1634 | static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index, | 1546 | static void boot_loader_write_mem32(struct hpi_adapter_obj *pao, |
1635 | u32 address, u32 data) | 1547 | int dsp_index, u32 address, u32 data) |
1636 | { | 1548 | { |
1637 | struct hpi_hw_obj *phw = pao->priv; | 1549 | struct hpi_hw_obj *phw = pao->priv; |
1638 | u16 err = 0; | ||
1639 | __iomem u32 *p_data; | 1550 | __iomem u32 *p_data; |
1640 | /* u32 dwVerifyData=0; */ | 1551 | /* u32 dwVerifyData=0; */ |
1641 | 1552 | ||
@@ -1675,15 +1586,11 @@ static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index, | |||
1675 | 1586 | ||
1676 | /* dummy read every 4 words for 6205 advisory 1.4.4 */ | 1587 | /* dummy read every 4 words for 6205 advisory 1.4.4 */ |
1677 | boot_loader_read_mem32(pao, 0, 0); | 1588 | boot_loader_read_mem32(pao, 0, 0); |
1678 | } else | 1589 | } |
1679 | err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX); | ||
1680 | return err; | ||
1681 | } | 1590 | } |
1682 | 1591 | ||
1683 | static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | 1592 | static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) |
1684 | { | 1593 | { |
1685 | u16 err = 0; | ||
1686 | |||
1687 | if (dsp_index == 0) { | 1594 | if (dsp_index == 0) { |
1688 | u32 setting; | 1595 | u32 setting; |
1689 | 1596 | ||
@@ -1711,8 +1618,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | |||
1711 | boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting); | 1618 | boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting); |
1712 | if (setting != boot_loader_read_mem32(pao, dsp_index, | 1619 | if (setting != boot_loader_read_mem32(pao, dsp_index, |
1713 | 0x01800008)) | 1620 | 0x01800008)) |
1714 | return hpi6205_error(dsp_index, | 1621 | return HPI6205_ERROR_DSP_EMIF; |
1715 | HPI6205_ERROR_DSP_EMIF); | ||
1716 | 1622 | ||
1717 | /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */ | 1623 | /* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */ |
1718 | /* which occupies D15..0. 6713 starts at 27MHz, so need */ | 1624 | /* which occupies D15..0. 6713 starts at 27MHz, so need */ |
@@ -1725,8 +1631,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | |||
1725 | boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting); | 1631 | boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting); |
1726 | if (setting != boot_loader_read_mem32(pao, dsp_index, | 1632 | if (setting != boot_loader_read_mem32(pao, dsp_index, |
1727 | 0x01800004)) | 1633 | 0x01800004)) |
1728 | return hpi6205_error(dsp_index, | 1634 | return HPI6205_ERROR_DSP_EMIF; |
1729 | HPI6205_ERROR_DSP_EMIF); | ||
1730 | 1635 | ||
1731 | /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */ | 1636 | /* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */ |
1732 | /* which occupies D15..0. 6713 starts at 27MHz, so need */ | 1637 | /* which occupies D15..0. 6713 starts at 27MHz, so need */ |
@@ -1738,8 +1643,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | |||
1738 | boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting); | 1643 | boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting); |
1739 | if (setting != boot_loader_read_mem32(pao, dsp_index, | 1644 | if (setting != boot_loader_read_mem32(pao, dsp_index, |
1740 | 0x01800010)) | 1645 | 0x01800010)) |
1741 | return hpi6205_error(dsp_index, | 1646 | return HPI6205_ERROR_DSP_EMIF; |
1742 | HPI6205_ERROR_DSP_EMIF); | ||
1743 | 1647 | ||
1744 | /* EMIF CE3 setup - 32 bit async. */ | 1648 | /* EMIF CE3 setup - 32 bit async. */ |
1745 | /* This is the PLD on the ASI5000 cards only */ | 1649 | /* This is the PLD on the ASI5000 cards only */ |
@@ -1750,8 +1654,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | |||
1750 | boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting); | 1654 | boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting); |
1751 | if (setting != boot_loader_read_mem32(pao, dsp_index, | 1655 | if (setting != boot_loader_read_mem32(pao, dsp_index, |
1752 | 0x01800014)) | 1656 | 0x01800014)) |
1753 | return hpi6205_error(dsp_index, | 1657 | return HPI6205_ERROR_DSP_EMIF; |
1754 | HPI6205_ERROR_DSP_EMIF); | ||
1755 | 1658 | ||
1756 | /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */ | 1659 | /* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */ |
1757 | /* need to use this else DSP code crashes? */ | 1660 | /* need to use this else DSP code crashes? */ |
@@ -1775,12 +1678,9 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | |||
1775 | read_data = | 1678 | read_data = |
1776 | 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR); | 1679 | 0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR); |
1777 | if (write_data != read_data) { | 1680 | if (write_data != read_data) { |
1778 | err = hpi6205_error(dsp_index, | ||
1779 | HPI6205_ERROR_C6713_HPIC); | ||
1780 | HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data, | 1681 | HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data, |
1781 | read_data); | 1682 | read_data); |
1782 | 1683 | return HPI6205_ERROR_C6713_HPIC; | |
1783 | return err; | ||
1784 | } | 1684 | } |
1785 | /* HPIA - walking ones test */ | 1685 | /* HPIA - walking ones test */ |
1786 | write_data = 1; | 1686 | write_data = 1; |
@@ -1798,11 +1698,9 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | |||
1798 | HPIAH_ADDR)) | 1698 | HPIAH_ADDR)) |
1799 | << 16); | 1699 | << 16); |
1800 | if (read_data != write_data) { | 1700 | if (read_data != write_data) { |
1801 | err = hpi6205_error(dsp_index, | ||
1802 | HPI6205_ERROR_C6713_HPIA); | ||
1803 | HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n", | 1701 | HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n", |
1804 | write_data, read_data); | 1702 | write_data, read_data); |
1805 | return err; | 1703 | return HPI6205_ERROR_C6713_HPIA; |
1806 | } | 1704 | } |
1807 | write_data = write_data << 1; | 1705 | write_data = write_data << 1; |
1808 | } | 1706 | } |
@@ -1847,30 +1745,81 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index) | |||
1847 | /* PLL should not be bypassed! */ | 1745 | /* PLL should not be bypassed! */ |
1848 | if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF) | 1746 | if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF) |
1849 | != 0x0001) { | 1747 | != 0x0001) { |
1850 | err = hpi6205_error(dsp_index, | 1748 | return HPI6205_ERROR_C6713_PLL; |
1851 | HPI6205_ERROR_C6713_PLL); | ||
1852 | return err; | ||
1853 | } | 1749 | } |
1854 | /* setup C67x EMIF (note this is the only use of | 1750 | /* setup C67x EMIF (note this is the only use of |
1855 | BAR1 via BootLoader_WriteMem32) */ | 1751 | BAR1 via BootLoader_WriteMem32) */ |
1856 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL, | 1752 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL, |
1857 | 0x000034A8); | 1753 | 0x000034A8); |
1754 | |||
1755 | /* EMIF CE0 setup - 2Mx32 Sync DRAM | ||
1756 | 31..28 Wr setup | ||
1757 | 27..22 Wr strobe | ||
1758 | 21..20 Wr hold | ||
1759 | 19..16 Rd setup | ||
1760 | 15..14 - | ||
1761 | 13..8 Rd strobe | ||
1762 | 7..4 MTYPE 0011 Sync DRAM 32bits | ||
1763 | 3 Wr hold MSB | ||
1764 | 2..0 Rd hold | ||
1765 | */ | ||
1858 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0, | 1766 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0, |
1859 | 0x00000030); | 1767 | 0x00000030); |
1768 | |||
1769 | /* EMIF SDRAM Extension | ||
1770 | 0x00 | ||
1771 | 31-21 0000b 0000b 000b | ||
1772 | 20 WR2RD = 2cycles-1 = 1b | ||
1773 | |||
1774 | 19-18 WR2DEAC = 3cycle-1 = 10b | ||
1775 | 17 WR2WR = 2cycle-1 = 1b | ||
1776 | 16-15 R2WDQM = 4cycle-1 = 11b | ||
1777 | 14-12 RD2WR = 6cycles-1 = 101b | ||
1778 | |||
1779 | 11-10 RD2DEAC = 4cycle-1 = 11b | ||
1780 | 9 RD2RD = 2cycle-1 = 1b | ||
1781 | 8-7 THZP = 3cycle-1 = 10b | ||
1782 | 6-5 TWR = 2cycle-1 = 01b (tWR = 17ns) | ||
1783 | 4 TRRD = 2cycle = 0b (tRRD = 14ns) | ||
1784 | 3-1 TRAS = 5cycle-1 = 100b (Tras=42ns) | ||
1785 | 1 CAS latency = 3cyc = 1b | ||
1786 | (for Micron 2M32-7 operating at 100MHz) | ||
1787 | */ | ||
1860 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT, | 1788 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT, |
1861 | 0x001BDF29); | 1789 | 0x001BDF29); |
1790 | |||
1791 | /* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank) | ||
1792 | 31 - 0b - | ||
1793 | 30 SDBSZ 1b 4 bank | ||
1794 | 29..28 SDRSZ 00b 11 row address pins | ||
1795 | |||
1796 | 27..26 SDCSZ 01b 8 column address pins | ||
1797 | 25 RFEN 1b refersh enabled | ||
1798 | 24 INIT 1b init SDRAM! | ||
1799 | |||
1800 | 23..20 TRCD 0001b (Trcd/Tcyc)-1 = (20/10)-1 = 1 | ||
1801 | |||
1802 | 19..16 TRP 0001b (Trp/Tcyc)-1 = (20/10)-1 = 1 | ||
1803 | |||
1804 | 15..12 TRC 0110b (Trc/Tcyc)-1 = (70/10)-1 = 6 | ||
1805 | |||
1806 | 11..0 - 0000b 0000b 0000b | ||
1807 | */ | ||
1862 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL, | 1808 | boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL, |
1863 | 0x47117000); | 1809 | 0x47116000); |
1810 | |||
1811 | /* SDRAM refresh timing | ||
1812 | Need 4,096 refresh cycles every 64ms = 15.625us = 1562cycles of 100MHz = 0x61A | ||
1813 | */ | ||
1864 | boot_loader_write_mem32(pao, dsp_index, | 1814 | boot_loader_write_mem32(pao, dsp_index, |
1865 | C6713_EMIF_SDRAMTIMING, 0x00000410); | 1815 | C6713_EMIF_SDRAMTIMING, 0x00000410); |
1866 | 1816 | ||
1867 | hpios_delay_micro_seconds(1000); | 1817 | hpios_delay_micro_seconds(1000); |
1868 | } else if (dsp_index == 2) { | 1818 | } else if (dsp_index == 2) { |
1869 | /* DSP 2 is a C6713 */ | 1819 | /* DSP 2 is a C6713 */ |
1820 | } | ||
1870 | 1821 | ||
1871 | } else | 1822 | return 0; |
1872 | err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX); | ||
1873 | return err; | ||
1874 | } | 1823 | } |
1875 | 1824 | ||
1876 | static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, | 1825 | static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, |
@@ -1896,7 +1845,7 @@ static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, | |||
1896 | test_addr); | 1845 | test_addr); |
1897 | if (data != test_data) { | 1846 | if (data != test_data) { |
1898 | HPI_DEBUG_LOG(VERBOSE, | 1847 | HPI_DEBUG_LOG(VERBOSE, |
1899 | "memtest error details " | 1848 | "Memtest error details " |
1900 | "%08x %08x %08x %i\n", test_addr, | 1849 | "%08x %08x %08x %i\n", test_addr, |
1901 | test_data, data, dsp_index); | 1850 | test_data, data, dsp_index); |
1902 | return 1; /* error */ | 1851 | return 1; /* error */ |
@@ -1916,7 +1865,7 @@ static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index, | |||
1916 | data = boot_loader_read_mem32(pao, dsp_index, test_addr); | 1865 | data = boot_loader_read_mem32(pao, dsp_index, test_addr); |
1917 | if (data != test_data) { | 1866 | if (data != test_data) { |
1918 | HPI_DEBUG_LOG(VERBOSE, | 1867 | HPI_DEBUG_LOG(VERBOSE, |
1919 | "memtest error details " | 1868 | "Memtest error details " |
1920 | "%08x %08x %08x %i\n", test_addr, test_data, | 1869 | "%08x %08x %08x %i\n", test_addr, test_data, |
1921 | data, dsp_index); | 1870 | data, dsp_index); |
1922 | return 1; /* error */ | 1871 | return 1; /* error */ |
@@ -1946,8 +1895,8 @@ static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao, | |||
1946 | /* 64K data mem */ | 1895 | /* 64K data mem */ |
1947 | err = boot_loader_test_memory(pao, dsp_index, | 1896 | err = boot_loader_test_memory(pao, dsp_index, |
1948 | 0x80000000, 0x10000); | 1897 | 0x80000000, 0x10000); |
1949 | } else if ((dsp_index == 1) || (dsp_index == 2)) { | 1898 | } else if (dsp_index == 1) { |
1950 | /* DSP 1&2 are a C6713 */ | 1899 | /* DSP 1 is a C6713 */ |
1951 | /* 192K internal mem */ | 1900 | /* 192K internal mem */ |
1952 | err = boot_loader_test_memory(pao, dsp_index, 0x00000000, | 1901 | err = boot_loader_test_memory(pao, dsp_index, 0x00000000, |
1953 | 0x30000); | 1902 | 0x30000); |
@@ -1955,11 +1904,10 @@ static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao, | |||
1955 | /* 64K internal mem / L2 cache */ | 1904 | /* 64K internal mem / L2 cache */ |
1956 | err = boot_loader_test_memory(pao, dsp_index, | 1905 | err = boot_loader_test_memory(pao, dsp_index, |
1957 | 0x00030000, 0x10000); | 1906 | 0x00030000, 0x10000); |
1958 | } else | 1907 | } |
1959 | return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX); | ||
1960 | 1908 | ||
1961 | if (err) | 1909 | if (err) |
1962 | return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_INTMEM); | 1910 | return HPI6205_ERROR_DSP_INTMEM; |
1963 | else | 1911 | else |
1964 | return 0; | 1912 | return 0; |
1965 | } | 1913 | } |
@@ -1972,24 +1920,23 @@ static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao, | |||
1972 | 1920 | ||
1973 | if (dsp_index == 0) { | 1921 | if (dsp_index == 0) { |
1974 | /* only test for SDRAM if an ASI5000 card */ | 1922 | /* only test for SDRAM if an ASI5000 card */ |
1975 | if (pao->pci.subsys_device_id == 0x5000) { | 1923 | if (pao->pci.pci_dev->subsystem_device == 0x5000) { |
1976 | /* DSP 0 is always C6205 */ | 1924 | /* DSP 0 is always C6205 */ |
1977 | dRAM_start_address = 0x00400000; | 1925 | dRAM_start_address = 0x00400000; |
1978 | dRAM_size = 0x200000; | 1926 | dRAM_size = 0x200000; |
1979 | /*dwDRAMinc=1024; */ | 1927 | /*dwDRAMinc=1024; */ |
1980 | } else | 1928 | } else |
1981 | return 0; | 1929 | return 0; |
1982 | } else if ((dsp_index == 1) || (dsp_index == 2)) { | 1930 | } else if (dsp_index == 1) { |
1983 | /* DSP 1 is a C6713 */ | 1931 | /* DSP 1 is a C6713 */ |
1984 | dRAM_start_address = 0x80000000; | 1932 | dRAM_start_address = 0x80000000; |
1985 | dRAM_size = 0x200000; | 1933 | dRAM_size = 0x200000; |
1986 | /*dwDRAMinc=1024; */ | 1934 | /*dwDRAMinc=1024; */ |
1987 | } else | 1935 | } |
1988 | return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX); | ||
1989 | 1936 | ||
1990 | if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address, | 1937 | if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address, |
1991 | dRAM_size)) | 1938 | dRAM_size)) |
1992 | return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_EXTMEM); | 1939 | return HPI6205_ERROR_DSP_EXTMEM; |
1993 | return 0; | 1940 | return 0; |
1994 | } | 1941 | } |
1995 | 1942 | ||
@@ -1998,28 +1945,25 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index) | |||
1998 | u32 data = 0; | 1945 | u32 data = 0; |
1999 | if (dsp_index == 0) { | 1946 | if (dsp_index == 0) { |
2000 | /* only test for DSP0 PLD on ASI5000 card */ | 1947 | /* only test for DSP0 PLD on ASI5000 card */ |
2001 | if (pao->pci.subsys_device_id == 0x5000) { | 1948 | if (pao->pci.pci_dev->subsystem_device == 0x5000) { |
2002 | /* PLD is located at CE3=0x03000000 */ | 1949 | /* PLD is located at CE3=0x03000000 */ |
2003 | data = boot_loader_read_mem32(pao, dsp_index, | 1950 | data = boot_loader_read_mem32(pao, dsp_index, |
2004 | 0x03000008); | 1951 | 0x03000008); |
2005 | if ((data & 0xF) != 0x5) | 1952 | if ((data & 0xF) != 0x5) |
2006 | return hpi6205_error(dsp_index, | 1953 | return HPI6205_ERROR_DSP_PLD; |
2007 | HPI6205_ERROR_DSP_PLD); | ||
2008 | data = boot_loader_read_mem32(pao, dsp_index, | 1954 | data = boot_loader_read_mem32(pao, dsp_index, |
2009 | 0x0300000C); | 1955 | 0x0300000C); |
2010 | if ((data & 0xF) != 0xA) | 1956 | if ((data & 0xF) != 0xA) |
2011 | return hpi6205_error(dsp_index, | 1957 | return HPI6205_ERROR_DSP_PLD; |
2012 | HPI6205_ERROR_DSP_PLD); | ||
2013 | } | 1958 | } |
2014 | } else if (dsp_index == 1) { | 1959 | } else if (dsp_index == 1) { |
2015 | /* DSP 1 is a C6713 */ | 1960 | /* DSP 1 is a C6713 */ |
2016 | if (pao->pci.subsys_device_id == 0x8700) { | 1961 | if (pao->pci.pci_dev->subsystem_device == 0x8700) { |
2017 | /* PLD is located at CE1=0x90000000 */ | 1962 | /* PLD is located at CE1=0x90000000 */ |
2018 | data = boot_loader_read_mem32(pao, dsp_index, | 1963 | data = boot_loader_read_mem32(pao, dsp_index, |
2019 | 0x90000010); | 1964 | 0x90000010); |
2020 | if ((data & 0xFF) != 0xAA) | 1965 | if ((data & 0xFF) != 0xAA) |
2021 | return hpi6205_error(dsp_index, | 1966 | return HPI6205_ERROR_DSP_PLD; |
2022 | HPI6205_ERROR_DSP_PLD); | ||
2023 | /* 8713 - LED on */ | 1967 | /* 8713 - LED on */ |
2024 | boot_loader_write_mem32(pao, dsp_index, 0x90000000, | 1968 | boot_loader_write_mem32(pao, dsp_index, 0x90000000, |
2025 | 0x02); | 1969 | 0x02); |
@@ -2037,14 +1981,11 @@ static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data, | |||
2037 | struct hpi_hw_obj *phw = pao->priv; | 1981 | struct hpi_hw_obj *phw = pao->priv; |
2038 | u32 data_transferred = 0; | 1982 | u32 data_transferred = 0; |
2039 | u16 err = 0; | 1983 | u16 err = 0; |
2040 | #ifndef HPI6205_NO_HSR_POLL | ||
2041 | u32 time_out; | ||
2042 | #endif | ||
2043 | u32 temp2; | 1984 | u32 temp2; |
2044 | struct bus_master_interface *interface = phw->p_interface_buffer; | 1985 | struct bus_master_interface *interface = phw->p_interface_buffer; |
2045 | 1986 | ||
2046 | if (!p_data) | 1987 | if (!p_data) |
2047 | return HPI_ERROR_INVALID_DATA_TRANSFER; | 1988 | return HPI_ERROR_INVALID_DATA_POINTER; |
2048 | 1989 | ||
2049 | data_size &= ~3L; /* round data_size down to nearest 4 bytes */ | 1990 | data_size &= ~3L; /* round data_size down to nearest 4 bytes */ |
2050 | 1991 | ||
@@ -2064,14 +2005,10 @@ static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data, | |||
2064 | 2005 | ||
2065 | interface->transfer_size_in_bytes = this_copy; | 2006 | interface->transfer_size_in_bytes = this_copy; |
2066 | 2007 | ||
2067 | #ifdef HPI6205_NO_HSR_POLL | ||
2068 | /* DSP must change this back to nOperation */ | 2008 | /* DSP must change this back to nOperation */ |
2069 | interface->dsp_ack = H620_HIF_IDLE; | 2009 | interface->dsp_ack = H620_HIF_IDLE; |
2070 | #endif | ||
2071 | |||
2072 | send_dsp_command(phw, operation); | 2010 | send_dsp_command(phw, operation); |
2073 | 2011 | ||
2074 | #ifdef HPI6205_NO_HSR_POLL | ||
2075 | temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT); | 2012 | temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT); |
2076 | HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n", | 2013 | HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n", |
2077 | HPI6205_TIMEOUT - temp2, this_copy); | 2014 | HPI6205_TIMEOUT - temp2, this_copy); |
@@ -2079,45 +2016,11 @@ static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data, | |||
2079 | if (!temp2) { | 2016 | if (!temp2) { |
2080 | /* timed out */ | 2017 | /* timed out */ |
2081 | HPI_DEBUG_LOG(ERROR, | 2018 | HPI_DEBUG_LOG(ERROR, |
2082 | "timed out waiting for " "state %d got %d\n", | 2019 | "Timed out waiting for " "state %d got %d\n", |
2083 | operation, interface->dsp_ack); | 2020 | operation, interface->dsp_ack); |
2084 | 2021 | ||
2085 | break; | 2022 | break; |
2086 | } | 2023 | } |
2087 | #else | ||
2088 | /* spin waiting on the result */ | ||
2089 | time_out = HPI6205_TIMEOUT; | ||
2090 | temp2 = 0; | ||
2091 | while ((temp2 == 0) && time_out--) { | ||
2092 | /* give 16k bus mastering transfer time to happen */ | ||
2093 | /*(16k / 132Mbytes/s = 122usec) */ | ||
2094 | hpios_delay_micro_seconds(20); | ||
2095 | temp2 = ioread32(phw->prHSR); | ||
2096 | temp2 &= C6205_HSR_INTSRC; | ||
2097 | } | ||
2098 | HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n", | ||
2099 | HPI6205_TIMEOUT - time_out, this_copy); | ||
2100 | if (temp2 == C6205_HSR_INTSRC) { | ||
2101 | HPI_DEBUG_LOG(VERBOSE, | ||
2102 | "interrupt from HIF <data> OK\n"); | ||
2103 | /* | ||
2104 | if(interface->dwDspAck != nOperation) { | ||
2105 | HPI_DEBUG_LOG(DEBUG("interface->dwDspAck=%d, | ||
2106 | expected %d \n", | ||
2107 | interface->dwDspAck,nOperation); | ||
2108 | } | ||
2109 | */ | ||
2110 | } | ||
2111 | /* need to handle this differently... */ | ||
2112 | else { | ||
2113 | HPI_DEBUG_LOG(ERROR, | ||
2114 | "interrupt from HIF <data> BAD\n"); | ||
2115 | err = HPI_ERROR_DSP_HARDWARE; | ||
2116 | } | ||
2117 | |||
2118 | /* reset the interrupt from the DSP */ | ||
2119 | iowrite32(C6205_HSR_INTSRC, phw->prHSR); | ||
2120 | #endif | ||
2121 | if (operation == H620_HIF_GET_DATA) | 2024 | if (operation == H620_HIF_GET_DATA) |
2122 | memcpy(&p_data[data_transferred], | 2025 | memcpy(&p_data[data_transferred], |
2123 | (void *)&interface->u.b_data[0], this_copy); | 2026 | (void *)&interface->u.b_data[0], this_copy); |
@@ -2174,31 +2077,39 @@ static unsigned int message_count; | |||
2174 | static u16 message_response_sequence(struct hpi_adapter_obj *pao, | 2077 | static u16 message_response_sequence(struct hpi_adapter_obj *pao, |
2175 | struct hpi_message *phm, struct hpi_response *phr) | 2078 | struct hpi_message *phm, struct hpi_response *phr) |
2176 | { | 2079 | { |
2177 | #ifndef HPI6205_NO_HSR_POLL | ||
2178 | u32 temp2; | ||
2179 | #endif | ||
2180 | u32 time_out, time_out2; | 2080 | u32 time_out, time_out2; |
2181 | struct hpi_hw_obj *phw = pao->priv; | 2081 | struct hpi_hw_obj *phw = pao->priv; |
2182 | struct bus_master_interface *interface = phw->p_interface_buffer; | 2082 | struct bus_master_interface *interface = phw->p_interface_buffer; |
2183 | u16 err = 0; | 2083 | u16 err = 0; |
2184 | 2084 | ||
2185 | message_count++; | 2085 | message_count++; |
2086 | if (phm->size > sizeof(interface->u)) { | ||
2087 | phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL; | ||
2088 | phr->specific_error = sizeof(interface->u); | ||
2089 | phr->size = sizeof(struct hpi_response_header); | ||
2090 | HPI_DEBUG_LOG(ERROR, | ||
2091 | "message len %d too big for buffer %zd \n", phm->size, | ||
2092 | sizeof(interface->u)); | ||
2093 | return 0; | ||
2094 | } | ||
2095 | |||
2186 | /* Assume buffer of type struct bus_master_interface | 2096 | /* Assume buffer of type struct bus_master_interface |
2187 | is allocated "noncacheable" */ | 2097 | is allocated "noncacheable" */ |
2188 | 2098 | ||
2189 | if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { | 2099 | if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { |
2190 | HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n"); | 2100 | HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n"); |
2191 | return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT); | 2101 | return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT; |
2192 | } | 2102 | } |
2193 | interface->u.message_buffer = *phm; | 2103 | |
2104 | memcpy(&interface->u.message_buffer, phm, phm->size); | ||
2194 | /* signal we want a response */ | 2105 | /* signal we want a response */ |
2195 | send_dsp_command(phw, H620_HIF_GET_RESP); | 2106 | send_dsp_command(phw, H620_HIF_GET_RESP); |
2196 | 2107 | ||
2197 | time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT); | 2108 | time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT); |
2198 | 2109 | ||
2199 | if (time_out2 == 0) { | 2110 | if (!time_out2) { |
2200 | HPI_DEBUG_LOG(ERROR, | 2111 | HPI_DEBUG_LOG(ERROR, |
2201 | "(%u) timed out waiting for " "GET_RESP state [%x]\n", | 2112 | "(%u) Timed out waiting for " "GET_RESP state [%x]\n", |
2202 | message_count, interface->dsp_ack); | 2113 | message_count, interface->dsp_ack); |
2203 | } else { | 2114 | } else { |
2204 | HPI_DEBUG_LOG(VERBOSE, | 2115 | HPI_DEBUG_LOG(VERBOSE, |
@@ -2208,58 +2119,38 @@ static u16 message_response_sequence(struct hpi_adapter_obj *pao, | |||
2208 | /* spin waiting on HIF interrupt flag (end of msg process) */ | 2119 | /* spin waiting on HIF interrupt flag (end of msg process) */ |
2209 | time_out = HPI6205_TIMEOUT; | 2120 | time_out = HPI6205_TIMEOUT; |
2210 | 2121 | ||
2211 | #ifndef HPI6205_NO_HSR_POLL | 2122 | /* read the result */ |
2212 | temp2 = 0; | 2123 | if (time_out) { |
2213 | while ((temp2 == 0) && --time_out) { | 2124 | if (interface->u.response_buffer.size <= phr->size) |
2214 | temp2 = ioread32(phw->prHSR); | 2125 | memcpy(phr, &interface->u.response_buffer, |
2215 | temp2 &= C6205_HSR_INTSRC; | 2126 | interface->u.response_buffer.size); |
2216 | hpios_delay_micro_seconds(1); | 2127 | else { |
2217 | } | 2128 | HPI_DEBUG_LOG(ERROR, |
2218 | if (temp2 == C6205_HSR_INTSRC) { | 2129 | "response len %d too big for buffer %d\n", |
2219 | rmb(); /* ensure we see latest value for dsp_ack */ | 2130 | interface->u.response_buffer.size, phr->size); |
2220 | if ((interface->dsp_ack != H620_HIF_GET_RESP)) { | 2131 | memcpy(phr, &interface->u.response_buffer, |
2221 | HPI_DEBUG_LOG(DEBUG, | 2132 | sizeof(struct hpi_response_header)); |
2222 | "(%u)interface->dsp_ack(0x%x) != " | 2133 | phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; |
2223 | "H620_HIF_GET_RESP, t=%u\n", message_count, | 2134 | phr->specific_error = |
2224 | interface->dsp_ack, | 2135 | interface->u.response_buffer.size; |
2225 | HPI6205_TIMEOUT - time_out); | 2136 | phr->size = sizeof(struct hpi_response_header); |
2226 | } else { | ||
2227 | HPI_DEBUG_LOG(VERBOSE, | ||
2228 | "(%u)int with GET_RESP after %u\n", | ||
2229 | message_count, HPI6205_TIMEOUT - time_out); | ||
2230 | } | 2137 | } |
2231 | |||
2232 | } else { | ||
2233 | /* can we do anything else in response to the error ? */ | ||
2234 | HPI_DEBUG_LOG(ERROR, | ||
2235 | "interrupt from HIF module BAD (function %x)\n", | ||
2236 | phm->function); | ||
2237 | } | 2138 | } |
2238 | |||
2239 | /* reset the interrupt from the DSP */ | ||
2240 | iowrite32(C6205_HSR_INTSRC, phw->prHSR); | ||
2241 | #endif | ||
2242 | |||
2243 | /* read the result */ | ||
2244 | if (time_out != 0) | ||
2245 | *phr = interface->u.response_buffer; | ||
2246 | |||
2247 | /* set interface back to idle */ | 2139 | /* set interface back to idle */ |
2248 | send_dsp_command(phw, H620_HIF_IDLE); | 2140 | send_dsp_command(phw, H620_HIF_IDLE); |
2249 | 2141 | ||
2250 | if ((time_out == 0) || (time_out2 == 0)) { | 2142 | if (!time_out || !time_out2) { |
2251 | HPI_DEBUG_LOG(DEBUG, "something timed out!\n"); | 2143 | HPI_DEBUG_LOG(DEBUG, "something timed out!\n"); |
2252 | return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_TIMEOUT); | 2144 | return HPI6205_ERROR_MSG_RESP_TIMEOUT; |
2253 | } | 2145 | } |
2254 | /* special case for adapter close - */ | 2146 | /* special case for adapter close - */ |
2255 | /* wait for the DSP to indicate it is idle */ | 2147 | /* wait for the DSP to indicate it is idle */ |
2256 | if (phm->function == HPI_ADAPTER_CLOSE) { | 2148 | if (phm->function == HPI_ADAPTER_CLOSE) { |
2257 | if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { | 2149 | if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) { |
2258 | HPI_DEBUG_LOG(DEBUG, | 2150 | HPI_DEBUG_LOG(DEBUG, |
2259 | "timeout waiting for idle " | 2151 | "Timeout waiting for idle " |
2260 | "(on adapter_close)\n"); | 2152 | "(on adapter_close)\n"); |
2261 | return hpi6205_error(0, | 2153 | return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT; |
2262 | HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT); | ||
2263 | } | 2154 | } |
2264 | } | 2155 | } |
2265 | err = hpi_validate_response(phm, phr); | 2156 | err = hpi_validate_response(phm, phr); |
@@ -2279,7 +2170,13 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm, | |||
2279 | /* maybe an error response */ | 2170 | /* maybe an error response */ |
2280 | if (err) { | 2171 | if (err) { |
2281 | /* something failed in the HPI/DSP interface */ | 2172 | /* something failed in the HPI/DSP interface */ |
2282 | phr->error = err; | 2173 | if (err >= HPI_ERROR_BACKEND_BASE) { |
2174 | phr->error = HPI_ERROR_DSP_COMMUNICATION; | ||
2175 | phr->specific_error = err; | ||
2176 | } else { | ||
2177 | phr->error = err; | ||
2178 | } | ||
2179 | |||
2283 | pao->dsp_crashed++; | 2180 | pao->dsp_crashed++; |
2284 | 2181 | ||
2285 | /* just the header of the response is valid */ | 2182 | /* just the header of the response is valid */ |
diff --git a/sound/pci/asihpi/hpi6205.h b/sound/pci/asihpi/hpi6205.h index 1adae0857cda..df2f02c0c7b4 100644 --- a/sound/pci/asihpi/hpi6205.h +++ b/sound/pci/asihpi/hpi6205.h | |||
@@ -25,9 +25,6 @@ Copyright AudioScience, Inc., 2003 | |||
25 | #ifndef _HPI6205_H_ | 25 | #ifndef _HPI6205_H_ |
26 | #define _HPI6205_H_ | 26 | #define _HPI6205_H_ |
27 | 27 | ||
28 | /* transitional conditional compile shared between host and DSP */ | ||
29 | /* #define HPI6205_NO_HSR_POLL */ | ||
30 | |||
31 | #include "hpi_internal.h" | 28 | #include "hpi_internal.h" |
32 | 29 | ||
33 | /*********************************************************** | 30 | /*********************************************************** |
@@ -78,8 +75,8 @@ struct bus_master_interface { | |||
78 | u32 dsp_ack; | 75 | u32 dsp_ack; |
79 | u32 transfer_size_in_bytes; | 76 | u32 transfer_size_in_bytes; |
80 | union { | 77 | union { |
81 | struct hpi_message message_buffer; | 78 | struct hpi_message_header message_buffer; |
82 | struct hpi_response response_buffer; | 79 | struct hpi_response_header response_buffer; |
83 | u8 b_data[HPI6205_SIZEOF_DATA]; | 80 | u8 b_data[HPI6205_SIZEOF_DATA]; |
84 | } u; | 81 | } u; |
85 | struct controlcache_6205 control_cache; | 82 | struct controlcache_6205 control_cache; |
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h index 16f502d459de..af678be0aa15 100644 --- a/sound/pci/asihpi/hpi_internal.h +++ b/sound/pci/asihpi/hpi_internal.h | |||
@@ -28,7 +28,7 @@ HPI internal definitions | |||
28 | /** maximum number of memory regions mapped to an adapter */ | 28 | /** maximum number of memory regions mapped to an adapter */ |
29 | #define HPI_MAX_ADAPTER_MEM_SPACES (2) | 29 | #define HPI_MAX_ADAPTER_MEM_SPACES (2) |
30 | 30 | ||
31 | /* Each OS needs its own hpios.h, or specific define as above */ | 31 | /* Each OS needs its own hpios.h */ |
32 | #include "hpios.h" | 32 | #include "hpios.h" |
33 | 33 | ||
34 | /* physical memory allocation */ | 34 | /* physical memory allocation */ |
@@ -49,7 +49,7 @@ HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle. | |||
49 | */ | 49 | */ |
50 | u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle, | 50 | u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle, |
51 | /**< memory handle */ | 51 | /**< memory handle */ |
52 | u32 size, /**< size in bytes to allocate */ | 52 | u32 size, /**< Size in bytes to allocate */ |
53 | struct pci_dev *p_os_reference | 53 | struct pci_dev *p_os_reference |
54 | /**< OS specific data required for memory allocation */ | 54 | /**< OS specific data required for memory allocation */ |
55 | ); | 55 | ); |
@@ -96,41 +96,6 @@ typedef void hpi_handler_func(struct hpi_message *, struct hpi_response *); | |||
96 | #define compile_time_assert(cond, msg) \ | 96 | #define compile_time_assert(cond, msg) \ |
97 | typedef char ASSERT_##msg[(cond) ? 1 : -1] | 97 | typedef char ASSERT_##msg[(cond) ? 1 : -1] |
98 | 98 | ||
99 | /*/////////////////////////////////////////////////////////////////////////// */ | ||
100 | /* Private HPI Entity related definitions */ | ||
101 | |||
102 | #define STR_SIZE_FIELD_MAX 65535U | ||
103 | #define STR_TYPE_FIELD_MAX 255U | ||
104 | #define STR_ROLE_FIELD_MAX 255U | ||
105 | |||
106 | struct hpi_entity_str { | ||
107 | u16 size; | ||
108 | u8 type; | ||
109 | u8 role; | ||
110 | }; | ||
111 | |||
112 | #if defined(_MSC_VER) | ||
113 | #pragma warning(push) | ||
114 | #pragma warning(disable : 4200) | ||
115 | #endif | ||
116 | |||
117 | struct hpi_entity { | ||
118 | struct hpi_entity_str header; | ||
119 | #if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008)) | ||
120 | /* DSP C6000 compiler v6.0.8 and lower | ||
121 | do not support flexible array member */ | ||
122 | u8 value[]; | ||
123 | #else | ||
124 | /* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */ | ||
125 | #define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE | ||
126 | u8 value[1]; | ||
127 | #endif | ||
128 | }; | ||
129 | |||
130 | #if defined(_MSC_VER) | ||
131 | #pragma warning(pop) | ||
132 | #endif | ||
133 | |||
134 | /******************************************* bus types */ | 99 | /******************************************* bus types */ |
135 | enum HPI_BUSES { | 100 | enum HPI_BUSES { |
136 | HPI_BUS_ISAPNP = 1, | 101 | HPI_BUS_ISAPNP = 1, |
@@ -139,206 +104,155 @@ enum HPI_BUSES { | |||
139 | HPI_BUS_NET = 4 | 104 | HPI_BUS_NET = 4 |
140 | }; | 105 | }; |
141 | 106 | ||
107 | enum HPI_SUBSYS_OPTIONS { | ||
108 | /* 0, 256 are invalid, 1..255 reserved for global options */ | ||
109 | HPI_SUBSYS_OPT_NET_ENABLE = 257, | ||
110 | HPI_SUBSYS_OPT_NET_BROADCAST = 258, | ||
111 | HPI_SUBSYS_OPT_NET_UNICAST = 259, | ||
112 | HPI_SUBSYS_OPT_NET_ADDR = 260, | ||
113 | HPI_SUBSYS_OPT_NET_MASK = 261, | ||
114 | HPI_SUBSYS_OPT_NET_ADAPTER_ADDRESS_ADD = 262 | ||
115 | }; | ||
116 | |||
117 | /** Volume flags | ||
118 | */ | ||
119 | enum HPI_VOLUME_FLAGS { | ||
120 | /** Set if the volume control is muted */ | ||
121 | HPI_VOLUME_FLAG_MUTED = (1 << 0), | ||
122 | /** Set if the volume control has a mute function */ | ||
123 | HPI_VOLUME_FLAG_HAS_MUTE = (1 << 1), | ||
124 | /** Set if volume control can do autofading */ | ||
125 | HPI_VOLUME_FLAG_HAS_AUTOFADE = (1 << 2) | ||
126 | /* Note Flags >= (1<<8) are for DSP internal use only */ | ||
127 | }; | ||
128 | |||
142 | /******************************************* CONTROL ATTRIBUTES ****/ | 129 | /******************************************* CONTROL ATTRIBUTES ****/ |
143 | /* (in order of control type ID */ | 130 | /* (in order of control type ID */ |
144 | 131 | ||
145 | /* This allows for 255 control types, 256 unique attributes each */ | 132 | /* This allows for 255 control types, 256 unique attributes each */ |
146 | #define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai) | 133 | #define HPI_CTL_ATTR(ctl, ai) ((HPI_CONTROL_##ctl << 8) + ai) |
147 | 134 | ||
148 | /* Get the sub-index of the attribute for a control type */ | 135 | /* Get the sub-index of the attribute for a control type */ |
149 | #define HPI_CTL_ATTR_INDEX(i) (i&0xff) | 136 | #define HPI_CTL_ATTR_INDEX(i) (i & 0xff) |
150 | 137 | ||
151 | /* Extract the control from the control attribute */ | 138 | /* Extract the control from the control attribute */ |
152 | #define HPI_CTL_ATTR_CONTROL(i) (i>>8) | 139 | #define HPI_CTL_ATTR_CONTROL(i) (i >> 8) |
153 | |||
154 | /* Generic control attributes. */ | ||
155 | |||
156 | /** Enable a control. | ||
157 | 0=disable, 1=enable | ||
158 | \note generic to all mixer plugins? | ||
159 | */ | ||
160 | #define HPI_GENERIC_ENABLE HPI_CTL_ATTR(GENERIC, 1) | ||
161 | 140 | ||
162 | /** Enable event generation for a control. | 141 | /** Enable event generation for a control. |
163 | 0=disable, 1=enable | 142 | 0=disable, 1=enable |
164 | \note generic to all controls that can generate events | 143 | \note generic to all controls that can generate events |
165 | */ | 144 | */ |
166 | #define HPI_GENERIC_EVENT_ENABLE HPI_CTL_ATTR(GENERIC, 2) | 145 | |
167 | 146 | /** Unique identifiers for every control attribute | |
168 | /* Volume Control attributes */ | ||
169 | #define HPI_VOLUME_GAIN HPI_CTL_ATTR(VOLUME, 1) | ||
170 | #define HPI_VOLUME_AUTOFADE HPI_CTL_ATTR(VOLUME, 2) | ||
171 | |||
172 | /** For HPI_ControlQuery() to get the number of channels of a volume control*/ | ||
173 | #define HPI_VOLUME_NUM_CHANNELS HPI_CTL_ATTR(VOLUME, 6) | ||
174 | #define HPI_VOLUME_RANGE HPI_CTL_ATTR(VOLUME, 10) | ||
175 | |||
176 | /** Level Control attributes */ | ||
177 | #define HPI_LEVEL_GAIN HPI_CTL_ATTR(LEVEL, 1) | ||
178 | #define HPI_LEVEL_RANGE HPI_CTL_ATTR(LEVEL, 10) | ||
179 | |||
180 | /* Meter Control attributes */ | ||
181 | /** return RMS signal level */ | ||
182 | #define HPI_METER_RMS HPI_CTL_ATTR(METER, 1) | ||
183 | /** return peak signal level */ | ||
184 | #define HPI_METER_PEAK HPI_CTL_ATTR(METER, 2) | ||
185 | /** ballistics for ALL rms meters on adapter */ | ||
186 | #define HPI_METER_RMS_BALLISTICS HPI_CTL_ATTR(METER, 3) | ||
187 | /** ballistics for ALL peak meters on adapter */ | ||
188 | #define HPI_METER_PEAK_BALLISTICS HPI_CTL_ATTR(METER, 4) | ||
189 | |||
190 | /** For HPI_ControlQuery() to get the number of channels of a meter control*/ | ||
191 | #define HPI_METER_NUM_CHANNELS HPI_CTL_ATTR(METER, 5) | ||
192 | |||
193 | /* Multiplexer control attributes */ | ||
194 | #define HPI_MULTIPLEXER_SOURCE HPI_CTL_ATTR(MULTIPLEXER, 1) | ||
195 | #define HPI_MULTIPLEXER_QUERYSOURCE HPI_CTL_ATTR(MULTIPLEXER, 2) | ||
196 | |||
197 | /** AES/EBU transmitter control attributes */ | ||
198 | /** AESEBU or SPDIF */ | ||
199 | #define HPI_AESEBUTX_FORMAT HPI_CTL_ATTR(AESEBUTX, 1) | ||
200 | #define HPI_AESEBUTX_SAMPLERATE HPI_CTL_ATTR(AESEBUTX, 3) | ||
201 | #define HPI_AESEBUTX_CHANNELSTATUS HPI_CTL_ATTR(AESEBUTX, 4) | ||
202 | #define HPI_AESEBUTX_USERDATA HPI_CTL_ATTR(AESEBUTX, 5) | ||
203 | |||
204 | /** AES/EBU receiver control attributes */ | ||
205 | #define HPI_AESEBURX_FORMAT HPI_CTL_ATTR(AESEBURX, 1) | ||
206 | #define HPI_AESEBURX_ERRORSTATUS HPI_CTL_ATTR(AESEBURX, 2) | ||
207 | #define HPI_AESEBURX_SAMPLERATE HPI_CTL_ATTR(AESEBURX, 3) | ||
208 | #define HPI_AESEBURX_CHANNELSTATUS HPI_CTL_ATTR(AESEBURX, 4) | ||
209 | #define HPI_AESEBURX_USERDATA HPI_CTL_ATTR(AESEBURX, 5) | ||
210 | |||
211 | /** \defgroup tuner_defs Tuners | ||
212 | \{ | ||
213 | */ | ||
214 | /** \defgroup tuner_attrs Tuner control attributes | ||
215 | \{ | ||
216 | */ | ||
217 | #define HPI_TUNER_BAND HPI_CTL_ATTR(TUNER, 1) | ||
218 | #define HPI_TUNER_FREQ HPI_CTL_ATTR(TUNER, 2) | ||
219 | #define HPI_TUNER_LEVEL HPI_CTL_ATTR(TUNER, 3) | ||
220 | #define HPI_TUNER_AUDIOMUTE HPI_CTL_ATTR(TUNER, 4) | ||
221 | /* use TUNER_STATUS instead */ | ||
222 | #define HPI_TUNER_VIDEO_STATUS HPI_CTL_ATTR(TUNER, 5) | ||
223 | #define HPI_TUNER_GAIN HPI_CTL_ATTR(TUNER, 6) | ||
224 | #define HPI_TUNER_STATUS HPI_CTL_ATTR(TUNER, 7) | ||
225 | #define HPI_TUNER_MODE HPI_CTL_ATTR(TUNER, 8) | ||
226 | /** RDS data. */ | ||
227 | #define HPI_TUNER_RDS HPI_CTL_ATTR(TUNER, 9) | ||
228 | /** Audio pre-emphasis. */ | ||
229 | #define HPI_TUNER_DEEMPHASIS HPI_CTL_ATTR(TUNER, 10) | ||
230 | /** HD Radio tuner program control. */ | ||
231 | #define HPI_TUNER_PROGRAM HPI_CTL_ATTR(TUNER, 11) | ||
232 | /** HD Radio tuner digital signal quality. */ | ||
233 | #define HPI_TUNER_HDRADIO_SIGNAL_QUALITY HPI_CTL_ATTR(TUNER, 12) | ||
234 | /** HD Radio SDK firmware version. */ | ||
235 | #define HPI_TUNER_HDRADIO_SDK_VERSION HPI_CTL_ATTR(TUNER, 13) | ||
236 | /** HD Radio DSP firmware version. */ | ||
237 | #define HPI_TUNER_HDRADIO_DSP_VERSION HPI_CTL_ATTR(TUNER, 14) | ||
238 | /** HD Radio signal blend (force analog, or automatic). */ | ||
239 | #define HPI_TUNER_HDRADIO_BLEND HPI_CTL_ATTR(TUNER, 15) | ||
240 | |||
241 | /** \} */ | ||
242 | |||
243 | /** \defgroup pads_attrs Tuner PADs control attributes | ||
244 | \{ | ||
245 | */ | ||
246 | /** The text string containing the station/channel combination. */ | ||
247 | #define HPI_PAD_CHANNEL_NAME HPI_CTL_ATTR(PAD, 1) | ||
248 | /** The text string containing the artist. */ | ||
249 | #define HPI_PAD_ARTIST HPI_CTL_ATTR(PAD, 2) | ||
250 | /** The text string containing the title. */ | ||
251 | #define HPI_PAD_TITLE HPI_CTL_ATTR(PAD, 3) | ||
252 | /** The text string containing the comment. */ | ||
253 | #define HPI_PAD_COMMENT HPI_CTL_ATTR(PAD, 4) | ||
254 | /** The integer containing the PTY code. */ | ||
255 | #define HPI_PAD_PROGRAM_TYPE HPI_CTL_ATTR(PAD, 5) | ||
256 | /** The integer containing the program identification. */ | ||
257 | #define HPI_PAD_PROGRAM_ID HPI_CTL_ATTR(PAD, 6) | ||
258 | /** The integer containing whether traffic information is supported. | ||
259 | Contains either 1 or 0. */ | ||
260 | #define HPI_PAD_TA_SUPPORT HPI_CTL_ATTR(PAD, 7) | ||
261 | /** The integer containing whether traffic announcement is in progress. | ||
262 | Contains either 1 or 0. */ | ||
263 | #define HPI_PAD_TA_ACTIVE HPI_CTL_ATTR(PAD, 8) | ||
264 | /** \} */ | ||
265 | /** \} */ | ||
266 | |||
267 | /* VOX control attributes */ | ||
268 | #define HPI_VOX_THRESHOLD HPI_CTL_ATTR(VOX, 1) | ||
269 | |||
270 | /*?? channel mode used hpi_multiplexer_source attribute == 1 */ | ||
271 | #define HPI_CHANNEL_MODE_MODE HPI_CTL_ATTR(CHANNEL_MODE, 1) | ||
272 | |||
273 | /** \defgroup channel_modes Channel Modes | ||
274 | Used for HPI_ChannelModeSet/Get() | ||
275 | \{ | ||
276 | */ | 147 | */ |
277 | /** Left channel out = left channel in, Right channel out = right channel in. */ | 148 | enum HPI_CONTROL_ATTRIBUTES { |
278 | #define HPI_CHANNEL_MODE_NORMAL 1 | 149 | HPI_GENERIC_ENABLE = HPI_CTL_ATTR(GENERIC, 1), |
279 | /** Left channel out = right channel in, Right channel out = left channel in. */ | 150 | HPI_GENERIC_EVENT_ENABLE = HPI_CTL_ATTR(GENERIC, 2), |
280 | #define HPI_CHANNEL_MODE_SWAP 2 | 151 | |
281 | /** Left channel out = left channel in, Right channel out = left channel in. */ | 152 | HPI_VOLUME_GAIN = HPI_CTL_ATTR(VOLUME, 1), |
282 | #define HPI_CHANNEL_MODE_LEFT_TO_STEREO 3 | 153 | HPI_VOLUME_AUTOFADE = HPI_CTL_ATTR(VOLUME, 2), |
283 | /** Left channel out = right channel in, Right channel out = right channel in.*/ | 154 | HPI_VOLUME_MUTE = HPI_CTL_ATTR(VOLUME, 3), |
284 | #define HPI_CHANNEL_MODE_RIGHT_TO_STEREO 4 | 155 | HPI_VOLUME_GAIN_AND_FLAGS = HPI_CTL_ATTR(VOLUME, 4), |
285 | /** Left channel out = (left channel in + right channel in)/2, | 156 | HPI_VOLUME_NUM_CHANNELS = HPI_CTL_ATTR(VOLUME, 6), |
286 | Right channel out = mute. */ | 157 | HPI_VOLUME_RANGE = HPI_CTL_ATTR(VOLUME, 10), |
287 | #define HPI_CHANNEL_MODE_STEREO_TO_LEFT 5 | 158 | |
288 | /** Left channel out = mute, | 159 | HPI_METER_RMS = HPI_CTL_ATTR(METER, 1), |
289 | Right channel out = (right channel in + left channel in)/2. */ | 160 | HPI_METER_PEAK = HPI_CTL_ATTR(METER, 2), |
290 | #define HPI_CHANNEL_MODE_STEREO_TO_RIGHT 6 | 161 | HPI_METER_RMS_BALLISTICS = HPI_CTL_ATTR(METER, 3), |
291 | #define HPI_CHANNEL_MODE_LAST 6 | 162 | HPI_METER_PEAK_BALLISTICS = HPI_CTL_ATTR(METER, 4), |
292 | /** \} */ | 163 | HPI_METER_NUM_CHANNELS = HPI_CTL_ATTR(METER, 5), |
293 | 164 | ||
294 | /* Bitstream control set attributes */ | 165 | HPI_MULTIPLEXER_SOURCE = HPI_CTL_ATTR(MULTIPLEXER, 1), |
295 | #define HPI_BITSTREAM_DATA_POLARITY HPI_CTL_ATTR(BITSTREAM, 1) | 166 | HPI_MULTIPLEXER_QUERYSOURCE = HPI_CTL_ATTR(MULTIPLEXER, 2), |
296 | #define HPI_BITSTREAM_CLOCK_EDGE HPI_CTL_ATTR(BITSTREAM, 2) | 167 | |
297 | #define HPI_BITSTREAM_CLOCK_SOURCE HPI_CTL_ATTR(BITSTREAM, 3) | 168 | HPI_AESEBUTX_FORMAT = HPI_CTL_ATTR(AESEBUTX, 1), |
169 | HPI_AESEBUTX_SAMPLERATE = HPI_CTL_ATTR(AESEBUTX, 3), | ||
170 | HPI_AESEBUTX_CHANNELSTATUS = HPI_CTL_ATTR(AESEBUTX, 4), | ||
171 | HPI_AESEBUTX_USERDATA = HPI_CTL_ATTR(AESEBUTX, 5), | ||
172 | |||
173 | HPI_AESEBURX_FORMAT = HPI_CTL_ATTR(AESEBURX, 1), | ||
174 | HPI_AESEBURX_ERRORSTATUS = HPI_CTL_ATTR(AESEBURX, 2), | ||
175 | HPI_AESEBURX_SAMPLERATE = HPI_CTL_ATTR(AESEBURX, 3), | ||
176 | HPI_AESEBURX_CHANNELSTATUS = HPI_CTL_ATTR(AESEBURX, 4), | ||
177 | HPI_AESEBURX_USERDATA = HPI_CTL_ATTR(AESEBURX, 5), | ||
178 | |||
179 | HPI_LEVEL_GAIN = HPI_CTL_ATTR(LEVEL, 1), | ||
180 | HPI_LEVEL_RANGE = HPI_CTL_ATTR(LEVEL, 10), | ||
181 | |||
182 | HPI_TUNER_BAND = HPI_CTL_ATTR(TUNER, 1), | ||
183 | HPI_TUNER_FREQ = HPI_CTL_ATTR(TUNER, 2), | ||
184 | HPI_TUNER_LEVEL_AVG = HPI_CTL_ATTR(TUNER, 3), | ||
185 | HPI_TUNER_LEVEL_RAW = HPI_CTL_ATTR(TUNER, 4), | ||
186 | HPI_TUNER_SNR = HPI_CTL_ATTR(TUNER, 5), | ||
187 | HPI_TUNER_GAIN = HPI_CTL_ATTR(TUNER, 6), | ||
188 | HPI_TUNER_STATUS = HPI_CTL_ATTR(TUNER, 7), | ||
189 | HPI_TUNER_MODE = HPI_CTL_ATTR(TUNER, 8), | ||
190 | HPI_TUNER_RDS = HPI_CTL_ATTR(TUNER, 9), | ||
191 | HPI_TUNER_DEEMPHASIS = HPI_CTL_ATTR(TUNER, 10), | ||
192 | HPI_TUNER_PROGRAM = HPI_CTL_ATTR(TUNER, 11), | ||
193 | HPI_TUNER_HDRADIO_SIGNAL_QUALITY = HPI_CTL_ATTR(TUNER, 12), | ||
194 | HPI_TUNER_HDRADIO_SDK_VERSION = HPI_CTL_ATTR(TUNER, 13), | ||
195 | HPI_TUNER_HDRADIO_DSP_VERSION = HPI_CTL_ATTR(TUNER, 14), | ||
196 | HPI_TUNER_HDRADIO_BLEND = HPI_CTL_ATTR(TUNER, 15), | ||
197 | |||
198 | HPI_VOX_THRESHOLD = HPI_CTL_ATTR(VOX, 1), | ||
199 | |||
200 | HPI_CHANNEL_MODE_MODE = HPI_CTL_ATTR(CHANNEL_MODE, 1), | ||
201 | |||
202 | HPI_BITSTREAM_DATA_POLARITY = HPI_CTL_ATTR(BITSTREAM, 1), | ||
203 | HPI_BITSTREAM_CLOCK_EDGE = HPI_CTL_ATTR(BITSTREAM, 2), | ||
204 | HPI_BITSTREAM_CLOCK_SOURCE = HPI_CTL_ATTR(BITSTREAM, 3), | ||
205 | HPI_BITSTREAM_ACTIVITY = HPI_CTL_ATTR(BITSTREAM, 4), | ||
206 | |||
207 | HPI_SAMPLECLOCK_SOURCE = HPI_CTL_ATTR(SAMPLECLOCK, 1), | ||
208 | HPI_SAMPLECLOCK_SAMPLERATE = HPI_CTL_ATTR(SAMPLECLOCK, 2), | ||
209 | HPI_SAMPLECLOCK_SOURCE_INDEX = HPI_CTL_ATTR(SAMPLECLOCK, 3), | ||
210 | HPI_SAMPLECLOCK_LOCAL_SAMPLERATE = HPI_CTL_ATTR(SAMPLECLOCK, 4), | ||
211 | HPI_SAMPLECLOCK_AUTO = HPI_CTL_ATTR(SAMPLECLOCK, 5), | ||
212 | HPI_SAMPLECLOCK_LOCAL_LOCK = HPI_CTL_ATTR(SAMPLECLOCK, 6), | ||
213 | |||
214 | HPI_MICROPHONE_PHANTOM_POWER = HPI_CTL_ATTR(MICROPHONE, 1), | ||
215 | |||
216 | HPI_EQUALIZER_NUM_FILTERS = HPI_CTL_ATTR(EQUALIZER, 1), | ||
217 | HPI_EQUALIZER_FILTER = HPI_CTL_ATTR(EQUALIZER, 2), | ||
218 | HPI_EQUALIZER_COEFFICIENTS = HPI_CTL_ATTR(EQUALIZER, 3), | ||
219 | |||
220 | HPI_COMPANDER_PARAMS = HPI_CTL_ATTR(COMPANDER, 1), | ||
221 | HPI_COMPANDER_MAKEUPGAIN = HPI_CTL_ATTR(COMPANDER, 2), | ||
222 | HPI_COMPANDER_THRESHOLD = HPI_CTL_ATTR(COMPANDER, 3), | ||
223 | HPI_COMPANDER_RATIO = HPI_CTL_ATTR(COMPANDER, 4), | ||
224 | HPI_COMPANDER_ATTACK = HPI_CTL_ATTR(COMPANDER, 5), | ||
225 | HPI_COMPANDER_DECAY = HPI_CTL_ATTR(COMPANDER, 6), | ||
226 | |||
227 | HPI_COBRANET_SET = HPI_CTL_ATTR(COBRANET, 1), | ||
228 | HPI_COBRANET_GET = HPI_CTL_ATTR(COBRANET, 2), | ||
229 | HPI_COBRANET_SET_DATA = HPI_CTL_ATTR(COBRANET, 3), | ||
230 | HPI_COBRANET_GET_DATA = HPI_CTL_ATTR(COBRANET, 4), | ||
231 | HPI_COBRANET_GET_STATUS = HPI_CTL_ATTR(COBRANET, 5), | ||
232 | HPI_COBRANET_SEND_PACKET = HPI_CTL_ATTR(COBRANET, 6), | ||
233 | HPI_COBRANET_GET_PACKET = HPI_CTL_ATTR(COBRANET, 7), | ||
234 | |||
235 | HPI_TONEDETECTOR_THRESHOLD = HPI_CTL_ATTR(TONEDETECTOR, 1), | ||
236 | HPI_TONEDETECTOR_STATE = HPI_CTL_ATTR(TONEDETECTOR, 2), | ||
237 | HPI_TONEDETECTOR_FREQUENCY = HPI_CTL_ATTR(TONEDETECTOR, 3), | ||
238 | |||
239 | HPI_SILENCEDETECTOR_THRESHOLD = HPI_CTL_ATTR(SILENCEDETECTOR, 1), | ||
240 | HPI_SILENCEDETECTOR_STATE = HPI_CTL_ATTR(SILENCEDETECTOR, 2), | ||
241 | HPI_SILENCEDETECTOR_DELAY = HPI_CTL_ATTR(SILENCEDETECTOR, 3), | ||
242 | |||
243 | HPI_PAD_CHANNEL_NAME = HPI_CTL_ATTR(PAD, 1), | ||
244 | HPI_PAD_ARTIST = HPI_CTL_ATTR(PAD, 2), | ||
245 | HPI_PAD_TITLE = HPI_CTL_ATTR(PAD, 3), | ||
246 | HPI_PAD_COMMENT = HPI_CTL_ATTR(PAD, 4), | ||
247 | HPI_PAD_PROGRAM_TYPE = HPI_CTL_ATTR(PAD, 5), | ||
248 | HPI_PAD_PROGRAM_ID = HPI_CTL_ATTR(PAD, 6), | ||
249 | HPI_PAD_TA_SUPPORT = HPI_CTL_ATTR(PAD, 7), | ||
250 | HPI_PAD_TA_ACTIVE = HPI_CTL_ATTR(PAD, 8) | ||
251 | }; | ||
298 | 252 | ||
299 | #define HPI_POLARITY_POSITIVE 0 | 253 | #define HPI_POLARITY_POSITIVE 0 |
300 | #define HPI_POLARITY_NEGATIVE 1 | 254 | #define HPI_POLARITY_NEGATIVE 1 |
301 | 255 | ||
302 | /* Bitstream control get attributes */ | ||
303 | #define HPI_BITSTREAM_ACTIVITY 1 | ||
304 | |||
305 | /* SampleClock control attributes */ | ||
306 | #define HPI_SAMPLECLOCK_SOURCE HPI_CTL_ATTR(SAMPLECLOCK, 1) | ||
307 | #define HPI_SAMPLECLOCK_SAMPLERATE HPI_CTL_ATTR(SAMPLECLOCK, 2) | ||
308 | #define HPI_SAMPLECLOCK_SOURCE_INDEX HPI_CTL_ATTR(SAMPLECLOCK, 3) | ||
309 | #define HPI_SAMPLECLOCK_LOCAL_SAMPLERATE\ | ||
310 | HPI_CTL_ATTR(SAMPLECLOCK, 4) | ||
311 | #define HPI_SAMPLECLOCK_AUTO HPI_CTL_ATTR(SAMPLECLOCK, 5) | ||
312 | #define HPI_SAMPLECLOCK_LOCAL_LOCK HPI_CTL_ATTR(SAMPLECLOCK, 6) | ||
313 | |||
314 | /* Microphone control attributes */ | ||
315 | #define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1) | ||
316 | |||
317 | /** Equalizer control attributes */ | ||
318 | /** Used to get number of filters in an EQ. (Can't set) */ | ||
319 | #define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1) | ||
320 | /** Set/get the filter by type, freq, Q, gain */ | ||
321 | #define HPI_EQUALIZER_FILTER HPI_CTL_ATTR(EQUALIZER, 2) | ||
322 | /** Get the biquad coefficients */ | ||
323 | #define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3) | ||
324 | |||
325 | /* Note compander also uses HPI_GENERIC_ENABLE */ | ||
326 | #define HPI_COMPANDER_PARAMS HPI_CTL_ATTR(COMPANDER, 1) | ||
327 | #define HPI_COMPANDER_MAKEUPGAIN HPI_CTL_ATTR(COMPANDER, 2) | ||
328 | #define HPI_COMPANDER_THRESHOLD HPI_CTL_ATTR(COMPANDER, 3) | ||
329 | #define HPI_COMPANDER_RATIO HPI_CTL_ATTR(COMPANDER, 4) | ||
330 | #define HPI_COMPANDER_ATTACK HPI_CTL_ATTR(COMPANDER, 5) | ||
331 | #define HPI_COMPANDER_DECAY HPI_CTL_ATTR(COMPANDER, 6) | ||
332 | |||
333 | /* Cobranet control attributes. */ | ||
334 | #define HPI_COBRANET_SET HPI_CTL_ATTR(COBRANET, 1) | ||
335 | #define HPI_COBRANET_GET HPI_CTL_ATTR(COBRANET, 2) | ||
336 | #define HPI_COBRANET_SET_DATA HPI_CTL_ATTR(COBRANET, 3) | ||
337 | #define HPI_COBRANET_GET_DATA HPI_CTL_ATTR(COBRANET, 4) | ||
338 | #define HPI_COBRANET_GET_STATUS HPI_CTL_ATTR(COBRANET, 5) | ||
339 | #define HPI_COBRANET_SEND_PACKET HPI_CTL_ATTR(COBRANET, 6) | ||
340 | #define HPI_COBRANET_GET_PACKET HPI_CTL_ATTR(COBRANET, 7) | ||
341 | |||
342 | /*------------------------------------------------------------ | 256 | /*------------------------------------------------------------ |
343 | Cobranet Chip Bridge - copied from HMI.H | 257 | Cobranet Chip Bridge - copied from HMI.H |
344 | ------------------------------------------------------------*/ | 258 | ------------------------------------------------------------*/ |
@@ -395,69 +309,22 @@ Used for HPI_ChannelModeSet/Get() | |||
395 | 309 | ||
396 | #define HPI_ETHERNET_UDP_PORT (44600) /*!< UDP messaging port */ | 310 | #define HPI_ETHERNET_UDP_PORT (44600) /*!< UDP messaging port */ |
397 | 311 | ||
398 | /** Base network time out is set to 100 milli-seconds. */ | 312 | /** Default network timeout in milli-seconds. */ |
399 | #define HPI_ETHERNET_TIMEOUT_MS (100) | 313 | #define HPI_ETHERNET_TIMEOUT_MS 500 |
400 | |||
401 | /** \defgroup tonedet_attr Tonedetector attributes | ||
402 | \{ | ||
403 | Used by HPI_ToneDetector_Set() and HPI_ToneDetector_Get() | ||
404 | */ | ||
405 | |||
406 | /** Set the threshold level of a tonedetector, | ||
407 | Threshold is a -ve number in units of dB/100, | ||
408 | */ | ||
409 | #define HPI_TONEDETECTOR_THRESHOLD HPI_CTL_ATTR(TONEDETECTOR, 1) | ||
410 | |||
411 | /** Get the current state of tonedetection | ||
412 | The result is a bitmap of detected tones. pairs of bits represent the left | ||
413 | and right channels, with left channel in LSB. | ||
414 | The lowest frequency detector state is in the LSB | ||
415 | */ | ||
416 | #define HPI_TONEDETECTOR_STATE HPI_CTL_ATTR(TONEDETECTOR, 2) | ||
417 | |||
418 | /** Get the frequency of a tonedetector band. | ||
419 | */ | ||
420 | #define HPI_TONEDETECTOR_FREQUENCY HPI_CTL_ATTR(TONEDETECTOR, 3) | ||
421 | |||
422 | /**\}*/ | ||
423 | 314 | ||
424 | /** \defgroup silencedet_attr SilenceDetector attributes | 315 | /** Locked memory buffer alloc/free phases */ |
425 | \{ | 316 | enum HPI_BUFFER_CMDS { |
426 | */ | 317 | /** use one message to allocate or free physical memory */ |
427 | 318 | HPI_BUFFER_CMD_EXTERNAL = 0, | |
428 | /** Get the current state of tonedetection | 319 | /** alloc physical memory */ |
429 | The result is a bitmap with 1s for silent channels. Left channel is in LSB | 320 | HPI_BUFFER_CMD_INTERNAL_ALLOC = 1, |
430 | */ | 321 | /** send physical memory address to adapter */ |
431 | #define HPI_SILENCEDETECTOR_STATE \ | 322 | HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER = 2, |
432 | HPI_CTL_ATTR(SILENCEDETECTOR, 2) | 323 | /** notify adapter to stop using physical buffer */ |
433 | 324 | HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER = 3, | |
434 | /** Set the threshold level of a SilenceDetector, | 325 | /** free physical buffer */ |
435 | Threshold is a -ve number in units of dB/100, | 326 | HPI_BUFFER_CMD_INTERNAL_FREE = 4 |
436 | */ | 327 | }; |
437 | #define HPI_SILENCEDETECTOR_THRESHOLD \ | ||
438 | HPI_CTL_ATTR(SILENCEDETECTOR, 1) | ||
439 | |||
440 | /** get/set the silence time before the detector triggers | ||
441 | */ | ||
442 | #define HPI_SILENCEDETECTOR_DELAY \ | ||
443 | HPI_CTL_ATTR(SILENCEDETECTOR, 3) | ||
444 | |||
445 | /**\}*/ | ||
446 | |||
447 | /* Locked memory buffer alloc/free phases */ | ||
448 | /** use one message to allocate or free physical memory */ | ||
449 | #define HPI_BUFFER_CMD_EXTERNAL 0 | ||
450 | /** alloc physical memory */ | ||
451 | #define HPI_BUFFER_CMD_INTERNAL_ALLOC 1 | ||
452 | /** send physical memory address to adapter */ | ||
453 | #define HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER 2 | ||
454 | /** notify adapter to stop using physical buffer */ | ||
455 | #define HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER 3 | ||
456 | /** free physical buffer */ | ||
457 | #define HPI_BUFFER_CMD_INTERNAL_FREE 4 | ||
458 | |||
459 | /******************************************* CONTROLX ATTRIBUTES ****/ | ||
460 | /* NOTE: All controlx attributes must be unique, unlike control attributes */ | ||
461 | 328 | ||
462 | /*****************************************************************************/ | 329 | /*****************************************************************************/ |
463 | /*****************************************************************************/ | 330 | /*****************************************************************************/ |
@@ -482,6 +349,12 @@ Threshold is a -ve number in units of dB/100, | |||
482 | #define HPI_USB_W2K_TAG 0x57495341 /* "ASIW" */ | 349 | #define HPI_USB_W2K_TAG 0x57495341 /* "ASIW" */ |
483 | #define HPI_USB_LINUX_TAG 0x4C495341 /* "ASIL" */ | 350 | #define HPI_USB_LINUX_TAG 0x4C495341 /* "ASIL" */ |
484 | 351 | ||
352 | /** Invalid Adapter index | ||
353 | Used in HPI messages that are not addressed to a specific adapter | ||
354 | Used in DLL to indicate device not present | ||
355 | */ | ||
356 | #define HPI_ADAPTER_INDEX_INVALID 0xFFFF | ||
357 | |||
485 | /** First 2 hex digits define the adapter family */ | 358 | /** First 2 hex digits define the adapter family */ |
486 | #define HPI_ADAPTER_FAMILY_MASK 0xff00 | 359 | #define HPI_ADAPTER_FAMILY_MASK 0xff00 |
487 | #define HPI_MODULE_FAMILY_MASK 0xfff0 | 360 | #define HPI_MODULE_FAMILY_MASK 0xfff0 |
@@ -490,178 +363,185 @@ Threshold is a -ve number in units of dB/100, | |||
490 | #define HPI_MODULE_FAMILY_ASI(f) (f & HPI_MODULE_FAMILY_MASK) | 363 | #define HPI_MODULE_FAMILY_ASI(f) (f & HPI_MODULE_FAMILY_MASK) |
491 | #define HPI_ADAPTER_ASI(f) (f) | 364 | #define HPI_ADAPTER_ASI(f) (f) |
492 | 365 | ||
493 | /******************************************* message types */ | 366 | enum HPI_MESSAGE_TYPES { |
494 | #define HPI_TYPE_MESSAGE 1 | 367 | HPI_TYPE_MESSAGE = 1, |
495 | #define HPI_TYPE_RESPONSE 2 | 368 | HPI_TYPE_RESPONSE = 2, |
496 | #define HPI_TYPE_DATA 3 | 369 | HPI_TYPE_DATA = 3, |
497 | #define HPI_TYPE_SSX2BYPASS_MESSAGE 4 | 370 | HPI_TYPE_SSX2BYPASS_MESSAGE = 4 |
498 | 371 | }; | |
499 | /******************************************* object types */ | 372 | |
500 | #define HPI_OBJ_SUBSYSTEM 1 | 373 | enum HPI_OBJECT_TYPES { |
501 | #define HPI_OBJ_ADAPTER 2 | 374 | HPI_OBJ_SUBSYSTEM = 1, |
502 | #define HPI_OBJ_OSTREAM 3 | 375 | HPI_OBJ_ADAPTER = 2, |
503 | #define HPI_OBJ_ISTREAM 4 | 376 | HPI_OBJ_OSTREAM = 3, |
504 | #define HPI_OBJ_MIXER 5 | 377 | HPI_OBJ_ISTREAM = 4, |
505 | #define HPI_OBJ_NODE 6 | 378 | HPI_OBJ_MIXER = 5, |
506 | #define HPI_OBJ_CONTROL 7 | 379 | HPI_OBJ_NODE = 6, |
507 | #define HPI_OBJ_NVMEMORY 8 | 380 | HPI_OBJ_CONTROL = 7, |
508 | #define HPI_OBJ_GPIO 9 | 381 | HPI_OBJ_NVMEMORY = 8, |
509 | #define HPI_OBJ_WATCHDOG 10 | 382 | HPI_OBJ_GPIO = 9, |
510 | #define HPI_OBJ_CLOCK 11 | 383 | HPI_OBJ_WATCHDOG = 10, |
511 | #define HPI_OBJ_PROFILE 12 | 384 | HPI_OBJ_CLOCK = 11, |
512 | #define HPI_OBJ_CONTROLEX 13 | 385 | HPI_OBJ_PROFILE = 12, |
513 | #define HPI_OBJ_ASYNCEVENT 14 | 386 | HPI_OBJ_CONTROLEX = 13, |
514 | 387 | HPI_OBJ_ASYNCEVENT = 14 | |
515 | #define HPI_OBJ_MAXINDEX 14 | 388 | #define HPI_OBJ_MAXINDEX 14 |
516 | 389 | }; | |
517 | /******************************************* methods/functions */ | 390 | |
518 | 391 | #define HPI_OBJ_FUNCTION_SPACING 0x100 | |
519 | #define HPI_OBJ_FUNCTION_SPACING 0x100 | 392 | #define HPI_FUNC_ID(obj, i) (HPI_OBJ_##obj * HPI_OBJ_FUNCTION_SPACING + i) |
520 | #define HPI_MAKE_INDEX(obj, index) (obj * HPI_OBJ_FUNCTION_SPACING + index) | 393 | |
521 | #define HPI_EXTRACT_INDEX(fn) (fn & 0xff) | 394 | #define HPI_EXTRACT_INDEX(fn) (fn & 0xff) |
522 | 395 | ||
523 | /* SUB-SYSTEM */ | 396 | enum HPI_FUNCTION_IDS { |
524 | #define HPI_SUBSYS_OPEN HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 1) | 397 | HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1), |
525 | #define HPI_SUBSYS_GET_VERSION HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 2) | 398 | HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2), |
526 | #define HPI_SUBSYS_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 3) | 399 | HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3), |
527 | #define HPI_SUBSYS_FIND_ADAPTERS HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 4) | 400 | HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), |
528 | #define HPI_SUBSYS_CREATE_ADAPTER HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 5) | 401 | HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5), |
529 | #define HPI_SUBSYS_CLOSE HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 6) | 402 | HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6), |
530 | #define HPI_SUBSYS_DELETE_ADAPTER HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 7) | 403 | HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), |
531 | #define HPI_SUBSYS_DRIVER_LOAD HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 8) | 404 | HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8), |
532 | #define HPI_SUBSYS_DRIVER_UNLOAD HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 9) | 405 | HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9), |
533 | #define HPI_SUBSYS_READ_PORT_8 HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 10) | 406 | HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), |
534 | #define HPI_SUBSYS_WRITE_PORT_8 HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 11) | 407 | HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), |
535 | #define HPI_SUBSYS_GET_NUM_ADAPTERS HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 12) | 408 | HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12), |
536 | #define HPI_SUBSYS_GET_ADAPTER HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 13) | 409 | HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13), |
537 | #define HPI_SUBSYS_SET_NETWORK_INTERFACE HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 14) | 410 | HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14), |
538 | #define HPI_SUBSYS_FUNCTION_COUNT 14 | 411 | HPI_SUBSYS_OPTION_INFO = HPI_FUNC_ID(SUBSYSTEM, 15), |
539 | /* ADAPTER */ | 412 | HPI_SUBSYS_OPTION_GET = HPI_FUNC_ID(SUBSYSTEM, 16), |
540 | #define HPI_ADAPTER_OPEN HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 1) | 413 | HPI_SUBSYS_OPTION_SET = HPI_FUNC_ID(SUBSYSTEM, 17), |
541 | #define HPI_ADAPTER_CLOSE HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 2) | 414 | #define HPI_SUBSYS_FUNCTION_COUNT 17 |
542 | #define HPI_ADAPTER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 3) | 415 | |
543 | #define HPI_ADAPTER_GET_ASSERT HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 4) | 416 | HPI_ADAPTER_OPEN = HPI_FUNC_ID(ADAPTER, 1), |
544 | #define HPI_ADAPTER_TEST_ASSERT HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 5) | 417 | HPI_ADAPTER_CLOSE = HPI_FUNC_ID(ADAPTER, 2), |
545 | #define HPI_ADAPTER_SET_MODE HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 6) | 418 | HPI_ADAPTER_GET_INFO = HPI_FUNC_ID(ADAPTER, 3), |
546 | #define HPI_ADAPTER_GET_MODE HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 7) | 419 | HPI_ADAPTER_GET_ASSERT = HPI_FUNC_ID(ADAPTER, 4), |
547 | #define HPI_ADAPTER_ENABLE_CAPABILITY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 8) | 420 | HPI_ADAPTER_TEST_ASSERT = HPI_FUNC_ID(ADAPTER, 5), |
548 | #define HPI_ADAPTER_SELFTEST HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 9) | 421 | HPI_ADAPTER_SET_MODE = HPI_FUNC_ID(ADAPTER, 6), |
549 | #define HPI_ADAPTER_FIND_OBJECT HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 10) | 422 | HPI_ADAPTER_GET_MODE = HPI_FUNC_ID(ADAPTER, 7), |
550 | #define HPI_ADAPTER_QUERY_FLASH HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 11) | 423 | HPI_ADAPTER_ENABLE_CAPABILITY = HPI_FUNC_ID(ADAPTER, 8), |
551 | #define HPI_ADAPTER_START_FLASH HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 12) | 424 | HPI_ADAPTER_SELFTEST = HPI_FUNC_ID(ADAPTER, 9), |
552 | #define HPI_ADAPTER_PROGRAM_FLASH HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 13) | 425 | HPI_ADAPTER_FIND_OBJECT = HPI_FUNC_ID(ADAPTER, 10), |
553 | #define HPI_ADAPTER_SET_PROPERTY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 14) | 426 | HPI_ADAPTER_QUERY_FLASH = HPI_FUNC_ID(ADAPTER, 11), |
554 | #define HPI_ADAPTER_GET_PROPERTY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 15) | 427 | HPI_ADAPTER_START_FLASH = HPI_FUNC_ID(ADAPTER, 12), |
555 | #define HPI_ADAPTER_ENUM_PROPERTY HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 16) | 428 | HPI_ADAPTER_PROGRAM_FLASH = HPI_FUNC_ID(ADAPTER, 13), |
556 | #define HPI_ADAPTER_MODULE_INFO HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 17) | 429 | HPI_ADAPTER_SET_PROPERTY = HPI_FUNC_ID(ADAPTER, 14), |
557 | #define HPI_ADAPTER_DEBUG_READ HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 18) | 430 | HPI_ADAPTER_GET_PROPERTY = HPI_FUNC_ID(ADAPTER, 15), |
558 | #define HPI_ADAPTER_FUNCTION_COUNT 18 | 431 | HPI_ADAPTER_ENUM_PROPERTY = HPI_FUNC_ID(ADAPTER, 16), |
559 | /* OUTPUT STREAM */ | 432 | HPI_ADAPTER_MODULE_INFO = HPI_FUNC_ID(ADAPTER, 17), |
560 | #define HPI_OSTREAM_OPEN HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 1) | 433 | HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18), |
561 | #define HPI_OSTREAM_CLOSE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 2) | 434 | HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19), |
562 | #define HPI_OSTREAM_WRITE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 3) | 435 | HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20), |
563 | #define HPI_OSTREAM_START HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 4) | 436 | #define HPI_ADAPTER_FUNCTION_COUNT 20 |
564 | #define HPI_OSTREAM_STOP HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 5) | 437 | |
565 | #define HPI_OSTREAM_RESET HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 6) | 438 | HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1), |
566 | #define HPI_OSTREAM_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 7) | 439 | HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2), |
567 | #define HPI_OSTREAM_QUERY_FORMAT HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 8) | 440 | HPI_OSTREAM_WRITE = HPI_FUNC_ID(OSTREAM, 3), |
568 | #define HPI_OSTREAM_DATA HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 9) | 441 | HPI_OSTREAM_START = HPI_FUNC_ID(OSTREAM, 4), |
569 | #define HPI_OSTREAM_SET_VELOCITY HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 10) | 442 | HPI_OSTREAM_STOP = HPI_FUNC_ID(OSTREAM, 5), |
570 | #define HPI_OSTREAM_SET_PUNCHINOUT HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 11) | 443 | HPI_OSTREAM_RESET = HPI_FUNC_ID(OSTREAM, 6), |
571 | #define HPI_OSTREAM_SINEGEN HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 12) | 444 | HPI_OSTREAM_GET_INFO = HPI_FUNC_ID(OSTREAM, 7), |
572 | #define HPI_OSTREAM_ANC_RESET HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 13) | 445 | HPI_OSTREAM_QUERY_FORMAT = HPI_FUNC_ID(OSTREAM, 8), |
573 | #define HPI_OSTREAM_ANC_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 14) | 446 | HPI_OSTREAM_DATA = HPI_FUNC_ID(OSTREAM, 9), |
574 | #define HPI_OSTREAM_ANC_READ HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 15) | 447 | HPI_OSTREAM_SET_VELOCITY = HPI_FUNC_ID(OSTREAM, 10), |
575 | #define HPI_OSTREAM_SET_TIMESCALE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 16) | 448 | HPI_OSTREAM_SET_PUNCHINOUT = HPI_FUNC_ID(OSTREAM, 11), |
576 | #define HPI_OSTREAM_SET_FORMAT HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 17) | 449 | HPI_OSTREAM_SINEGEN = HPI_FUNC_ID(OSTREAM, 12), |
577 | #define HPI_OSTREAM_HOSTBUFFER_ALLOC HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 18) | 450 | HPI_OSTREAM_ANC_RESET = HPI_FUNC_ID(OSTREAM, 13), |
578 | #define HPI_OSTREAM_HOSTBUFFER_FREE HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 19) | 451 | HPI_OSTREAM_ANC_GET_INFO = HPI_FUNC_ID(OSTREAM, 14), |
579 | #define HPI_OSTREAM_GROUP_ADD HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 20) | 452 | HPI_OSTREAM_ANC_READ = HPI_FUNC_ID(OSTREAM, 15), |
580 | #define HPI_OSTREAM_GROUP_GETMAP HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 21) | 453 | HPI_OSTREAM_SET_TIMESCALE = HPI_FUNC_ID(OSTREAM, 16), |
581 | #define HPI_OSTREAM_GROUP_RESET HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 22) | 454 | HPI_OSTREAM_SET_FORMAT = HPI_FUNC_ID(OSTREAM, 17), |
582 | #define HPI_OSTREAM_HOSTBUFFER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 23) | 455 | HPI_OSTREAM_HOSTBUFFER_ALLOC = HPI_FUNC_ID(OSTREAM, 18), |
583 | #define HPI_OSTREAM_WAIT_START HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 24) | 456 | HPI_OSTREAM_HOSTBUFFER_FREE = HPI_FUNC_ID(OSTREAM, 19), |
584 | #define HPI_OSTREAM_FUNCTION_COUNT 24 | 457 | HPI_OSTREAM_GROUP_ADD = HPI_FUNC_ID(OSTREAM, 20), |
585 | /* INPUT STREAM */ | 458 | HPI_OSTREAM_GROUP_GETMAP = HPI_FUNC_ID(OSTREAM, 21), |
586 | #define HPI_ISTREAM_OPEN HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 1) | 459 | HPI_OSTREAM_GROUP_RESET = HPI_FUNC_ID(OSTREAM, 22), |
587 | #define HPI_ISTREAM_CLOSE HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 2) | 460 | HPI_OSTREAM_HOSTBUFFER_GET_INFO = HPI_FUNC_ID(OSTREAM, 23), |
588 | #define HPI_ISTREAM_SET_FORMAT HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 3) | 461 | HPI_OSTREAM_WAIT_START = HPI_FUNC_ID(OSTREAM, 24), |
589 | #define HPI_ISTREAM_READ HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 4) | 462 | HPI_OSTREAM_WAIT = HPI_FUNC_ID(OSTREAM, 25), |
590 | #define HPI_ISTREAM_START HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 5) | 463 | #define HPI_OSTREAM_FUNCTION_COUNT 25 |
591 | #define HPI_ISTREAM_STOP HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 6) | 464 | |
592 | #define HPI_ISTREAM_RESET HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 7) | 465 | HPI_ISTREAM_OPEN = HPI_FUNC_ID(ISTREAM, 1), |
593 | #define HPI_ISTREAM_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 8) | 466 | HPI_ISTREAM_CLOSE = HPI_FUNC_ID(ISTREAM, 2), |
594 | #define HPI_ISTREAM_QUERY_FORMAT HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 9) | 467 | HPI_ISTREAM_SET_FORMAT = HPI_FUNC_ID(ISTREAM, 3), |
595 | #define HPI_ISTREAM_ANC_RESET HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 10) | 468 | HPI_ISTREAM_READ = HPI_FUNC_ID(ISTREAM, 4), |
596 | #define HPI_ISTREAM_ANC_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 11) | 469 | HPI_ISTREAM_START = HPI_FUNC_ID(ISTREAM, 5), |
597 | #define HPI_ISTREAM_ANC_WRITE HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 12) | 470 | HPI_ISTREAM_STOP = HPI_FUNC_ID(ISTREAM, 6), |
598 | #define HPI_ISTREAM_HOSTBUFFER_ALLOC HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 13) | 471 | HPI_ISTREAM_RESET = HPI_FUNC_ID(ISTREAM, 7), |
599 | #define HPI_ISTREAM_HOSTBUFFER_FREE HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 14) | 472 | HPI_ISTREAM_GET_INFO = HPI_FUNC_ID(ISTREAM, 8), |
600 | #define HPI_ISTREAM_GROUP_ADD HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 15) | 473 | HPI_ISTREAM_QUERY_FORMAT = HPI_FUNC_ID(ISTREAM, 9), |
601 | #define HPI_ISTREAM_GROUP_GETMAP HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 16) | 474 | HPI_ISTREAM_ANC_RESET = HPI_FUNC_ID(ISTREAM, 10), |
602 | #define HPI_ISTREAM_GROUP_RESET HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 17) | 475 | HPI_ISTREAM_ANC_GET_INFO = HPI_FUNC_ID(ISTREAM, 11), |
603 | #define HPI_ISTREAM_HOSTBUFFER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 18) | 476 | HPI_ISTREAM_ANC_WRITE = HPI_FUNC_ID(ISTREAM, 12), |
604 | #define HPI_ISTREAM_WAIT_START HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 19) | 477 | HPI_ISTREAM_HOSTBUFFER_ALLOC = HPI_FUNC_ID(ISTREAM, 13), |
605 | #define HPI_ISTREAM_FUNCTION_COUNT 19 | 478 | HPI_ISTREAM_HOSTBUFFER_FREE = HPI_FUNC_ID(ISTREAM, 14), |
606 | /* MIXER */ | 479 | HPI_ISTREAM_GROUP_ADD = HPI_FUNC_ID(ISTREAM, 15), |
480 | HPI_ISTREAM_GROUP_GETMAP = HPI_FUNC_ID(ISTREAM, 16), | ||
481 | HPI_ISTREAM_GROUP_RESET = HPI_FUNC_ID(ISTREAM, 17), | ||
482 | HPI_ISTREAM_HOSTBUFFER_GET_INFO = HPI_FUNC_ID(ISTREAM, 18), | ||
483 | HPI_ISTREAM_WAIT_START = HPI_FUNC_ID(ISTREAM, 19), | ||
484 | HPI_ISTREAM_WAIT = HPI_FUNC_ID(ISTREAM, 20), | ||
485 | #define HPI_ISTREAM_FUNCTION_COUNT 20 | ||
486 | |||
607 | /* NOTE: | 487 | /* NOTE: |
608 | GET_NODE_INFO, SET_CONNECTION, GET_CONNECTIONS are not currently used */ | 488 | GET_NODE_INFO, SET_CONNECTION, GET_CONNECTIONS are not currently used */ |
609 | #define HPI_MIXER_OPEN HPI_MAKE_INDEX(HPI_OBJ_MIXER, 1) | 489 | HPI_MIXER_OPEN = HPI_FUNC_ID(MIXER, 1), |
610 | #define HPI_MIXER_CLOSE HPI_MAKE_INDEX(HPI_OBJ_MIXER, 2) | 490 | HPI_MIXER_CLOSE = HPI_FUNC_ID(MIXER, 2), |
611 | #define HPI_MIXER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_MIXER, 3) | 491 | HPI_MIXER_GET_INFO = HPI_FUNC_ID(MIXER, 3), |
612 | #define HPI_MIXER_GET_NODE_INFO HPI_MAKE_INDEX(HPI_OBJ_MIXER, 4) | 492 | HPI_MIXER_GET_NODE_INFO = HPI_FUNC_ID(MIXER, 4), |
613 | #define HPI_MIXER_GET_CONTROL HPI_MAKE_INDEX(HPI_OBJ_MIXER, 5) | 493 | HPI_MIXER_GET_CONTROL = HPI_FUNC_ID(MIXER, 5), |
614 | #define HPI_MIXER_SET_CONNECTION HPI_MAKE_INDEX(HPI_OBJ_MIXER, 6) | 494 | HPI_MIXER_SET_CONNECTION = HPI_FUNC_ID(MIXER, 6), |
615 | #define HPI_MIXER_GET_CONNECTIONS HPI_MAKE_INDEX(HPI_OBJ_MIXER, 7) | 495 | HPI_MIXER_GET_CONNECTIONS = HPI_FUNC_ID(MIXER, 7), |
616 | #define HPI_MIXER_GET_CONTROL_BY_INDEX HPI_MAKE_INDEX(HPI_OBJ_MIXER, 8) | 496 | HPI_MIXER_GET_CONTROL_BY_INDEX = HPI_FUNC_ID(MIXER, 8), |
617 | #define HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX HPI_MAKE_INDEX(HPI_OBJ_MIXER, 9) | 497 | HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX = HPI_FUNC_ID(MIXER, 9), |
618 | #define HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES HPI_MAKE_INDEX(HPI_OBJ_MIXER, 10) | 498 | HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES = HPI_FUNC_ID(MIXER, 10), |
619 | #define HPI_MIXER_STORE HPI_MAKE_INDEX(HPI_OBJ_MIXER, 11) | 499 | HPI_MIXER_STORE = HPI_FUNC_ID(MIXER, 11), |
620 | #define HPI_MIXER_FUNCTION_COUNT 11 | 500 | HPI_MIXER_GET_CACHE_INFO = HPI_FUNC_ID(MIXER, 12), |
621 | /* MIXER CONTROLS */ | 501 | #define HPI_MIXER_FUNCTION_COUNT 12 |
622 | #define HPI_CONTROL_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 1) | 502 | |
623 | #define HPI_CONTROL_GET_STATE HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 2) | 503 | HPI_CONTROL_GET_INFO = HPI_FUNC_ID(CONTROL, 1), |
624 | #define HPI_CONTROL_SET_STATE HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 3) | 504 | HPI_CONTROL_GET_STATE = HPI_FUNC_ID(CONTROL, 2), |
505 | HPI_CONTROL_SET_STATE = HPI_FUNC_ID(CONTROL, 3), | ||
625 | #define HPI_CONTROL_FUNCTION_COUNT 3 | 506 | #define HPI_CONTROL_FUNCTION_COUNT 3 |
626 | /* NONVOL MEMORY */ | 507 | |
627 | #define HPI_NVMEMORY_OPEN HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 1) | 508 | HPI_NVMEMORY_OPEN = HPI_FUNC_ID(NVMEMORY, 1), |
628 | #define HPI_NVMEMORY_READ_BYTE HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 2) | 509 | HPI_NVMEMORY_READ_BYTE = HPI_FUNC_ID(NVMEMORY, 2), |
629 | #define HPI_NVMEMORY_WRITE_BYTE HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 3) | 510 | HPI_NVMEMORY_WRITE_BYTE = HPI_FUNC_ID(NVMEMORY, 3), |
630 | #define HPI_NVMEMORY_FUNCTION_COUNT 3 | 511 | #define HPI_NVMEMORY_FUNCTION_COUNT 3 |
631 | /* GPIO */ | 512 | |
632 | #define HPI_GPIO_OPEN HPI_MAKE_INDEX(HPI_OBJ_GPIO, 1) | 513 | HPI_GPIO_OPEN = HPI_FUNC_ID(GPIO, 1), |
633 | #define HPI_GPIO_READ_BIT HPI_MAKE_INDEX(HPI_OBJ_GPIO, 2) | 514 | HPI_GPIO_READ_BIT = HPI_FUNC_ID(GPIO, 2), |
634 | #define HPI_GPIO_WRITE_BIT HPI_MAKE_INDEX(HPI_OBJ_GPIO, 3) | 515 | HPI_GPIO_WRITE_BIT = HPI_FUNC_ID(GPIO, 3), |
635 | #define HPI_GPIO_READ_ALL HPI_MAKE_INDEX(HPI_OBJ_GPIO, 4) | 516 | HPI_GPIO_READ_ALL = HPI_FUNC_ID(GPIO, 4), |
636 | #define HPI_GPIO_WRITE_STATUS HPI_MAKE_INDEX(HPI_OBJ_GPIO, 5) | 517 | HPI_GPIO_WRITE_STATUS = HPI_FUNC_ID(GPIO, 5), |
637 | #define HPI_GPIO_FUNCTION_COUNT 5 | 518 | #define HPI_GPIO_FUNCTION_COUNT 5 |
638 | /* ASYNC EVENT */ | 519 | |
639 | #define HPI_ASYNCEVENT_OPEN HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 1) | 520 | HPI_ASYNCEVENT_OPEN = HPI_FUNC_ID(ASYNCEVENT, 1), |
640 | #define HPI_ASYNCEVENT_CLOSE HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 2) | 521 | HPI_ASYNCEVENT_CLOSE = HPI_FUNC_ID(ASYNCEVENT, 2), |
641 | #define HPI_ASYNCEVENT_WAIT HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 3) | 522 | HPI_ASYNCEVENT_WAIT = HPI_FUNC_ID(ASYNCEVENT, 3), |
642 | #define HPI_ASYNCEVENT_GETCOUNT HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 4) | 523 | HPI_ASYNCEVENT_GETCOUNT = HPI_FUNC_ID(ASYNCEVENT, 4), |
643 | #define HPI_ASYNCEVENT_GET HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 5) | 524 | HPI_ASYNCEVENT_GET = HPI_FUNC_ID(ASYNCEVENT, 5), |
644 | #define HPI_ASYNCEVENT_SENDEVENTS HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 6) | 525 | HPI_ASYNCEVENT_SENDEVENTS = HPI_FUNC_ID(ASYNCEVENT, 6), |
645 | #define HPI_ASYNCEVENT_FUNCTION_COUNT 6 | 526 | #define HPI_ASYNCEVENT_FUNCTION_COUNT 6 |
646 | /* WATCH-DOG */ | 527 | |
647 | #define HPI_WATCHDOG_OPEN HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 1) | 528 | HPI_WATCHDOG_OPEN = HPI_FUNC_ID(WATCHDOG, 1), |
648 | #define HPI_WATCHDOG_SET_TIME HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 2) | 529 | HPI_WATCHDOG_SET_TIME = HPI_FUNC_ID(WATCHDOG, 2), |
649 | #define HPI_WATCHDOG_PING HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 3) | 530 | HPI_WATCHDOG_PING = HPI_FUNC_ID(WATCHDOG, 3), |
650 | /* CLOCK */ | 531 | |
651 | #define HPI_CLOCK_OPEN HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 1) | 532 | HPI_CLOCK_OPEN = HPI_FUNC_ID(CLOCK, 1), |
652 | #define HPI_CLOCK_SET_TIME HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 2) | 533 | HPI_CLOCK_SET_TIME = HPI_FUNC_ID(CLOCK, 2), |
653 | #define HPI_CLOCK_GET_TIME HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 3) | 534 | HPI_CLOCK_GET_TIME = HPI_FUNC_ID(CLOCK, 3), |
654 | /* PROFILE */ | 535 | |
655 | #define HPI_PROFILE_OPEN_ALL HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 1) | 536 | HPI_PROFILE_OPEN_ALL = HPI_FUNC_ID(PROFILE, 1), |
656 | #define HPI_PROFILE_START_ALL HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 2) | 537 | HPI_PROFILE_START_ALL = HPI_FUNC_ID(PROFILE, 2), |
657 | #define HPI_PROFILE_STOP_ALL HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 3) | 538 | HPI_PROFILE_STOP_ALL = HPI_FUNC_ID(PROFILE, 3), |
658 | #define HPI_PROFILE_GET HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 4) | 539 | HPI_PROFILE_GET = HPI_FUNC_ID(PROFILE, 4), |
659 | #define HPI_PROFILE_GET_IDLECOUNT HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 5) | 540 | HPI_PROFILE_GET_IDLECOUNT = HPI_FUNC_ID(PROFILE, 5), |
660 | #define HPI_PROFILE_GET_NAME HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 6) | 541 | HPI_PROFILE_GET_NAME = HPI_FUNC_ID(PROFILE, 6), |
661 | #define HPI_PROFILE_GET_UTILIZATION HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 7) | 542 | HPI_PROFILE_GET_UTILIZATION = HPI_FUNC_ID(PROFILE, 7) |
662 | #define HPI_PROFILE_FUNCTION_COUNT 7 | 543 | #define HPI_PROFILE_FUNCTION_COUNT 7 |
663 | /* ////////////////////////////////////////////////////////////////////// */ | 544 | }; |
664 | /* PRIVATE ATTRIBUTES */ | ||
665 | 545 | ||
666 | /* ////////////////////////////////////////////////////////////////////// */ | 546 | /* ////////////////////////////////////////////////////////////////////// */ |
667 | /* STRUCTURES */ | 547 | /* STRUCTURES */ |
@@ -672,18 +552,7 @@ Threshold is a -ve number in units of dB/100, | |||
672 | /** PCI bus resource */ | 552 | /** PCI bus resource */ |
673 | struct hpi_pci { | 553 | struct hpi_pci { |
674 | u32 __iomem *ap_mem_base[HPI_MAX_ADAPTER_MEM_SPACES]; | 554 | u32 __iomem *ap_mem_base[HPI_MAX_ADAPTER_MEM_SPACES]; |
675 | struct pci_dev *p_os_data; | 555 | struct pci_dev *pci_dev; |
676 | |||
677 | #ifndef HPI64BIT /* keep structure size constant */ | ||
678 | u32 padding[HPI_MAX_ADAPTER_MEM_SPACES + 1]; | ||
679 | #endif | ||
680 | u16 vendor_id; | ||
681 | u16 device_id; | ||
682 | u16 subsys_vendor_id; | ||
683 | u16 subsys_device_id; | ||
684 | u16 bus_number; | ||
685 | u16 device_number; | ||
686 | u32 interrupt; | ||
687 | }; | 556 | }; |
688 | 557 | ||
689 | struct hpi_resource { | 558 | struct hpi_resource { |
@@ -702,12 +571,10 @@ struct hpi_resource { | |||
702 | /** Format info used inside struct hpi_message | 571 | /** Format info used inside struct hpi_message |
703 | Not the same as public API struct hpi_format */ | 572 | Not the same as public API struct hpi_format */ |
704 | struct hpi_msg_format { | 573 | struct hpi_msg_format { |
705 | u32 sample_rate; | 574 | u32 sample_rate; /**< 11025, 32000, 44100 etc. */ |
706 | /**< 11025, 32000, 44100 ... */ | 575 | u32 bit_rate; /**< for MPEG */ |
707 | u32 bit_rate; /**< for MPEG */ | 576 | u32 attributes; /**< stereo/joint_stereo/mono */ |
708 | u32 attributes; | 577 | u16 channels; /**< 1,2..., (or ancillary mode or idle bit */ |
709 | /**< Stereo/JointStereo/Mono */ | ||
710 | u16 channels; /**< 1,2..., (or ancillary mode or idle bit */ | ||
711 | u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see \ref HPI_FORMATS. */ | 578 | u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see \ref HPI_FORMATS. */ |
712 | }; | 579 | }; |
713 | 580 | ||
@@ -742,7 +609,7 @@ struct hpi_data_compat32 { | |||
742 | struct hpi_buffer { | 609 | struct hpi_buffer { |
743 | /** placehoder for backward compatability (see dwBufferSize) */ | 610 | /** placehoder for backward compatability (see dwBufferSize) */ |
744 | struct hpi_msg_format reserved; | 611 | struct hpi_msg_format reserved; |
745 | u32 command; /**< HPI_BUFFER_CMD_xxx*/ | 612 | u32 command; /**< HPI_BUFFER_CMD_xxx*/ |
746 | u32 pci_address; /**< PCI physical address of buffer for DSP DMA */ | 613 | u32 pci_address; /**< PCI physical address of buffer for DSP DMA */ |
747 | u32 buffer_size; /**< must line up with data_size of HPI_DATA*/ | 614 | u32 buffer_size; /**< must line up with data_size of HPI_DATA*/ |
748 | }; | 615 | }; |
@@ -777,30 +644,25 @@ struct hpi_subsys_msg { | |||
777 | 644 | ||
778 | struct hpi_subsys_res { | 645 | struct hpi_subsys_res { |
779 | u32 version; | 646 | u32 version; |
780 | u32 data; /* used to return extended version */ | 647 | u32 data; /* extended version */ |
781 | u16 num_adapters; /* number of adapters */ | 648 | u16 num_adapters; |
782 | u16 adapter_index; | 649 | u16 adapter_index; |
783 | u16 aw_adapter_list[HPI_MAX_ADAPTERS]; | 650 | u16 adapter_type; |
784 | }; | 651 | u16 pad16; |
785 | |||
786 | struct hpi_adapter_msg { | ||
787 | u32 adapter_mode; /* adapter mode */ | ||
788 | u16 assert_id; /* assert number for "test assert" call | ||
789 | object_index for find object call | ||
790 | query_or_set for hpi_adapter_set_mode_ex() */ | ||
791 | u16 object_type; /* for adapter find object call */ | ||
792 | }; | 652 | }; |
793 | 653 | ||
794 | union hpi_adapterx_msg { | 654 | union hpi_adapterx_msg { |
795 | struct hpi_adapter_msg adapter; | ||
796 | struct { | 655 | struct { |
797 | u32 offset; | 656 | u32 dsp_address; |
798 | } query_flash; | 657 | u32 count_bytes; |
658 | } debug_read; | ||
799 | struct { | 659 | struct { |
800 | u32 offset; | 660 | u32 adapter_mode; |
801 | u32 length; | 661 | u16 query_or_set; |
802 | u32 key; | 662 | } mode; |
803 | } start_flash; | 663 | struct { |
664 | u16 index; | ||
665 | } module_info; | ||
804 | struct { | 666 | struct { |
805 | u32 checksum; | 667 | u32 checksum; |
806 | u16 sequence; | 668 | u16 sequence; |
@@ -809,28 +671,41 @@ union hpi_adapterx_msg { | |||
809 | u16 unused; | 671 | u16 unused; |
810 | } program_flash; | 672 | } program_flash; |
811 | struct { | 673 | struct { |
674 | u16 index; | ||
675 | u16 what; | ||
676 | u16 property_index; | ||
677 | } property_enum; | ||
678 | struct { | ||
812 | u16 property; | 679 | u16 property; |
813 | u16 parameter1; | 680 | u16 parameter1; |
814 | u16 parameter2; | 681 | u16 parameter2; |
815 | } property_set; | 682 | } property_set; |
816 | struct { | 683 | struct { |
817 | u16 index; | 684 | u32 offset; |
818 | u16 what; | 685 | } query_flash; |
819 | u16 property_index; | ||
820 | } property_enum; | ||
821 | struct { | 686 | struct { |
822 | u16 index; | 687 | u32 pad32; |
823 | } module_info; | 688 | u16 key1; |
689 | u16 key2; | ||
690 | } restart; | ||
824 | struct { | 691 | struct { |
825 | u32 dsp_address; | 692 | u32 offset; |
826 | u32 count_bytes; | 693 | u32 length; |
827 | } debug_read; | 694 | u32 key; |
695 | } start_flash; | ||
696 | struct { | ||
697 | u32 pad32; | ||
698 | u16 value; | ||
699 | } test_assert; | ||
700 | struct { | ||
701 | u32 yes; | ||
702 | } irq_query; | ||
828 | }; | 703 | }; |
829 | 704 | ||
830 | struct hpi_adapter_res { | 705 | struct hpi_adapter_res { |
831 | u32 serial_number; | 706 | u32 serial_number; |
832 | u16 adapter_type; | 707 | u16 adapter_type; |
833 | u16 adapter_index; /* is this needed? also used for dsp_index */ | 708 | u16 adapter_index; |
834 | u16 num_instreams; | 709 | u16 num_instreams; |
835 | u16 num_outstreams; | 710 | u16 num_outstreams; |
836 | u16 num_mixers; | 711 | u16 num_mixers; |
@@ -839,12 +714,18 @@ struct hpi_adapter_res { | |||
839 | }; | 714 | }; |
840 | 715 | ||
841 | union hpi_adapterx_res { | 716 | union hpi_adapterx_res { |
842 | struct hpi_adapter_res adapter; | 717 | struct hpi_adapter_res info; |
843 | struct { | 718 | struct { |
844 | u32 checksum; | 719 | u32 p1; |
845 | u32 length; | 720 | u16 count; |
846 | u32 version; | 721 | u16 dsp_index; |
847 | } query_flash; | 722 | u32 p2; |
723 | u32 dsp_msg_addr; | ||
724 | char sz_message[HPI_STRING_LEN]; | ||
725 | } assert; | ||
726 | struct { | ||
727 | u32 adapter_mode; | ||
728 | } mode; | ||
848 | struct { | 729 | struct { |
849 | u16 sequence; | 730 | u16 sequence; |
850 | } program_flash; | 731 | } program_flash; |
@@ -852,6 +733,14 @@ union hpi_adapterx_res { | |||
852 | u16 parameter1; | 733 | u16 parameter1; |
853 | u16 parameter2; | 734 | u16 parameter2; |
854 | } property_get; | 735 | } property_get; |
736 | struct { | ||
737 | u32 checksum; | ||
738 | u32 length; | ||
739 | u32 version; | ||
740 | } query_flash; | ||
741 | struct { | ||
742 | u32 yes; | ||
743 | } irq_query; | ||
855 | }; | 744 | }; |
856 | 745 | ||
857 | struct hpi_stream_msg { | 746 | struct hpi_stream_msg { |
@@ -863,6 +752,7 @@ struct hpi_stream_msg { | |||
863 | u32 time_scale; | 752 | u32 time_scale; |
864 | struct hpi_buffer buffer; | 753 | struct hpi_buffer buffer; |
865 | struct hpi_streamid stream; | 754 | struct hpi_streamid stream; |
755 | u32 threshold_bytes; | ||
866 | } u; | 756 | } u; |
867 | }; | 757 | }; |
868 | 758 | ||
@@ -911,7 +801,7 @@ struct hpi_stream_res { | |||
911 | struct hpi_mixer_msg { | 801 | struct hpi_mixer_msg { |
912 | u16 control_index; | 802 | u16 control_index; |
913 | u16 control_type; /* = HPI_CONTROL_METER _VOLUME etc */ | 803 | u16 control_type; /* = HPI_CONTROL_METER _VOLUME etc */ |
914 | u16 padding1; /* maintain alignment of subsequent fields */ | 804 | u16 padding1; /* Maintain alignment of subsequent fields */ |
915 | u16 node_type1; /* = HPI_SOURCENODE_LINEIN etc */ | 805 | u16 node_type1; /* = HPI_SOURCENODE_LINEIN etc */ |
916 | u16 node_index1; /* = 0..N */ | 806 | u16 node_index1; /* = 0..N */ |
917 | u16 node_type2; | 807 | u16 node_type2; |
@@ -949,6 +839,11 @@ union hpi_mixerx_res { | |||
949 | u32 p_data; /* pointer to data array */ | 839 | u32 p_data; /* pointer to data array */ |
950 | u16 more_to_do; /* indicates if there is more to do */ | 840 | u16 more_to_do; /* indicates if there is more to do */ |
951 | } gcabi; | 841 | } gcabi; |
842 | struct { | ||
843 | u32 total_controls; /* count of controls in the mixer */ | ||
844 | u32 cache_controls; /* count of controls in the cac */ | ||
845 | u32 cache_bytes; /* size of cache */ | ||
846 | } cache_info; | ||
952 | }; | 847 | }; |
953 | 848 | ||
954 | struct hpi_control_msg { | 849 | struct hpi_control_msg { |
@@ -1000,12 +895,16 @@ union hpi_control_union_res { | |||
1000 | u32 band; | 895 | u32 band; |
1001 | u32 frequency; | 896 | u32 frequency; |
1002 | u32 gain; | 897 | u32 gain; |
1003 | u32 level; | ||
1004 | u32 deemphasis; | 898 | u32 deemphasis; |
1005 | struct { | 899 | struct { |
1006 | u32 data[2]; | 900 | u32 data[2]; |
1007 | u32 bLER; | 901 | u32 bLER; |
1008 | } rds; | 902 | } rds; |
903 | short s_level; | ||
904 | struct { | ||
905 | u16 value; | ||
906 | u16 mask; | ||
907 | } status; | ||
1009 | } tuner; | 908 | } tuner; |
1010 | struct { | 909 | struct { |
1011 | char sz_data[8]; | 910 | char sz_data[8]; |
@@ -1178,11 +1077,11 @@ struct hpi_profile_res_open { | |||
1178 | }; | 1077 | }; |
1179 | 1078 | ||
1180 | struct hpi_profile_res_time { | 1079 | struct hpi_profile_res_time { |
1181 | u32 micro_seconds; | 1080 | u32 total_tick_count; |
1182 | u32 call_count; | 1081 | u32 call_count; |
1183 | u32 max_micro_seconds; | 1082 | u32 max_tick_count; |
1184 | u32 min_micro_seconds; | 1083 | u32 ticks_per_millisecond; |
1185 | u16 seconds; | 1084 | u16 profile_interval; |
1186 | }; | 1085 | }; |
1187 | 1086 | ||
1188 | struct hpi_profile_res_name { | 1087 | struct hpi_profile_res_name { |
@@ -1218,7 +1117,6 @@ struct hpi_message { | |||
1218 | u16 obj_index; /* */ | 1117 | u16 obj_index; /* */ |
1219 | union { | 1118 | union { |
1220 | struct hpi_subsys_msg s; | 1119 | struct hpi_subsys_msg s; |
1221 | struct hpi_adapter_msg a; | ||
1222 | union hpi_adapterx_msg ax; | 1120 | union hpi_adapterx_msg ax; |
1223 | struct hpi_stream_msg d; | 1121 | struct hpi_stream_msg d; |
1224 | struct hpi_mixer_msg m; | 1122 | struct hpi_mixer_msg m; |
@@ -1239,7 +1137,7 @@ struct hpi_message { | |||
1239 | }; | 1137 | }; |
1240 | 1138 | ||
1241 | #define HPI_MESSAGE_SIZE_BY_OBJECT { \ | 1139 | #define HPI_MESSAGE_SIZE_BY_OBJECT { \ |
1242 | sizeof(struct hpi_message_header) , /* default, no object type 0 */ \ | 1140 | sizeof(struct hpi_message_header) , /* Default, no object type 0 */ \ |
1243 | sizeof(struct hpi_message_header) + sizeof(struct hpi_subsys_msg),\ | 1141 | sizeof(struct hpi_message_header) + sizeof(struct hpi_subsys_msg),\ |
1244 | sizeof(struct hpi_message_header) + sizeof(union hpi_adapterx_msg),\ | 1142 | sizeof(struct hpi_message_header) + sizeof(union hpi_adapterx_msg),\ |
1245 | sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\ | 1143 | sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\ |
@@ -1256,6 +1154,11 @@ struct hpi_message { | |||
1256 | sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \ | 1154 | sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \ |
1257 | } | 1155 | } |
1258 | 1156 | ||
1157 | /* | ||
1158 | Note that the wSpecificError error field should be inspected and potentially | ||
1159 | reported whenever HPI_ERROR_DSP_COMMUNICATION or HPI_ERROR_DSP_BOOTLOAD is | ||
1160 | returned in wError. | ||
1161 | */ | ||
1259 | struct hpi_response_header { | 1162 | struct hpi_response_header { |
1260 | u16 size; | 1163 | u16 size; |
1261 | u8 type; /* HPI_TYPE_RESPONSE */ | 1164 | u8 type; /* HPI_TYPE_RESPONSE */ |
@@ -1277,7 +1180,6 @@ struct hpi_response { | |||
1277 | u16 specific_error; /* adapter specific error */ | 1180 | u16 specific_error; /* adapter specific error */ |
1278 | union { | 1181 | union { |
1279 | struct hpi_subsys_res s; | 1182 | struct hpi_subsys_res s; |
1280 | struct hpi_adapter_res a; | ||
1281 | union hpi_adapterx_res ax; | 1183 | union hpi_adapterx_res ax; |
1282 | struct hpi_stream_res d; | 1184 | struct hpi_stream_res d; |
1283 | struct hpi_mixer_res m; | 1185 | struct hpi_mixer_res m; |
@@ -1297,7 +1199,7 @@ struct hpi_response { | |||
1297 | }; | 1199 | }; |
1298 | 1200 | ||
1299 | #define HPI_RESPONSE_SIZE_BY_OBJECT { \ | 1201 | #define HPI_RESPONSE_SIZE_BY_OBJECT { \ |
1300 | sizeof(struct hpi_response_header) ,/* default, no object type 0 */ \ | 1202 | sizeof(struct hpi_response_header) ,/* Default, no object type 0 */ \ |
1301 | sizeof(struct hpi_response_header) + sizeof(struct hpi_subsys_res),\ | 1203 | sizeof(struct hpi_response_header) + sizeof(struct hpi_subsys_res),\ |
1302 | sizeof(struct hpi_response_header) + sizeof(union hpi_adapterx_res),\ | 1204 | sizeof(struct hpi_response_header) + sizeof(union hpi_adapterx_res),\ |
1303 | sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\ | 1205 | sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\ |
@@ -1314,7 +1216,7 @@ struct hpi_response { | |||
1314 | sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \ | 1216 | sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \ |
1315 | } | 1217 | } |
1316 | 1218 | ||
1317 | /*********************** version 1 message/response *****************************/ | 1219 | /*********************** version 1 message/response **************************/ |
1318 | #define HPINET_ETHERNET_DATA_SIZE (1500) | 1220 | #define HPINET_ETHERNET_DATA_SIZE (1500) |
1319 | #define HPINET_IP_HDR_SIZE (20) | 1221 | #define HPINET_IP_HDR_SIZE (20) |
1320 | #define HPINET_IP_DATA_SIZE (HPINET_ETHERNET_DATA_SIZE - HPINET_IP_HDR_SIZE) | 1222 | #define HPINET_IP_DATA_SIZE (HPINET_ETHERNET_DATA_SIZE - HPINET_IP_HDR_SIZE) |
@@ -1394,6 +1296,17 @@ struct hpi_res_adapter_program_flash { | |||
1394 | sizeof(struct hpi_response_header) - sizeof(u16)]; | 1296 | sizeof(struct hpi_response_header) - sizeof(u16)]; |
1395 | }; | 1297 | }; |
1396 | 1298 | ||
1299 | struct hpi_msg_adapter_debug_read { | ||
1300 | struct hpi_message_header h; | ||
1301 | u32 dsp_address; | ||
1302 | u32 count_bytes; | ||
1303 | }; | ||
1304 | |||
1305 | struct hpi_res_adapter_debug_read { | ||
1306 | struct hpi_response_header h; | ||
1307 | u8 bytes[256]; | ||
1308 | }; | ||
1309 | |||
1397 | #if 1 | 1310 | #if 1 |
1398 | #define hpi_message_header_v1 hpi_message_header | 1311 | #define hpi_message_header_v1 hpi_message_header |
1399 | #define hpi_response_header_v1 hpi_response_header | 1312 | #define hpi_response_header_v1 hpi_response_header |
@@ -1414,23 +1327,10 @@ struct hpi_response_header_v1 { | |||
1414 | }; | 1327 | }; |
1415 | #endif | 1328 | #endif |
1416 | 1329 | ||
1417 | /* STRV HPI Packet */ | ||
1418 | struct hpi_msg_strv { | ||
1419 | struct hpi_message_header h; | ||
1420 | struct hpi_entity strv; | ||
1421 | }; | ||
1422 | |||
1423 | struct hpi_res_strv { | ||
1424 | struct hpi_response_header h; | ||
1425 | struct hpi_entity strv; | ||
1426 | }; | ||
1427 | #define MIN_STRV_PACKET_SIZE sizeof(struct hpi_res_strv) | ||
1428 | |||
1429 | struct hpi_msg_payload_v0 { | 1330 | struct hpi_msg_payload_v0 { |
1430 | struct hpi_message_header h; | 1331 | struct hpi_message_header h; |
1431 | union { | 1332 | union { |
1432 | struct hpi_subsys_msg s; | 1333 | struct hpi_subsys_msg s; |
1433 | struct hpi_adapter_msg a; | ||
1434 | union hpi_adapterx_msg ax; | 1334 | union hpi_adapterx_msg ax; |
1435 | struct hpi_stream_msg d; | 1335 | struct hpi_stream_msg d; |
1436 | struct hpi_mixer_msg m; | 1336 | struct hpi_mixer_msg m; |
@@ -1451,7 +1351,6 @@ struct hpi_res_payload_v0 { | |||
1451 | struct hpi_response_header h; | 1351 | struct hpi_response_header h; |
1452 | union { | 1352 | union { |
1453 | struct hpi_subsys_res s; | 1353 | struct hpi_subsys_res s; |
1454 | struct hpi_adapter_res a; | ||
1455 | union hpi_adapterx_res ax; | 1354 | union hpi_adapterx_res ax; |
1456 | struct hpi_stream_res d; | 1355 | struct hpi_stream_res d; |
1457 | struct hpi_mixer_res m; | 1356 | struct hpi_mixer_res m; |
@@ -1471,13 +1370,13 @@ struct hpi_res_payload_v0 { | |||
1471 | union hpi_message_buffer_v1 { | 1370 | union hpi_message_buffer_v1 { |
1472 | struct hpi_message m0; /* version 0 */ | 1371 | struct hpi_message m0; /* version 0 */ |
1473 | struct hpi_message_header_v1 h; | 1372 | struct hpi_message_header_v1 h; |
1474 | unsigned char buf[HPI_MAX_PAYLOAD_SIZE]; | 1373 | u8 buf[HPI_MAX_PAYLOAD_SIZE]; |
1475 | }; | 1374 | }; |
1476 | 1375 | ||
1477 | union hpi_response_buffer_v1 { | 1376 | union hpi_response_buffer_v1 { |
1478 | struct hpi_response r0; /* version 0 */ | 1377 | struct hpi_response r0; /* version 0 */ |
1479 | struct hpi_response_header_v1 h; | 1378 | struct hpi_response_header_v1 h; |
1480 | unsigned char buf[HPI_MAX_PAYLOAD_SIZE]; | 1379 | u8 buf[HPI_MAX_PAYLOAD_SIZE]; |
1481 | }; | 1380 | }; |
1482 | 1381 | ||
1483 | compile_time_assert((sizeof(union hpi_message_buffer_v1) <= | 1382 | compile_time_assert((sizeof(union hpi_message_buffer_v1) <= |
@@ -1499,6 +1398,11 @@ struct hpi_control_defn { | |||
1499 | /*////////////////////////////////////////////////////////////////////////// */ | 1398 | /*////////////////////////////////////////////////////////////////////////// */ |
1500 | /* declarations for control caching (internal to HPI<->DSP interaction) */ | 1399 | /* declarations for control caching (internal to HPI<->DSP interaction) */ |
1501 | 1400 | ||
1401 | /** indicates a cached u16 value is invalid. */ | ||
1402 | #define HPI_CACHE_INVALID_UINT16 0xFFFF | ||
1403 | /** indicates a cached short value is invalid. */ | ||
1404 | #define HPI_CACHE_INVALID_SHORT -32768 | ||
1405 | |||
1502 | /** A compact representation of (part of) a controls state. | 1406 | /** A compact representation of (part of) a controls state. |
1503 | Used for efficient transfer of the control state | 1407 | Used for efficient transfer of the control state |
1504 | between DSP and host or across a network | 1408 | between DSP and host or across a network |
@@ -1512,58 +1416,104 @@ struct hpi_control_cache_info { | |||
1512 | u16 control_index; | 1416 | u16 control_index; |
1513 | }; | 1417 | }; |
1514 | 1418 | ||
1515 | struct hpi_control_cache_single { | 1419 | struct hpi_control_cache_vol { |
1420 | struct hpi_control_cache_info i; | ||
1421 | short an_log[2]; | ||
1422 | unsigned short flags; | ||
1423 | char padding[2]; | ||
1424 | }; | ||
1425 | |||
1426 | struct hpi_control_cache_meter { | ||
1427 | struct hpi_control_cache_info i; | ||
1428 | short an_log_peak[2]; | ||
1429 | short an_logRMS[2]; | ||
1430 | }; | ||
1431 | |||
1432 | struct hpi_control_cache_channelmode { | ||
1433 | struct hpi_control_cache_info i; | ||
1434 | u16 mode; | ||
1435 | char temp_padding[6]; | ||
1436 | }; | ||
1437 | |||
1438 | struct hpi_control_cache_mux { | ||
1439 | struct hpi_control_cache_info i; | ||
1440 | u16 source_node_type; | ||
1441 | u16 source_node_index; | ||
1442 | char temp_padding[4]; | ||
1443 | }; | ||
1444 | |||
1445 | struct hpi_control_cache_level { | ||
1516 | struct hpi_control_cache_info i; | 1446 | struct hpi_control_cache_info i; |
1447 | short an_log[2]; | ||
1448 | char temp_padding[4]; | ||
1449 | }; | ||
1450 | |||
1451 | struct hpi_control_cache_tuner { | ||
1452 | struct hpi_control_cache_info i; | ||
1453 | u32 freq_ink_hz; | ||
1454 | u16 band; | ||
1455 | short s_level_avg; | ||
1456 | }; | ||
1457 | |||
1458 | struct hpi_control_cache_aes3rx { | ||
1459 | struct hpi_control_cache_info i; | ||
1460 | u32 error_status; | ||
1461 | u32 format; | ||
1462 | }; | ||
1463 | |||
1464 | struct hpi_control_cache_aes3tx { | ||
1465 | struct hpi_control_cache_info i; | ||
1466 | u32 format; | ||
1467 | char temp_padding[4]; | ||
1468 | }; | ||
1469 | |||
1470 | struct hpi_control_cache_tonedetector { | ||
1471 | struct hpi_control_cache_info i; | ||
1472 | u16 state; | ||
1473 | char temp_padding[6]; | ||
1474 | }; | ||
1475 | |||
1476 | struct hpi_control_cache_silencedetector { | ||
1477 | struct hpi_control_cache_info i; | ||
1478 | u32 state; | ||
1479 | char temp_padding[4]; | ||
1480 | }; | ||
1481 | |||
1482 | struct hpi_control_cache_sampleclock { | ||
1483 | struct hpi_control_cache_info i; | ||
1484 | u16 source; | ||
1485 | u16 source_index; | ||
1486 | u32 sample_rate; | ||
1487 | }; | ||
1488 | |||
1489 | struct hpi_control_cache_microphone { | ||
1490 | struct hpi_control_cache_info i; | ||
1491 | u16 phantom_state; | ||
1492 | char temp_padding[6]; | ||
1493 | }; | ||
1494 | |||
1495 | struct hpi_control_cache_generic { | ||
1496 | struct hpi_control_cache_info i; | ||
1497 | u32 dw1; | ||
1498 | u32 dw2; | ||
1499 | }; | ||
1500 | |||
1501 | struct hpi_control_cache_single { | ||
1517 | union { | 1502 | union { |
1518 | struct { /* volume */ | 1503 | struct hpi_control_cache_info i; |
1519 | short an_log[2]; | 1504 | struct hpi_control_cache_vol vol; |
1520 | } v; | 1505 | struct hpi_control_cache_meter meter; |
1521 | struct { /* peak meter */ | 1506 | struct hpi_control_cache_channelmode mode; |
1522 | short an_log_peak[2]; | 1507 | struct hpi_control_cache_mux mux; |
1523 | short an_logRMS[2]; | 1508 | struct hpi_control_cache_level level; |
1524 | } p; | 1509 | struct hpi_control_cache_tuner tuner; |
1525 | struct { /* channel mode */ | 1510 | struct hpi_control_cache_aes3rx aes3rx; |
1526 | u16 mode; | 1511 | struct hpi_control_cache_aes3tx aes3tx; |
1527 | } m; | 1512 | struct hpi_control_cache_tonedetector tone; |
1528 | struct { /* multiplexer */ | 1513 | struct hpi_control_cache_silencedetector silence; |
1529 | u16 source_node_type; | 1514 | struct hpi_control_cache_sampleclock clk; |
1530 | u16 source_node_index; | 1515 | struct hpi_control_cache_microphone microphone; |
1531 | } x; | 1516 | struct hpi_control_cache_generic generic; |
1532 | struct { /* level/trim */ | ||
1533 | short an_log[2]; | ||
1534 | } l; | ||
1535 | struct { /* tuner - partial caching. | ||
1536 | some attributes go to the DSP. */ | ||
1537 | u32 freq_ink_hz; | ||
1538 | u16 band; | ||
1539 | u16 level; | ||
1540 | } t; | ||
1541 | struct { /* AESEBU rx status */ | ||
1542 | u32 error_status; | ||
1543 | u32 source; | ||
1544 | } aes3rx; | ||
1545 | struct { /* AESEBU tx */ | ||
1546 | u32 format; | ||
1547 | } aes3tx; | ||
1548 | struct { /* tone detector */ | ||
1549 | u16 state; | ||
1550 | } tone; | ||
1551 | struct { /* silence detector */ | ||
1552 | u32 state; | ||
1553 | u32 count; | ||
1554 | } silence; | ||
1555 | struct { /* sample clock */ | ||
1556 | u16 source; | ||
1557 | u16 source_index; | ||
1558 | u32 sample_rate; | ||
1559 | } clk; | ||
1560 | struct { /* microphone control */ | ||
1561 | u16 state; | ||
1562 | } phantom_power; | ||
1563 | struct { /* generic control */ | ||
1564 | u32 dw1; | ||
1565 | u32 dw2; | ||
1566 | } g; | ||
1567 | } u; | 1517 | } u; |
1568 | }; | 1518 | }; |
1569 | 1519 | ||
@@ -1580,8 +1530,7 @@ struct hpi_control_cache_pad { | |||
1580 | u32 traffic_anouncement; | 1530 | u32 traffic_anouncement; |
1581 | }; | 1531 | }; |
1582 | 1532 | ||
1583 | /*/////////////////////////////////////////////////////////////////////////// */ | 1533 | /* 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */ |
1584 | /* declarations for 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */ | ||
1585 | struct hpi_fifo_buffer { | 1534 | struct hpi_fifo_buffer { |
1586 | u32 size; | 1535 | u32 size; |
1587 | u32 dSP_index; | 1536 | u32 dSP_index; |
@@ -1606,25 +1555,18 @@ u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index, | |||
1606 | /*////////////////////////////////////////////////////////////////////////// */ | 1555 | /*////////////////////////////////////////////////////////////////////////// */ |
1607 | 1556 | ||
1608 | /* main HPI entry point */ | 1557 | /* main HPI entry point */ |
1609 | hpi_handler_func hpi_send_recv; | 1558 | void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr); |
1610 | |||
1611 | /* UDP message */ | ||
1612 | void hpi_send_recvUDP(struct hpi_message *phm, struct hpi_response *phr, | ||
1613 | const unsigned int timeout); | ||
1614 | 1559 | ||
1615 | /* used in PnP OS/driver */ | 1560 | /* used in PnP OS/driver */ |
1616 | u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys, | 1561 | u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, |
1617 | const struct hpi_resource *p_resource, u16 *pw_adapter_index); | 1562 | u16 *pw_adapter_index); |
1618 | 1563 | ||
1619 | u16 hpi_subsys_delete_adapter(const struct hpi_hsubsys *ph_subsys, | 1564 | u16 hpi_subsys_delete_adapter(u16 adapter_index); |
1620 | u16 adapter_index); | ||
1621 | 1565 | ||
1622 | u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | 1566 | u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, |
1623 | u32 h_outstream, u8 **pp_buffer, | ||
1624 | struct hpi_hostbuffer_status **pp_status); | 1567 | struct hpi_hostbuffer_status **pp_status); |
1625 | 1568 | ||
1626 | u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | 1569 | u16 hpi_instream_host_buffer_get_info(u32 h_instream, u8 **pp_buffer, |
1627 | u32 h_instream, u8 **pp_buffer, | ||
1628 | struct hpi_hostbuffer_status **pp_status); | 1570 | struct hpi_hostbuffer_status **pp_status); |
1629 | 1571 | ||
1630 | u16 hpi_adapter_restart(u16 adapter_index); | 1572 | u16 hpi_adapter_restart(u16 adapter_index); |
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c index d67f4d3db911..3e9c5c289764 100644 --- a/sound/pci/asihpi/hpicmn.c +++ b/sound/pci/asihpi/hpicmn.c | |||
@@ -26,6 +26,8 @@ | |||
26 | 26 | ||
27 | #include "hpi_internal.h" | 27 | #include "hpi_internal.h" |
28 | #include "hpidebug.h" | 28 | #include "hpidebug.h" |
29 | #include "hpimsginit.h" | ||
30 | |||
29 | #include "hpicmn.h" | 31 | #include "hpicmn.h" |
30 | 32 | ||
31 | struct hpi_adapters_list { | 33 | struct hpi_adapters_list { |
@@ -43,14 +45,24 @@ static struct hpi_adapters_list adapters; | |||
43 | **/ | 45 | **/ |
44 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) | 46 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr) |
45 | { | 47 | { |
46 | u16 error = 0; | 48 | if (phr->type != HPI_TYPE_RESPONSE) { |
49 | HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type); | ||
50 | return HPI_ERROR_INVALID_RESPONSE; | ||
51 | } | ||
47 | 52 | ||
48 | if ((phr->type != HPI_TYPE_RESPONSE) | 53 | if (phr->object != phm->object) { |
49 | || (phr->object != phm->object) | 54 | HPI_DEBUG_LOG(ERROR, "header object %d invalid\n", |
50 | || (phr->function != phm->function)) | 55 | phr->object); |
51 | error = HPI_ERROR_INVALID_RESPONSE; | 56 | return HPI_ERROR_INVALID_RESPONSE; |
57 | } | ||
58 | |||
59 | if (phr->function != phm->function) { | ||
60 | HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", | ||
61 | phr->function); | ||
62 | return HPI_ERROR_INVALID_RESPONSE; | ||
63 | } | ||
52 | 64 | ||
53 | return error; | 65 | return 0; |
54 | } | 66 | } |
55 | 67 | ||
56 | u16 hpi_add_adapter(struct hpi_adapter_obj *pao) | 68 | u16 hpi_add_adapter(struct hpi_adapter_obj *pao) |
@@ -66,8 +78,18 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao) | |||
66 | } | 78 | } |
67 | 79 | ||
68 | if (adapters.adapter[pao->index].adapter_type) { | 80 | if (adapters.adapter[pao->index].adapter_type) { |
69 | { | 81 | int a; |
70 | retval = HPI_DUPLICATE_ADAPTER_NUMBER; | 82 | for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) { |
83 | if (!adapters.adapter[a].adapter_type) { | ||
84 | HPI_DEBUG_LOG(WARNING, | ||
85 | "ASI%X duplicate index %d moved to %d\n", | ||
86 | pao->adapter_type, pao->index, a); | ||
87 | pao->index = a; | ||
88 | break; | ||
89 | } | ||
90 | } | ||
91 | if (a < 0) { | ||
92 | retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER; | ||
71 | goto unlock; | 93 | goto unlock; |
72 | } | 94 | } |
73 | } | 95 | } |
@@ -76,17 +98,22 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao) | |||
76 | adapters.gw_num_adapters++; | 98 | adapters.gw_num_adapters++; |
77 | 99 | ||
78 | unlock: | 100 | unlock: |
79 | hpios_alistlock_un_lock(&adapters); | 101 | hpios_alistlock_unlock(&adapters); |
80 | return retval; | 102 | return retval; |
81 | } | 103 | } |
82 | 104 | ||
83 | void hpi_delete_adapter(struct hpi_adapter_obj *pao) | 105 | void hpi_delete_adapter(struct hpi_adapter_obj *pao) |
84 | { | 106 | { |
85 | memset(pao, 0, sizeof(struct hpi_adapter_obj)); | 107 | if (!pao->adapter_type) { |
108 | HPI_DEBUG_LOG(ERROR, "removing null adapter?\n"); | ||
109 | return; | ||
110 | } | ||
86 | 111 | ||
87 | hpios_alistlock_lock(&adapters); | 112 | hpios_alistlock_lock(&adapters); |
88 | adapters.gw_num_adapters--; /* dec the number of adapters */ | 113 | if (adapters.adapter[pao->index].adapter_type) |
89 | hpios_alistlock_un_lock(&adapters); | 114 | adapters.gw_num_adapters--; |
115 | memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0])); | ||
116 | hpios_alistlock_unlock(&adapters); | ||
90 | } | 117 | } |
91 | 118 | ||
92 | /** | 119 | /** |
@@ -99,7 +126,7 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) | |||
99 | struct hpi_adapter_obj *pao = NULL; | 126 | struct hpi_adapter_obj *pao = NULL; |
100 | 127 | ||
101 | if (adapter_index >= HPI_MAX_ADAPTERS) { | 128 | if (adapter_index >= HPI_MAX_ADAPTERS) { |
102 | HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ", | 129 | HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n", |
103 | adapter_index); | 130 | adapter_index); |
104 | return NULL; | 131 | return NULL; |
105 | } | 132 | } |
@@ -125,51 +152,34 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index) | |||
125 | * wipe an HPI_ADAPTERS_LIST structure. | 152 | * wipe an HPI_ADAPTERS_LIST structure. |
126 | * | 153 | * |
127 | **/ | 154 | **/ |
128 | static void wipe_adapter_list(void | 155 | static void wipe_adapter_list(void) |
129 | ) | ||
130 | { | 156 | { |
131 | memset(&adapters, 0, sizeof(adapters)); | 157 | memset(&adapters, 0, sizeof(adapters)); |
132 | } | 158 | } |
133 | 159 | ||
134 | /** | 160 | static void subsys_get_adapter(struct hpi_message *phm, |
135 | * SubSysGetAdapters fills awAdapterList in an struct hpi_response structure | 161 | struct hpi_response *phr) |
136 | * with all adapters in the given HPI_ADAPTERS_LIST. | ||
137 | * | ||
138 | */ | ||
139 | static void subsys_get_adapters(struct hpi_response *phr) | ||
140 | { | 162 | { |
141 | /* fill in the response adapter array with the position */ | 163 | int count = phm->obj_index; |
142 | /* identified by the adapter number/index of the adapters in */ | 164 | u16 index = 0; |
143 | /* this HPI */ | ||
144 | /* i.e. if we have an A120 with it's jumper set to */ | ||
145 | /* Adapter Number 2 then put an Adapter type A120 in the */ | ||
146 | /* array in position 1 */ | ||
147 | /* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */ | ||
148 | |||
149 | /* input: NONE */ | ||
150 | /* output: wNumAdapters */ | ||
151 | /* awAdapter[] */ | ||
152 | /* */ | ||
153 | |||
154 | short i; | ||
155 | struct hpi_adapter_obj *pao = NULL; | ||
156 | 165 | ||
157 | HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n"); | 166 | /* find the nCount'th nonzero adapter in array */ |
158 | 167 | for (index = 0; index < HPI_MAX_ADAPTERS; index++) { | |
159 | /* for each adapter, place it's type in the position of the array */ | 168 | if (adapters.adapter[index].adapter_type) { |
160 | /* corresponding to it's adapter number */ | 169 | if (!count) |
161 | for (i = 0; i < adapters.gw_num_adapters; i++) { | 170 | break; |
162 | pao = &adapters.adapter[i]; | 171 | count--; |
163 | if (phr->u.s.aw_adapter_list[pao->index] != 0) { | ||
164 | phr->error = HPI_DUPLICATE_ADAPTER_NUMBER; | ||
165 | phr->specific_error = pao->index; | ||
166 | return; | ||
167 | } | 172 | } |
168 | phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type; | ||
169 | } | 173 | } |
170 | 174 | ||
171 | phr->u.s.num_adapters = adapters.gw_num_adapters; | 175 | if (index < HPI_MAX_ADAPTERS) { |
172 | phr->error = 0; /* the function completed OK; */ | 176 | phr->u.s.adapter_index = adapters.adapter[index].index; |
177 | phr->u.s.adapter_type = adapters.adapter[index].adapter_type; | ||
178 | } else { | ||
179 | phr->u.s.adapter_index = 0; | ||
180 | phr->u.s.adapter_type = 0; | ||
181 | phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER; | ||
182 | } | ||
173 | } | 183 | } |
174 | 184 | ||
175 | static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) | 185 | static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) |
@@ -178,67 +188,98 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC) | |||
178 | int cached = 0; | 188 | int cached = 0; |
179 | if (!pC) | 189 | if (!pC) |
180 | return 0; | 190 | return 0; |
181 | if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count) | 191 | |
182 | && (pC->cache_size_in_bytes) | 192 | if (pC->init) |
183 | ) { | 193 | return pC->init; |
184 | u32 *p_master_cache; | 194 | |
185 | pC->init = 1; | 195 | if (!pC->p_cache) |
186 | 196 | return 0; | |
187 | p_master_cache = (u32 *)pC->p_cache; | 197 | |
188 | HPI_DEBUG_LOG(VERBOSE, "check %d controls\n", | 198 | if (pC->control_count && pC->cache_size_in_bytes) { |
199 | char *p_master_cache; | ||
200 | unsigned int byte_count = 0; | ||
201 | |||
202 | p_master_cache = (char *)pC->p_cache; | ||
203 | HPI_DEBUG_LOG(DEBUG, "check %d controls\n", | ||
189 | pC->control_count); | 204 | pC->control_count); |
190 | for (i = 0; i < pC->control_count; i++) { | 205 | for (i = 0; i < pC->control_count; i++) { |
191 | struct hpi_control_cache_info *info = | 206 | struct hpi_control_cache_info *info = |
192 | (struct hpi_control_cache_info *) | 207 | (struct hpi_control_cache_info *) |
193 | p_master_cache; | 208 | &p_master_cache[byte_count]; |
209 | |||
210 | if (!info->size_in32bit_words) { | ||
211 | if (!i) { | ||
212 | HPI_DEBUG_LOG(INFO, | ||
213 | "adap %d cache not ready?\n", | ||
214 | pC->adap_idx); | ||
215 | return 0; | ||
216 | } | ||
217 | /* The cache is invalid. | ||
218 | * Minimum valid entry size is | ||
219 | * sizeof(struct hpi_control_cache_info) | ||
220 | */ | ||
221 | HPI_DEBUG_LOG(ERROR, | ||
222 | "adap %d zero size cache entry %d\n", | ||
223 | pC->adap_idx, i); | ||
224 | break; | ||
225 | } | ||
194 | 226 | ||
195 | if (info->control_type) { | 227 | if (info->control_type) { |
196 | pC->p_info[i] = info; | 228 | pC->p_info[info->control_index] = info; |
197 | cached++; | 229 | cached++; |
198 | } else | 230 | } else /* dummy cache entry */ |
199 | pC->p_info[i] = NULL; | 231 | pC->p_info[info->control_index] = NULL; |
200 | 232 | ||
201 | if (info->size_in32bit_words) | 233 | byte_count += info->size_in32bit_words * 4; |
202 | p_master_cache += info->size_in32bit_words; | ||
203 | else | ||
204 | p_master_cache += | ||
205 | sizeof(struct | ||
206 | hpi_control_cache_single) / | ||
207 | sizeof(u32); | ||
208 | 234 | ||
209 | HPI_DEBUG_LOG(VERBOSE, | 235 | HPI_DEBUG_LOG(VERBOSE, |
210 | "cached %d, pinfo %p index %d type %d\n", | 236 | "cached %d, pinfo %p index %d type %d size %d\n", |
211 | cached, pC->p_info[i], info->control_index, | 237 | cached, pC->p_info[info->control_index], |
212 | info->control_type); | 238 | info->control_index, info->control_type, |
239 | info->size_in32bit_words); | ||
240 | |||
241 | /* quit loop early if whole cache has been scanned. | ||
242 | * dwControlCount is the maximum possible entries | ||
243 | * but some may be absent from the cache | ||
244 | */ | ||
245 | if (byte_count >= pC->cache_size_in_bytes) | ||
246 | break; | ||
247 | /* have seen last control index */ | ||
248 | if (info->control_index == pC->control_count - 1) | ||
249 | break; | ||
213 | } | 250 | } |
214 | /* | 251 | |
215 | We didn't find anything to cache, so try again later ! | 252 | if (byte_count != pC->cache_size_in_bytes) |
216 | */ | 253 | HPI_DEBUG_LOG(WARNING, |
217 | if (!cached) | 254 | "adap %d bytecount %d != cache size %d\n", |
218 | pC->init = 0; | 255 | pC->adap_idx, byte_count, |
256 | pC->cache_size_in_bytes); | ||
257 | else | ||
258 | HPI_DEBUG_LOG(DEBUG, | ||
259 | "adap %d cache good, bytecount == cache size = %d\n", | ||
260 | pC->adap_idx, byte_count); | ||
261 | |||
262 | pC->init = (u16)cached; | ||
219 | } | 263 | } |
220 | return pC->init; | 264 | return pC->init; |
221 | } | 265 | } |
222 | 266 | ||
223 | /** Find a control. | 267 | /** Find a control. |
224 | */ | 268 | */ |
225 | static short find_control(struct hpi_message *phm, | 269 | static short find_control(u16 control_index, |
226 | struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI, | 270 | struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI) |
227 | u16 *pw_control_index) | ||
228 | { | 271 | { |
229 | *pw_control_index = phm->obj_index; | ||
230 | |||
231 | if (!control_cache_alloc_check(p_cache)) { | 272 | if (!control_cache_alloc_check(p_cache)) { |
232 | HPI_DEBUG_LOG(VERBOSE, | 273 | HPI_DEBUG_LOG(VERBOSE, |
233 | "control_cache_alloc_check() failed. adap%d ci%d\n", | 274 | "control_cache_alloc_check() failed %d\n", |
234 | phm->adapter_index, *pw_control_index); | 275 | control_index); |
235 | return 0; | 276 | return 0; |
236 | } | 277 | } |
237 | 278 | ||
238 | *pI = p_cache->p_info[*pw_control_index]; | 279 | *pI = p_cache->p_info[control_index]; |
239 | if (!*pI) { | 280 | if (!*pI) { |
240 | HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n", | 281 | HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n", |
241 | phm->adapter_index, *pw_control_index); | 282 | control_index); |
242 | return 0; | 283 | return 0; |
243 | } else { | 284 | } else { |
244 | HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n", | 285 | HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n", |
@@ -247,25 +288,6 @@ static short find_control(struct hpi_message *phm, | |||
247 | return 1; | 288 | return 1; |
248 | } | 289 | } |
249 | 290 | ||
250 | /** Used by the kernel driver to figure out if a buffer needs mapping. | ||
251 | */ | ||
252 | short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache, | ||
253 | struct hpi_message *phm, void **p, unsigned int *pN) | ||
254 | { | ||
255 | *pN = 0; | ||
256 | *p = NULL; | ||
257 | if ((phm->function == HPI_CONTROL_GET_STATE) | ||
258 | && (phm->object == HPI_OBJ_CONTROLEX) | ||
259 | ) { | ||
260 | u16 control_index; | ||
261 | struct hpi_control_cache_info *pI; | ||
262 | |||
263 | if (!find_control(phm, p_cache, &pI, &control_index)) | ||
264 | return 0; | ||
265 | } | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | /* allow unified treatment of several string fields within struct */ | 291 | /* allow unified treatment of several string fields within struct */ |
270 | #define HPICMN_PAD_OFS_AND_SIZE(m) {\ | 292 | #define HPICMN_PAD_OFS_AND_SIZE(m) {\ |
271 | offsetof(struct hpi_control_cache_pad, m), \ | 293 | offsetof(struct hpi_control_cache_pad, m), \ |
@@ -290,13 +312,16 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
290 | struct hpi_message *phm, struct hpi_response *phr) | 312 | struct hpi_message *phm, struct hpi_response *phr) |
291 | { | 313 | { |
292 | short found = 1; | 314 | short found = 1; |
293 | u16 control_index; | ||
294 | struct hpi_control_cache_info *pI; | 315 | struct hpi_control_cache_info *pI; |
295 | struct hpi_control_cache_single *pC; | 316 | struct hpi_control_cache_single *pC; |
296 | struct hpi_control_cache_pad *p_pad; | 317 | struct hpi_control_cache_pad *p_pad; |
297 | 318 | ||
298 | if (!find_control(phm, p_cache, &pI, &control_index)) | 319 | if (!find_control(phm->obj_index, p_cache, &pI)) { |
320 | HPI_DEBUG_LOG(VERBOSE, | ||
321 | "HPICMN find_control() failed for adap %d\n", | ||
322 | phm->adapter_index); | ||
299 | return 0; | 323 | return 0; |
324 | } | ||
300 | 325 | ||
301 | phr->error = 0; | 326 | phr->error = 0; |
302 | 327 | ||
@@ -310,55 +335,79 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
310 | 335 | ||
311 | case HPI_CONTROL_METER: | 336 | case HPI_CONTROL_METER: |
312 | if (phm->u.c.attribute == HPI_METER_PEAK) { | 337 | if (phm->u.c.attribute == HPI_METER_PEAK) { |
313 | phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0]; | 338 | phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0]; |
314 | phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1]; | 339 | phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1]; |
315 | } else if (phm->u.c.attribute == HPI_METER_RMS) { | 340 | } else if (phm->u.c.attribute == HPI_METER_RMS) { |
316 | phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0]; | 341 | if (pC->u.meter.an_logRMS[0] == |
317 | phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1]; | 342 | HPI_CACHE_INVALID_SHORT) { |
343 | phr->error = | ||
344 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
345 | phr->u.c.an_log_value[0] = HPI_METER_MINIMUM; | ||
346 | phr->u.c.an_log_value[1] = HPI_METER_MINIMUM; | ||
347 | } else { | ||
348 | phr->u.c.an_log_value[0] = | ||
349 | pC->u.meter.an_logRMS[0]; | ||
350 | phr->u.c.an_log_value[1] = | ||
351 | pC->u.meter.an_logRMS[1]; | ||
352 | } | ||
318 | } else | 353 | } else |
319 | found = 0; | 354 | found = 0; |
320 | break; | 355 | break; |
321 | case HPI_CONTROL_VOLUME: | 356 | case HPI_CONTROL_VOLUME: |
322 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { | 357 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { |
323 | phr->u.c.an_log_value[0] = pC->u.v.an_log[0]; | 358 | phr->u.c.an_log_value[0] = pC->u.vol.an_log[0]; |
324 | phr->u.c.an_log_value[1] = pC->u.v.an_log[1]; | 359 | phr->u.c.an_log_value[1] = pC->u.vol.an_log[1]; |
325 | } else | 360 | } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { |
361 | if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) { | ||
362 | if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED) | ||
363 | phr->u.c.param1 = | ||
364 | HPI_BITMASK_ALL_CHANNELS; | ||
365 | else | ||
366 | phr->u.c.param1 = 0; | ||
367 | } else { | ||
368 | phr->error = | ||
369 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
370 | phr->u.c.param1 = 0; | ||
371 | } | ||
372 | } else { | ||
326 | found = 0; | 373 | found = 0; |
374 | } | ||
327 | break; | 375 | break; |
328 | case HPI_CONTROL_MULTIPLEXER: | 376 | case HPI_CONTROL_MULTIPLEXER: |
329 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { | 377 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { |
330 | phr->u.c.param1 = pC->u.x.source_node_type; | 378 | phr->u.c.param1 = pC->u.mux.source_node_type; |
331 | phr->u.c.param2 = pC->u.x.source_node_index; | 379 | phr->u.c.param2 = pC->u.mux.source_node_index; |
332 | } else { | 380 | } else { |
333 | found = 0; | 381 | found = 0; |
334 | } | 382 | } |
335 | break; | 383 | break; |
336 | case HPI_CONTROL_CHANNEL_MODE: | 384 | case HPI_CONTROL_CHANNEL_MODE: |
337 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) | 385 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) |
338 | phr->u.c.param1 = pC->u.m.mode; | 386 | phr->u.c.param1 = pC->u.mode.mode; |
339 | else | 387 | else |
340 | found = 0; | 388 | found = 0; |
341 | break; | 389 | break; |
342 | case HPI_CONTROL_LEVEL: | 390 | case HPI_CONTROL_LEVEL: |
343 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { | 391 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { |
344 | phr->u.c.an_log_value[0] = pC->u.l.an_log[0]; | 392 | phr->u.c.an_log_value[0] = pC->u.level.an_log[0]; |
345 | phr->u.c.an_log_value[1] = pC->u.l.an_log[1]; | 393 | phr->u.c.an_log_value[1] = pC->u.level.an_log[1]; |
346 | } else | 394 | } else |
347 | found = 0; | 395 | found = 0; |
348 | break; | 396 | break; |
349 | case HPI_CONTROL_TUNER: | 397 | case HPI_CONTROL_TUNER: |
350 | if (phm->u.c.attribute == HPI_TUNER_FREQ) | 398 | if (phm->u.c.attribute == HPI_TUNER_FREQ) |
351 | phr->u.c.param1 = pC->u.t.freq_ink_hz; | 399 | phr->u.c.param1 = pC->u.tuner.freq_ink_hz; |
352 | else if (phm->u.c.attribute == HPI_TUNER_BAND) | 400 | else if (phm->u.c.attribute == HPI_TUNER_BAND) |
353 | phr->u.c.param1 = pC->u.t.band; | 401 | phr->u.c.param1 = pC->u.tuner.band; |
354 | else if ((phm->u.c.attribute == HPI_TUNER_LEVEL) | 402 | else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG) |
355 | && (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE)) | 403 | if (pC->u.tuner.s_level_avg == |
356 | if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) { | 404 | HPI_CACHE_INVALID_SHORT) { |
357 | phr->u.c.param1 = 0; | 405 | phr->u.cu.tuner.s_level = 0; |
358 | phr->error = | 406 | phr->error = |
359 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | 407 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; |
360 | } else | 408 | } else |
361 | phr->u.c.param1 = pC->u.t.level; | 409 | phr->u.cu.tuner.s_level = |
410 | pC->u.tuner.s_level_avg; | ||
362 | else | 411 | else |
363 | found = 0; | 412 | found = 0; |
364 | break; | 413 | break; |
@@ -366,7 +415,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
366 | if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) | 415 | if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) |
367 | phr->u.c.param1 = pC->u.aes3rx.error_status; | 416 | phr->u.c.param1 = pC->u.aes3rx.error_status; |
368 | else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) | 417 | else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) |
369 | phr->u.c.param1 = pC->u.aes3rx.source; | 418 | phr->u.c.param1 = pC->u.aes3rx.format; |
370 | else | 419 | else |
371 | found = 0; | 420 | found = 0; |
372 | break; | 421 | break; |
@@ -385,13 +434,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
385 | case HPI_CONTROL_SILENCEDETECTOR: | 434 | case HPI_CONTROL_SILENCEDETECTOR: |
386 | if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) { | 435 | if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) { |
387 | phr->u.c.param1 = pC->u.silence.state; | 436 | phr->u.c.param1 = pC->u.silence.state; |
388 | phr->u.c.param2 = pC->u.silence.count; | ||
389 | } else | 437 | } else |
390 | found = 0; | 438 | found = 0; |
391 | break; | 439 | break; |
392 | case HPI_CONTROL_MICROPHONE: | 440 | case HPI_CONTROL_MICROPHONE: |
393 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) | 441 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) |
394 | phr->u.c.param1 = pC->u.phantom_power.state; | 442 | phr->u.c.param1 = pC->u.microphone.phantom_state; |
395 | else | 443 | else |
396 | found = 0; | 444 | found = 0; |
397 | break; | 445 | break; |
@@ -400,7 +448,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
400 | phr->u.c.param1 = pC->u.clk.source; | 448 | phr->u.c.param1 = pC->u.clk.source; |
401 | else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) { | 449 | else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) { |
402 | if (pC->u.clk.source_index == | 450 | if (pC->u.clk.source_index == |
403 | HPI_ERROR_ILLEGAL_CACHE_VALUE) { | 451 | HPI_CACHE_INVALID_UINT16) { |
404 | phr->u.c.param1 = 0; | 452 | phr->u.c.param1 = 0; |
405 | phr->error = | 453 | phr->error = |
406 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | 454 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; |
@@ -411,60 +459,63 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
411 | else | 459 | else |
412 | found = 0; | 460 | found = 0; |
413 | break; | 461 | break; |
414 | case HPI_CONTROL_PAD: | 462 | case HPI_CONTROL_PAD:{ |
463 | struct hpi_control_cache_pad *p_pad; | ||
464 | p_pad = (struct hpi_control_cache_pad *)pI; | ||
415 | 465 | ||
416 | if (!(p_pad->field_valid_flags & (1 << | 466 | if (!(p_pad->field_valid_flags & (1 << |
417 | HPI_CTL_ATTR_INDEX(phm->u.c. | 467 | HPI_CTL_ATTR_INDEX(phm->u.c. |
418 | attribute)))) { | 468 | attribute)))) { |
419 | phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
420 | break; | ||
421 | } | ||
422 | |||
423 | if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID) | ||
424 | phr->u.c.param1 = p_pad->pI; | ||
425 | else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE) | ||
426 | phr->u.c.param1 = p_pad->pTY; | ||
427 | else { | ||
428 | unsigned int index = | ||
429 | HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1; | ||
430 | unsigned int offset = phm->u.c.param1; | ||
431 | unsigned int pad_string_len, field_size; | ||
432 | char *pad_string; | ||
433 | unsigned int tocopy; | ||
434 | |||
435 | HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n", | ||
436 | phm->u.c.attribute); | ||
437 | |||
438 | if (index > ARRAY_SIZE(pad_desc) - 1) { | ||
439 | phr->error = | 469 | phr->error = |
440 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | 470 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; |
441 | break; | 471 | break; |
442 | } | 472 | } |
443 | 473 | ||
444 | pad_string = ((char *)p_pad) + pad_desc[index].offset; | 474 | if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID) |
445 | field_size = pad_desc[index].field_size; | 475 | phr->u.c.param1 = p_pad->pI; |
446 | /* Ensure null terminator */ | 476 | else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE) |
447 | pad_string[field_size - 1] = 0; | 477 | phr->u.c.param1 = p_pad->pTY; |
448 | 478 | else { | |
449 | pad_string_len = strlen(pad_string) + 1; | 479 | unsigned int index = |
450 | 480 | HPI_CTL_ATTR_INDEX(phm->u.c. | |
451 | if (offset > pad_string_len) { | 481 | attribute) - 1; |
452 | phr->error = HPI_ERROR_INVALID_CONTROL_VALUE; | 482 | unsigned int offset = phm->u.c.param1; |
453 | break; | 483 | unsigned int pad_string_len, field_size; |
484 | char *pad_string; | ||
485 | unsigned int tocopy; | ||
486 | |||
487 | if (index > ARRAY_SIZE(pad_desc) - 1) { | ||
488 | phr->error = | ||
489 | HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; | ||
490 | break; | ||
491 | } | ||
492 | |||
493 | pad_string = | ||
494 | ((char *)p_pad) + | ||
495 | pad_desc[index].offset; | ||
496 | field_size = pad_desc[index].field_size; | ||
497 | /* Ensure null terminator */ | ||
498 | pad_string[field_size - 1] = 0; | ||
499 | |||
500 | pad_string_len = strlen(pad_string) + 1; | ||
501 | |||
502 | if (offset > pad_string_len) { | ||
503 | phr->error = | ||
504 | HPI_ERROR_INVALID_CONTROL_VALUE; | ||
505 | break; | ||
506 | } | ||
507 | |||
508 | tocopy = pad_string_len - offset; | ||
509 | if (tocopy > sizeof(phr->u.cu.chars8.sz_data)) | ||
510 | tocopy = sizeof(phr->u.cu.chars8. | ||
511 | sz_data); | ||
512 | |||
513 | memcpy(phr->u.cu.chars8.sz_data, | ||
514 | &pad_string[offset], tocopy); | ||
515 | |||
516 | phr->u.cu.chars8.remaining_chars = | ||
517 | pad_string_len - offset - tocopy; | ||
454 | } | 518 | } |
455 | |||
456 | tocopy = pad_string_len - offset; | ||
457 | if (tocopy > sizeof(phr->u.cu.chars8.sz_data)) | ||
458 | tocopy = sizeof(phr->u.cu.chars8.sz_data); | ||
459 | |||
460 | HPI_DEBUG_LOG(VERBOSE, | ||
461 | "PADS memcpy(%d), offset %d \n", tocopy, | ||
462 | offset); | ||
463 | memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset], | ||
464 | tocopy); | ||
465 | |||
466 | phr->u.cu.chars8.remaining_chars = | ||
467 | pad_string_len - offset - tocopy; | ||
468 | } | 519 | } |
469 | break; | 520 | break; |
470 | default: | 521 | default: |
@@ -472,16 +523,9 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache, | |||
472 | break; | 523 | break; |
473 | } | 524 | } |
474 | 525 | ||
475 | if (found) | 526 | HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n", |
476 | HPI_DEBUG_LOG(VERBOSE, | 527 | found ? "Cached" : "Uncached", phm->adapter_index, |
477 | "cached adap %d, ctl %d, type %d, attr %d\n", | 528 | pI->control_index, pI->control_type, phm->u.c.attribute); |
478 | phm->adapter_index, pI->control_index, | ||
479 | pI->control_type, phm->u.c.attribute); | ||
480 | else | ||
481 | HPI_DEBUG_LOG(VERBOSE, | ||
482 | "uncached adap %d, ctl %d, ctl type %d\n", | ||
483 | phm->adapter_index, pI->control_index, | ||
484 | pI->control_type); | ||
485 | 529 | ||
486 | if (found) | 530 | if (found) |
487 | phr->size = | 531 | phr->size = |
@@ -497,18 +541,21 @@ Only update if no error. | |||
497 | Volume and Level return the limited values in the response, so use these | 541 | Volume and Level return the limited values in the response, so use these |
498 | Multiplexer does so use sent values | 542 | Multiplexer does so use sent values |
499 | */ | 543 | */ |
500 | void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | 544 | void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache, |
501 | struct hpi_message *phm, struct hpi_response *phr) | 545 | struct hpi_message *phm, struct hpi_response *phr) |
502 | { | 546 | { |
503 | u16 control_index; | ||
504 | struct hpi_control_cache_single *pC; | 547 | struct hpi_control_cache_single *pC; |
505 | struct hpi_control_cache_info *pI; | 548 | struct hpi_control_cache_info *pI; |
506 | 549 | ||
507 | if (phr->error) | 550 | if (phr->error) |
508 | return; | 551 | return; |
509 | 552 | ||
510 | if (!find_control(phm, p_cache, &pI, &control_index)) | 553 | if (!find_control(phm->obj_index, p_cache, &pI)) { |
554 | HPI_DEBUG_LOG(VERBOSE, | ||
555 | "HPICMN find_control() failed for adap %d\n", | ||
556 | phm->adapter_index); | ||
511 | return; | 557 | return; |
558 | } | ||
512 | 559 | ||
513 | /* pC is the default cached control strucure. | 560 | /* pC is the default cached control strucure. |
514 | May be cast to something else in the following switch statement. | 561 | May be cast to something else in the following switch statement. |
@@ -518,31 +565,36 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | |||
518 | switch (pI->control_type) { | 565 | switch (pI->control_type) { |
519 | case HPI_CONTROL_VOLUME: | 566 | case HPI_CONTROL_VOLUME: |
520 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { | 567 | if (phm->u.c.attribute == HPI_VOLUME_GAIN) { |
521 | pC->u.v.an_log[0] = phr->u.c.an_log_value[0]; | 568 | pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; |
522 | pC->u.v.an_log[1] = phr->u.c.an_log_value[1]; | 569 | pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; |
570 | } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { | ||
571 | if (phm->u.c.param1) | ||
572 | pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED; | ||
573 | else | ||
574 | pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED; | ||
523 | } | 575 | } |
524 | break; | 576 | break; |
525 | case HPI_CONTROL_MULTIPLEXER: | 577 | case HPI_CONTROL_MULTIPLEXER: |
526 | /* mux does not return its setting on Set command. */ | 578 | /* mux does not return its setting on Set command. */ |
527 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { | 579 | if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { |
528 | pC->u.x.source_node_type = (u16)phm->u.c.param1; | 580 | pC->u.mux.source_node_type = (u16)phm->u.c.param1; |
529 | pC->u.x.source_node_index = (u16)phm->u.c.param2; | 581 | pC->u.mux.source_node_index = (u16)phm->u.c.param2; |
530 | } | 582 | } |
531 | break; | 583 | break; |
532 | case HPI_CONTROL_CHANNEL_MODE: | 584 | case HPI_CONTROL_CHANNEL_MODE: |
533 | /* mode does not return its setting on Set command. */ | 585 | /* mode does not return its setting on Set command. */ |
534 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) | 586 | if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) |
535 | pC->u.m.mode = (u16)phm->u.c.param1; | 587 | pC->u.mode.mode = (u16)phm->u.c.param1; |
536 | break; | 588 | break; |
537 | case HPI_CONTROL_LEVEL: | 589 | case HPI_CONTROL_LEVEL: |
538 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { | 590 | if (phm->u.c.attribute == HPI_LEVEL_GAIN) { |
539 | pC->u.v.an_log[0] = phr->u.c.an_log_value[0]; | 591 | pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; |
540 | pC->u.v.an_log[1] = phr->u.c.an_log_value[1]; | 592 | pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; |
541 | } | 593 | } |
542 | break; | 594 | break; |
543 | case HPI_CONTROL_MICROPHONE: | 595 | case HPI_CONTROL_MICROPHONE: |
544 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) | 596 | if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) |
545 | pC->u.phantom_power.state = (u16)phm->u.c.param1; | 597 | pC->u.microphone.phantom_state = (u16)phm->u.c.param1; |
546 | break; | 598 | break; |
547 | case HPI_CONTROL_AESEBU_TRANSMITTER: | 599 | case HPI_CONTROL_AESEBU_TRANSMITTER: |
548 | if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) | 600 | if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) |
@@ -550,7 +602,7 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | |||
550 | break; | 602 | break; |
551 | case HPI_CONTROL_AESEBU_RECEIVER: | 603 | case HPI_CONTROL_AESEBU_RECEIVER: |
552 | if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) | 604 | if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) |
553 | pC->u.aes3rx.source = phm->u.c.param1; | 605 | pC->u.aes3rx.format = phm->u.c.param1; |
554 | break; | 606 | break; |
555 | case HPI_CONTROL_SAMPLECLOCK: | 607 | case HPI_CONTROL_SAMPLECLOCK: |
556 | if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) | 608 | if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) |
@@ -565,59 +617,57 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache, | |||
565 | } | 617 | } |
566 | } | 618 | } |
567 | 619 | ||
568 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 | 620 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, |
569 | number_of_controls, const u32 size_in_bytes, | 621 | const u32 size_in_bytes, u8 *p_dsp_control_buffer) |
570 | struct hpi_control_cache_info *pDSP_control_buffer) | ||
571 | { | 622 | { |
572 | struct hpi_control_cache *p_cache = | 623 | struct hpi_control_cache *p_cache = |
573 | kmalloc(sizeof(*p_cache), GFP_KERNEL); | 624 | kmalloc(sizeof(*p_cache), GFP_KERNEL); |
574 | if (!p_cache) | 625 | if (!p_cache) |
575 | return NULL; | 626 | return NULL; |
627 | |||
576 | p_cache->p_info = | 628 | p_cache->p_info = |
577 | kmalloc(sizeof(*p_cache->p_info) * number_of_controls, | 629 | kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL); |
578 | GFP_KERNEL); | ||
579 | if (!p_cache->p_info) { | 630 | if (!p_cache->p_info) { |
580 | kfree(p_cache); | 631 | kfree(p_cache); |
581 | return NULL; | 632 | return NULL; |
582 | } | 633 | } |
634 | memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count); | ||
583 | p_cache->cache_size_in_bytes = size_in_bytes; | 635 | p_cache->cache_size_in_bytes = size_in_bytes; |
584 | p_cache->control_count = number_of_controls; | 636 | p_cache->control_count = control_count; |
585 | p_cache->p_cache = | 637 | p_cache->p_cache = p_dsp_control_buffer; |
586 | (struct hpi_control_cache_single *)pDSP_control_buffer; | ||
587 | p_cache->init = 0; | 638 | p_cache->init = 0; |
588 | return p_cache; | 639 | return p_cache; |
589 | } | 640 | } |
590 | 641 | ||
591 | void hpi_free_control_cache(struct hpi_control_cache *p_cache) | 642 | void hpi_free_control_cache(struct hpi_control_cache *p_cache) |
592 | { | 643 | { |
593 | if (p_cache->init) { | 644 | if (p_cache) { |
594 | kfree(p_cache->p_info); | 645 | kfree(p_cache->p_info); |
595 | p_cache->p_info = NULL; | ||
596 | p_cache->init = 0; | ||
597 | kfree(p_cache); | 646 | kfree(p_cache); |
598 | } | 647 | } |
599 | } | 648 | } |
600 | 649 | ||
601 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) | 650 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) |
602 | { | 651 | { |
652 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0); | ||
603 | 653 | ||
604 | switch (phm->function) { | 654 | switch (phm->function) { |
605 | case HPI_SUBSYS_OPEN: | 655 | case HPI_SUBSYS_OPEN: |
606 | case HPI_SUBSYS_CLOSE: | 656 | case HPI_SUBSYS_CLOSE: |
607 | case HPI_SUBSYS_DRIVER_UNLOAD: | 657 | case HPI_SUBSYS_DRIVER_UNLOAD: |
608 | phr->error = 0; | ||
609 | break; | 658 | break; |
610 | case HPI_SUBSYS_DRIVER_LOAD: | 659 | case HPI_SUBSYS_DRIVER_LOAD: |
611 | wipe_adapter_list(); | 660 | wipe_adapter_list(); |
612 | hpios_alistlock_init(&adapters); | 661 | hpios_alistlock_init(&adapters); |
613 | phr->error = 0; | ||
614 | break; | 662 | break; |
615 | case HPI_SUBSYS_GET_INFO: | 663 | case HPI_SUBSYS_GET_ADAPTER: |
616 | subsys_get_adapters(phr); | 664 | subsys_get_adapter(phm, phr); |
665 | break; | ||
666 | case HPI_SUBSYS_GET_NUM_ADAPTERS: | ||
667 | phr->u.s.num_adapters = adapters.gw_num_adapters; | ||
617 | break; | 668 | break; |
618 | case HPI_SUBSYS_CREATE_ADAPTER: | 669 | case HPI_SUBSYS_CREATE_ADAPTER: |
619 | case HPI_SUBSYS_DELETE_ADAPTER: | 670 | case HPI_SUBSYS_DELETE_ADAPTER: |
620 | phr->error = 0; | ||
621 | break; | 671 | break; |
622 | default: | 672 | default: |
623 | phr->error = HPI_ERROR_INVALID_FUNC; | 673 | phr->error = HPI_ERROR_INVALID_FUNC; |
diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h index 6229022f56cb..590f0b69e655 100644 --- a/sound/pci/asihpi/hpicmn.h +++ b/sound/pci/asihpi/hpicmn.h | |||
@@ -33,18 +33,19 @@ struct hpi_adapter_obj { | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | struct hpi_control_cache { | 35 | struct hpi_control_cache { |
36 | u32 init; /**< indicates whether the | 36 | /** indicates whether the structures are initialized */ |
37 | structures are initialized */ | 37 | u16 init; |
38 | u16 adap_idx; | ||
38 | u32 control_count; | 39 | u32 control_count; |
39 | u32 cache_size_in_bytes; | 40 | u32 cache_size_in_bytes; |
40 | struct hpi_control_cache_info | 41 | /** pointer to allocated memory of lookup pointers. */ |
41 | **p_info; /**< pointer to allocated memory of | 42 | struct hpi_control_cache_info **p_info; |
42 | lookup pointers. */ | 43 | /** pointer to DSP's control cache. */ |
43 | struct hpi_control_cache_single | 44 | u8 *p_cache; |
44 | *p_cache; /**< pointer to DSP's control cache. */ | ||
45 | }; | 45 | }; |
46 | 46 | ||
47 | struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index); | 47 | struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index); |
48 | |||
48 | u16 hpi_add_adapter(struct hpi_adapter_obj *pao); | 49 | u16 hpi_add_adapter(struct hpi_adapter_obj *pao); |
49 | 50 | ||
50 | void hpi_delete_adapter(struct hpi_adapter_obj *pao); | 51 | void hpi_delete_adapter(struct hpi_adapter_obj *pao); |
@@ -52,13 +53,10 @@ void hpi_delete_adapter(struct hpi_adapter_obj *pao); | |||
52 | short hpi_check_control_cache(struct hpi_control_cache *pC, | 53 | short hpi_check_control_cache(struct hpi_control_cache *pC, |
53 | struct hpi_message *phm, struct hpi_response *phr); | 54 | struct hpi_message *phm, struct hpi_response *phr); |
54 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 | 55 | struct hpi_control_cache *hpi_alloc_control_cache(const u32 |
55 | number_of_controls, const u32 size_in_bytes, | 56 | number_of_controls, const u32 size_in_bytes, u8 *pDSP_control_buffer); |
56 | struct hpi_control_cache_info | ||
57 | *pDSP_control_buffer); | ||
58 | void hpi_free_control_cache(struct hpi_control_cache *p_cache); | 57 | void hpi_free_control_cache(struct hpi_control_cache *p_cache); |
59 | 58 | ||
60 | void hpi_sync_control_cache(struct hpi_control_cache *pC, | 59 | void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC, |
61 | struct hpi_message *phm, struct hpi_response *phr); | 60 | struct hpi_message *phm, struct hpi_response *phr); |
61 | |||
62 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr); | 62 | u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr); |
63 | short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache, | ||
64 | struct hpi_message *phm, void **p, unsigned int *pN); | ||
diff --git a/sound/pci/asihpi/hpidebug.c b/sound/pci/asihpi/hpidebug.c index 949836ec913a..b52baf62791e 100644 --- a/sound/pci/asihpi/hpidebug.c +++ b/sound/pci/asihpi/hpidebug.c | |||
@@ -45,161 +45,14 @@ int hpi_debug_level_get(void) | |||
45 | return hpi_debug_level; | 45 | return hpi_debug_level; |
46 | } | 46 | } |
47 | 47 | ||
48 | #ifdef HPIOS_DEBUG_PRINT | ||
49 | /* implies OS has no printf-like function */ | ||
50 | #include <stdarg.h> | ||
51 | |||
52 | void hpi_debug_printf(char *fmt, ...) | ||
53 | { | ||
54 | va_list arglist; | ||
55 | char buffer[128]; | ||
56 | |||
57 | va_start(arglist, fmt); | ||
58 | |||
59 | if (buffer[0]) | ||
60 | HPIOS_DEBUG_PRINT(buffer); | ||
61 | va_end(arglist); | ||
62 | } | ||
63 | #endif | ||
64 | |||
65 | struct treenode { | ||
66 | void *array; | ||
67 | unsigned int num_elements; | ||
68 | }; | ||
69 | |||
70 | #define make_treenode_from_array(nodename, array) \ | ||
71 | static void *tmp_strarray_##nodename[] = array; \ | ||
72 | static struct treenode nodename = { \ | ||
73 | &tmp_strarray_##nodename, \ | ||
74 | ARRAY_SIZE(tmp_strarray_##nodename) \ | ||
75 | }; | ||
76 | |||
77 | #define get_treenode_elem(node_ptr, idx, type) \ | ||
78 | (&(*((type *)(node_ptr)->array)[idx])) | ||
79 | |||
80 | make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS) | ||
81 | |||
82 | make_treenode_from_array(hpi_subsys_strings, HPI_SUBSYS_STRINGS) | ||
83 | make_treenode_from_array(hpi_adapter_strings, HPI_ADAPTER_STRINGS) | ||
84 | make_treenode_from_array(hpi_istream_strings, HPI_ISTREAM_STRINGS) | ||
85 | make_treenode_from_array(hpi_ostream_strings, HPI_OSTREAM_STRINGS) | ||
86 | make_treenode_from_array(hpi_mixer_strings, HPI_MIXER_STRINGS) | ||
87 | make_treenode_from_array(hpi_node_strings, | ||
88 | { | ||
89 | "NODE is invalid object"}) | ||
90 | |||
91 | make_treenode_from_array(hpi_control_strings, HPI_CONTROL_STRINGS) | ||
92 | make_treenode_from_array(hpi_nvmemory_strings, HPI_OBJ_STRINGS) | ||
93 | make_treenode_from_array(hpi_digitalio_strings, HPI_DIGITALIO_STRINGS) | ||
94 | make_treenode_from_array(hpi_watchdog_strings, HPI_WATCHDOG_STRINGS) | ||
95 | make_treenode_from_array(hpi_clock_strings, HPI_CLOCK_STRINGS) | ||
96 | make_treenode_from_array(hpi_profile_strings, HPI_PROFILE_STRINGS) | ||
97 | make_treenode_from_array(hpi_asyncevent_strings, HPI_ASYNCEVENT_STRINGS) | ||
98 | #define HPI_FUNCTION_STRINGS \ | ||
99 | { \ | ||
100 | &hpi_subsys_strings,\ | ||
101 | &hpi_adapter_strings,\ | ||
102 | &hpi_ostream_strings,\ | ||
103 | &hpi_istream_strings,\ | ||
104 | &hpi_mixer_strings,\ | ||
105 | &hpi_node_strings,\ | ||
106 | &hpi_control_strings,\ | ||
107 | &hpi_nvmemory_strings,\ | ||
108 | &hpi_digitalio_strings,\ | ||
109 | &hpi_watchdog_strings,\ | ||
110 | &hpi_clock_strings,\ | ||
111 | &hpi_profile_strings,\ | ||
112 | &hpi_control_strings, \ | ||
113 | &hpi_asyncevent_strings \ | ||
114 | } | ||
115 | make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS) | ||
116 | |||
117 | compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match); | ||
118 | |||
119 | static char *hpi_function_string(unsigned int function) | ||
120 | { | ||
121 | unsigned int object; | ||
122 | struct treenode *tmp; | ||
123 | |||
124 | object = function / HPI_OBJ_FUNCTION_SPACING; | ||
125 | function = function - object * HPI_OBJ_FUNCTION_SPACING; | ||
126 | |||
127 | if (object == 0 || object == HPI_OBJ_NODE | ||
128 | || object > hpi_function_strings.num_elements) | ||
129 | return "invalid object"; | ||
130 | |||
131 | tmp = get_treenode_elem(&hpi_function_strings, object - 1, | ||
132 | struct treenode *); | ||
133 | |||
134 | if (function == 0 || function > tmp->num_elements) | ||
135 | return "invalid function"; | ||
136 | |||
137 | return get_treenode_elem(tmp, function - 1, char *); | ||
138 | } | ||
139 | |||
140 | void hpi_debug_message(struct hpi_message *phm, char *sz_fileline) | 48 | void hpi_debug_message(struct hpi_message *phm, char *sz_fileline) |
141 | { | 49 | { |
142 | if (phm) { | 50 | if (phm) { |
143 | if ((phm->object <= HPI_OBJ_MAXINDEX) && phm->object) { | 51 | printk(KERN_DEBUG "HPI_MSG%d,%d,%d,%d,%d\n", phm->version, |
144 | u16 index = 0; | 52 | phm->adapter_index, phm->obj_index, phm->function, |
145 | u16 attrib = 0; | 53 | phm->u.c.attribute); |
146 | int is_control = 0; | 54 | } |
147 | 55 | ||
148 | index = phm->obj_index; | ||
149 | switch (phm->object) { | ||
150 | case HPI_OBJ_ADAPTER: | ||
151 | case HPI_OBJ_PROFILE: | ||
152 | break; | ||
153 | case HPI_OBJ_MIXER: | ||
154 | if (phm->function == | ||
155 | HPI_MIXER_GET_CONTROL_BY_INDEX) | ||
156 | index = phm->u.m.control_index; | ||
157 | break; | ||
158 | case HPI_OBJ_OSTREAM: | ||
159 | case HPI_OBJ_ISTREAM: | ||
160 | break; | ||
161 | |||
162 | case HPI_OBJ_CONTROLEX: | ||
163 | case HPI_OBJ_CONTROL: | ||
164 | if (phm->version == 1) | ||
165 | attrib = HPI_CTL_ATTR(UNIVERSAL, 1); | ||
166 | else | ||
167 | attrib = phm->u.c.attribute; | ||
168 | is_control = 1; | ||
169 | break; | ||
170 | default: | ||
171 | break; | ||
172 | } | ||
173 | |||
174 | if (is_control && (attrib & 0xFF00)) { | ||
175 | int control_type = (attrib & 0xFF00) >> 8; | ||
176 | int attr_index = HPI_CTL_ATTR_INDEX(attrib); | ||
177 | /* note the KERN facility level | ||
178 | is in szFileline already */ | ||
179 | printk("%s adapter %d %s " | ||
180 | "ctrl_index x%04x %s %d\n", | ||
181 | sz_fileline, phm->adapter_index, | ||
182 | hpi_function_string(phm->function), | ||
183 | index, | ||
184 | get_treenode_elem | ||
185 | (&hpi_control_type_strings, | ||
186 | control_type, char *), | ||
187 | attr_index); | ||
188 | |||
189 | } else | ||
190 | printk("%s adapter %d %s " | ||
191 | "idx x%04x attr x%04x \n", | ||
192 | sz_fileline, phm->adapter_index, | ||
193 | hpi_function_string(phm->function), | ||
194 | index, attrib); | ||
195 | } else { | ||
196 | printk("adap=%d, invalid obj=%d, func=0x%x\n", | ||
197 | phm->adapter_index, phm->object, | ||
198 | phm->function); | ||
199 | } | ||
200 | } else | ||
201 | printk(KERN_ERR | ||
202 | "NULL message pointer to hpi_debug_message!\n"); | ||
203 | } | 56 | } |
204 | 57 | ||
205 | void hpi_debug_data(u16 *pdata, u32 len) | 58 | void hpi_debug_data(u16 *pdata, u32 len) |
diff --git a/sound/pci/asihpi/hpidebug.h b/sound/pci/asihpi/hpidebug.h index a2f0952a99f0..940f54c3c538 100644 --- a/sound/pci/asihpi/hpidebug.h +++ b/sound/pci/asihpi/hpidebug.h | |||
@@ -37,7 +37,7 @@ enum { HPI_DEBUG_LEVEL_ERROR = 0, /* always log errors */ | |||
37 | #define HPI_DEBUG_LEVEL_DEFAULT HPI_DEBUG_LEVEL_NOTICE | 37 | #define HPI_DEBUG_LEVEL_DEFAULT HPI_DEBUG_LEVEL_NOTICE |
38 | 38 | ||
39 | /* an OS can define an extra flag string that is appended to | 39 | /* an OS can define an extra flag string that is appended to |
40 | the start of each message, eg see hpios_linux.h */ | 40 | the start of each message, eg see linux kernel hpios.h */ |
41 | 41 | ||
42 | #ifdef SOURCEFILE_NAME | 42 | #ifdef SOURCEFILE_NAME |
43 | #define FILE_LINE SOURCEFILE_NAME ":" __stringify(__LINE__) " " | 43 | #define FILE_LINE SOURCEFILE_NAME ":" __stringify(__LINE__) " " |
@@ -45,18 +45,11 @@ enum { HPI_DEBUG_LEVEL_ERROR = 0, /* always log errors */ | |||
45 | #define FILE_LINE __FILE__ ":" __stringify(__LINE__) " " | 45 | #define FILE_LINE __FILE__ ":" __stringify(__LINE__) " " |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | #if defined(HPI_DEBUG) && defined(_WINDOWS) | ||
49 | #define HPI_DEBUGBREAK() debug_break() | ||
50 | #else | ||
51 | #define HPI_DEBUGBREAK() | ||
52 | #endif | ||
53 | |||
54 | #define HPI_DEBUG_ASSERT(expression) \ | 48 | #define HPI_DEBUG_ASSERT(expression) \ |
55 | do { \ | 49 | do { \ |
56 | if (!(expression)) {\ | 50 | if (!(expression)) { \ |
57 | printk(KERN_ERR FILE_LINE\ | 51 | printk(KERN_ERR FILE_LINE \ |
58 | "ASSERT " __stringify(expression));\ | 52 | "ASSERT " __stringify(expression)); \ |
59 | HPI_DEBUGBREAK();\ | ||
60 | } \ | 53 | } \ |
61 | } while (0) | 54 | } while (0) |
62 | 55 | ||
@@ -78,28 +71,27 @@ void hpi_debug_message(struct hpi_message *phm, char *sz_fileline); | |||
78 | 71 | ||
79 | void hpi_debug_data(u16 *pdata, u32 len); | 72 | void hpi_debug_data(u16 *pdata, u32 len); |
80 | 73 | ||
81 | #define HPI_DEBUG_DATA(pdata, len) \ | 74 | #define HPI_DEBUG_DATA(pdata, len) \ |
82 | do { \ | 75 | do { \ |
83 | if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \ | 76 | if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \ |
84 | hpi_debug_data(pdata, len); \ | 77 | hpi_debug_data(pdata, len); \ |
85 | } while (0) | 78 | } while (0) |
86 | 79 | ||
87 | #define HPI_DEBUG_MESSAGE(level, phm) \ | 80 | #define HPI_DEBUG_MESSAGE(level, phm) \ |
88 | do { \ | 81 | do { \ |
89 | if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \ | 82 | if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \ |
90 | hpi_debug_message(phm,HPI_DEBUG_FLAG_##level \ | 83 | hpi_debug_message(phm, HPI_DEBUG_FLAG_##level \ |
91 | FILE_LINE __stringify(level));\ | 84 | FILE_LINE __stringify(level)); \ |
92 | } \ | 85 | } \ |
93 | } while (0) | 86 | } while (0) |
94 | 87 | ||
95 | #define HPI_DEBUG_RESPONSE(phr) \ | 88 | #define HPI_DEBUG_RESPONSE(phr) \ |
96 | do { \ | 89 | do { \ |
97 | if ((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && (phr->error))\ | 90 | if (((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && \ |
98 | HPI_DEBUG_LOG(ERROR, \ | 91 | (phr->error)) ||\ |
99 | "HPI response - error# %d\n", \ | 92 | (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)) \ |
100 | phr->error); \ | 93 | printk(KERN_DEBUG "HPI_RES%d,%d,%d\n", \ |
101 | else if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \ | 94 | phr->version, phr->error, phr->specific_error); \ |
102 | HPI_DEBUG_LOG(VERBOSE, "HPI response OK\n");\ | ||
103 | } while (0) | 95 | } while (0) |
104 | 96 | ||
105 | #ifndef compile_time_assert | 97 | #ifndef compile_time_assert |
@@ -107,279 +99,4 @@ void hpi_debug_data(u16 *pdata, u32 len); | |||
107 | typedef char msg[(cond) ? 1 : -1] | 99 | typedef char msg[(cond) ? 1 : -1] |
108 | #endif | 100 | #endif |
109 | 101 | ||
110 | /* check that size is exactly some number */ | 102 | #endif /* _HPIDEBUG_H_ */ |
111 | #define function_count_check(sym, size) \ | ||
112 | compile_time_assert((sym##_FUNCTION_COUNT) == (size),\ | ||
113 | strings_match_defs_##sym) | ||
114 | |||
115 | /* These strings should be generated using a macro which defines | ||
116 | the corresponding symbol values. */ | ||
117 | #define HPI_OBJ_STRINGS \ | ||
118 | { \ | ||
119 | "HPI_OBJ_SUBSYSTEM", \ | ||
120 | "HPI_OBJ_ADAPTER", \ | ||
121 | "HPI_OBJ_OSTREAM", \ | ||
122 | "HPI_OBJ_ISTREAM", \ | ||
123 | "HPI_OBJ_MIXER", \ | ||
124 | "HPI_OBJ_NODE", \ | ||
125 | "HPI_OBJ_CONTROL", \ | ||
126 | "HPI_OBJ_NVMEMORY", \ | ||
127 | "HPI_OBJ_DIGITALIO", \ | ||
128 | "HPI_OBJ_WATCHDOG", \ | ||
129 | "HPI_OBJ_CLOCK", \ | ||
130 | "HPI_OBJ_PROFILE", \ | ||
131 | "HPI_OBJ_CONTROLEX" \ | ||
132 | } | ||
133 | |||
134 | #define HPI_SUBSYS_STRINGS \ | ||
135 | { \ | ||
136 | "HPI_SUBSYS_OPEN", \ | ||
137 | "HPI_SUBSYS_GET_VERSION", \ | ||
138 | "HPI_SUBSYS_GET_INFO", \ | ||
139 | "HPI_SUBSYS_FIND_ADAPTERS", \ | ||
140 | "HPI_SUBSYS_CREATE_ADAPTER",\ | ||
141 | "HPI_SUBSYS_CLOSE", \ | ||
142 | "HPI_SUBSYS_DELETE_ADAPTER", \ | ||
143 | "HPI_SUBSYS_DRIVER_LOAD", \ | ||
144 | "HPI_SUBSYS_DRIVER_UNLOAD", \ | ||
145 | "HPI_SUBSYS_READ_PORT_8", \ | ||
146 | "HPI_SUBSYS_WRITE_PORT_8", \ | ||
147 | "HPI_SUBSYS_GET_NUM_ADAPTERS",\ | ||
148 | "HPI_SUBSYS_GET_ADAPTER", \ | ||
149 | "HPI_SUBSYS_SET_NETWORK_INTERFACE"\ | ||
150 | } | ||
151 | function_count_check(HPI_SUBSYS, 14); | ||
152 | |||
153 | #define HPI_ADAPTER_STRINGS \ | ||
154 | { \ | ||
155 | "HPI_ADAPTER_OPEN", \ | ||
156 | "HPI_ADAPTER_CLOSE", \ | ||
157 | "HPI_ADAPTER_GET_INFO", \ | ||
158 | "HPI_ADAPTER_GET_ASSERT", \ | ||
159 | "HPI_ADAPTER_TEST_ASSERT", \ | ||
160 | "HPI_ADAPTER_SET_MODE", \ | ||
161 | "HPI_ADAPTER_GET_MODE", \ | ||
162 | "HPI_ADAPTER_ENABLE_CAPABILITY",\ | ||
163 | "HPI_ADAPTER_SELFTEST", \ | ||
164 | "HPI_ADAPTER_FIND_OBJECT", \ | ||
165 | "HPI_ADAPTER_QUERY_FLASH", \ | ||
166 | "HPI_ADAPTER_START_FLASH", \ | ||
167 | "HPI_ADAPTER_PROGRAM_FLASH", \ | ||
168 | "HPI_ADAPTER_SET_PROPERTY", \ | ||
169 | "HPI_ADAPTER_GET_PROPERTY", \ | ||
170 | "HPI_ADAPTER_ENUM_PROPERTY", \ | ||
171 | "HPI_ADAPTER_MODULE_INFO", \ | ||
172 | "HPI_ADAPTER_DEBUG_READ" \ | ||
173 | } | ||
174 | |||
175 | function_count_check(HPI_ADAPTER, 18); | ||
176 | |||
177 | #define HPI_OSTREAM_STRINGS \ | ||
178 | { \ | ||
179 | "HPI_OSTREAM_OPEN", \ | ||
180 | "HPI_OSTREAM_CLOSE", \ | ||
181 | "HPI_OSTREAM_WRITE", \ | ||
182 | "HPI_OSTREAM_START", \ | ||
183 | "HPI_OSTREAM_STOP", \ | ||
184 | "HPI_OSTREAM_RESET", \ | ||
185 | "HPI_OSTREAM_GET_INFO", \ | ||
186 | "HPI_OSTREAM_QUERY_FORMAT", \ | ||
187 | "HPI_OSTREAM_DATA", \ | ||
188 | "HPI_OSTREAM_SET_VELOCITY", \ | ||
189 | "HPI_OSTREAM_SET_PUNCHINOUT", \ | ||
190 | "HPI_OSTREAM_SINEGEN", \ | ||
191 | "HPI_OSTREAM_ANC_RESET", \ | ||
192 | "HPI_OSTREAM_ANC_GET_INFO", \ | ||
193 | "HPI_OSTREAM_ANC_READ", \ | ||
194 | "HPI_OSTREAM_SET_TIMESCALE",\ | ||
195 | "HPI_OSTREAM_SET_FORMAT", \ | ||
196 | "HPI_OSTREAM_HOSTBUFFER_ALLOC", \ | ||
197 | "HPI_OSTREAM_HOSTBUFFER_FREE", \ | ||
198 | "HPI_OSTREAM_GROUP_ADD",\ | ||
199 | "HPI_OSTREAM_GROUP_GETMAP", \ | ||
200 | "HPI_OSTREAM_GROUP_RESET", \ | ||
201 | "HPI_OSTREAM_HOSTBUFFER_GET_INFO", \ | ||
202 | "HPI_OSTREAM_WAIT_START", \ | ||
203 | } | ||
204 | function_count_check(HPI_OSTREAM, 24); | ||
205 | |||
206 | #define HPI_ISTREAM_STRINGS \ | ||
207 | { \ | ||
208 | "HPI_ISTREAM_OPEN", \ | ||
209 | "HPI_ISTREAM_CLOSE", \ | ||
210 | "HPI_ISTREAM_SET_FORMAT", \ | ||
211 | "HPI_ISTREAM_READ", \ | ||
212 | "HPI_ISTREAM_START", \ | ||
213 | "HPI_ISTREAM_STOP", \ | ||
214 | "HPI_ISTREAM_RESET", \ | ||
215 | "HPI_ISTREAM_GET_INFO", \ | ||
216 | "HPI_ISTREAM_QUERY_FORMAT", \ | ||
217 | "HPI_ISTREAM_ANC_RESET", \ | ||
218 | "HPI_ISTREAM_ANC_GET_INFO", \ | ||
219 | "HPI_ISTREAM_ANC_WRITE", \ | ||
220 | "HPI_ISTREAM_HOSTBUFFER_ALLOC",\ | ||
221 | "HPI_ISTREAM_HOSTBUFFER_FREE", \ | ||
222 | "HPI_ISTREAM_GROUP_ADD", \ | ||
223 | "HPI_ISTREAM_GROUP_GETMAP", \ | ||
224 | "HPI_ISTREAM_GROUP_RESET", \ | ||
225 | "HPI_ISTREAM_HOSTBUFFER_GET_INFO", \ | ||
226 | "HPI_ISTREAM_WAIT_START", \ | ||
227 | } | ||
228 | function_count_check(HPI_ISTREAM, 19); | ||
229 | |||
230 | #define HPI_MIXER_STRINGS \ | ||
231 | { \ | ||
232 | "HPI_MIXER_OPEN", \ | ||
233 | "HPI_MIXER_CLOSE", \ | ||
234 | "HPI_MIXER_GET_INFO", \ | ||
235 | "HPI_MIXER_GET_NODE_INFO", \ | ||
236 | "HPI_MIXER_GET_CONTROL", \ | ||
237 | "HPI_MIXER_SET_CONNECTION", \ | ||
238 | "HPI_MIXER_GET_CONNECTIONS", \ | ||
239 | "HPI_MIXER_GET_CONTROL_BY_INDEX", \ | ||
240 | "HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX", \ | ||
241 | "HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES", \ | ||
242 | "HPI_MIXER_STORE", \ | ||
243 | } | ||
244 | function_count_check(HPI_MIXER, 11); | ||
245 | |||
246 | #define HPI_CONTROL_STRINGS \ | ||
247 | { \ | ||
248 | "HPI_CONTROL_GET_INFO", \ | ||
249 | "HPI_CONTROL_GET_STATE", \ | ||
250 | "HPI_CONTROL_SET_STATE" \ | ||
251 | } | ||
252 | function_count_check(HPI_CONTROL, 3); | ||
253 | |||
254 | #define HPI_NVMEMORY_STRINGS \ | ||
255 | { \ | ||
256 | "HPI_NVMEMORY_OPEN", \ | ||
257 | "HPI_NVMEMORY_READ_BYTE", \ | ||
258 | "HPI_NVMEMORY_WRITE_BYTE" \ | ||
259 | } | ||
260 | function_count_check(HPI_NVMEMORY, 3); | ||
261 | |||
262 | #define HPI_DIGITALIO_STRINGS \ | ||
263 | { \ | ||
264 | "HPI_GPIO_OPEN", \ | ||
265 | "HPI_GPIO_READ_BIT", \ | ||
266 | "HPI_GPIO_WRITE_BIT", \ | ||
267 | "HPI_GPIO_READ_ALL", \ | ||
268 | "HPI_GPIO_WRITE_STATUS"\ | ||
269 | } | ||
270 | function_count_check(HPI_GPIO, 5); | ||
271 | |||
272 | #define HPI_WATCHDOG_STRINGS \ | ||
273 | { \ | ||
274 | "HPI_WATCHDOG_OPEN", \ | ||
275 | "HPI_WATCHDOG_SET_TIME", \ | ||
276 | "HPI_WATCHDOG_PING" \ | ||
277 | } | ||
278 | |||
279 | #define HPI_CLOCK_STRINGS \ | ||
280 | { \ | ||
281 | "HPI_CLOCK_OPEN", \ | ||
282 | "HPI_CLOCK_SET_TIME", \ | ||
283 | "HPI_CLOCK_GET_TIME" \ | ||
284 | } | ||
285 | |||
286 | #define HPI_PROFILE_STRINGS \ | ||
287 | { \ | ||
288 | "HPI_PROFILE_OPEN_ALL", \ | ||
289 | "HPI_PROFILE_START_ALL", \ | ||
290 | "HPI_PROFILE_STOP_ALL", \ | ||
291 | "HPI_PROFILE_GET", \ | ||
292 | "HPI_PROFILE_GET_IDLECOUNT", \ | ||
293 | "HPI_PROFILE_GET_NAME", \ | ||
294 | "HPI_PROFILE_GET_UTILIZATION" \ | ||
295 | } | ||
296 | function_count_check(HPI_PROFILE, 7); | ||
297 | |||
298 | #define HPI_ASYNCEVENT_STRINGS \ | ||
299 | { \ | ||
300 | "HPI_ASYNCEVENT_OPEN",\ | ||
301 | "HPI_ASYNCEVENT_CLOSE ",\ | ||
302 | "HPI_ASYNCEVENT_WAIT",\ | ||
303 | "HPI_ASYNCEVENT_GETCOUNT",\ | ||
304 | "HPI_ASYNCEVENT_GET",\ | ||
305 | "HPI_ASYNCEVENT_SENDEVENTS"\ | ||
306 | } | ||
307 | function_count_check(HPI_ASYNCEVENT, 6); | ||
308 | |||
309 | #define HPI_CONTROL_TYPE_STRINGS \ | ||
310 | { \ | ||
311 | "null control", \ | ||
312 | "HPI_CONTROL_CONNECTION", \ | ||
313 | "HPI_CONTROL_VOLUME", \ | ||
314 | "HPI_CONTROL_METER", \ | ||
315 | "HPI_CONTROL_MUTE", \ | ||
316 | "HPI_CONTROL_MULTIPLEXER", \ | ||
317 | "HPI_CONTROL_AESEBU_TRANSMITTER", \ | ||
318 | "HPI_CONTROL_AESEBU_RECEIVER", \ | ||
319 | "HPI_CONTROL_LEVEL", \ | ||
320 | "HPI_CONTROL_TUNER", \ | ||
321 | "HPI_CONTROL_ONOFFSWITCH", \ | ||
322 | "HPI_CONTROL_VOX", \ | ||
323 | "HPI_CONTROL_AES18_TRANSMITTER", \ | ||
324 | "HPI_CONTROL_AES18_RECEIVER", \ | ||
325 | "HPI_CONTROL_AES18_BLOCKGENERATOR", \ | ||
326 | "HPI_CONTROL_CHANNEL_MODE", \ | ||
327 | "HPI_CONTROL_BITSTREAM", \ | ||
328 | "HPI_CONTROL_SAMPLECLOCK", \ | ||
329 | "HPI_CONTROL_MICROPHONE", \ | ||
330 | "HPI_CONTROL_PARAMETRIC_EQ", \ | ||
331 | "HPI_CONTROL_COMPANDER", \ | ||
332 | "HPI_CONTROL_COBRANET", \ | ||
333 | "HPI_CONTROL_TONE_DETECT", \ | ||
334 | "HPI_CONTROL_SILENCE_DETECT", \ | ||
335 | "HPI_CONTROL_PAD", \ | ||
336 | "HPI_CONTROL_SRC" ,\ | ||
337 | "HPI_CONTROL_UNIVERSAL" \ | ||
338 | } | ||
339 | |||
340 | compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27), | ||
341 | controltype_strings_match_defs); | ||
342 | |||
343 | #define HPI_SOURCENODE_STRINGS \ | ||
344 | { \ | ||
345 | "no source", \ | ||
346 | "HPI_SOURCENODE_OSTREAM", \ | ||
347 | "HPI_SOURCENODE_LINEIN", \ | ||
348 | "HPI_SOURCENODE_AESEBU_IN", \ | ||
349 | "HPI_SOURCENODE_TUNER", \ | ||
350 | "HPI_SOURCENODE_RF", \ | ||
351 | "HPI_SOURCENODE_CLOCK_SOURCE", \ | ||
352 | "HPI_SOURCENODE_RAW_BITSTREAM", \ | ||
353 | "HPI_SOURCENODE_MICROPHONE", \ | ||
354 | "HPI_SOURCENODE_COBRANET", \ | ||
355 | "HPI_SOURCENODE_ANALOG", \ | ||
356 | "HPI_SOURCENODE_ADAPTER" \ | ||
357 | } | ||
358 | |||
359 | compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_NONE + 1) == | ||
360 | (12), sourcenode_strings_match_defs); | ||
361 | |||
362 | #define HPI_DESTNODE_STRINGS \ | ||
363 | { \ | ||
364 | "no destination", \ | ||
365 | "HPI_DESTNODE_ISTREAM", \ | ||
366 | "HPI_DESTNODE_LINEOUT", \ | ||
367 | "HPI_DESTNODE_AESEBU_OUT", \ | ||
368 | "HPI_DESTNODE_RF", \ | ||
369 | "HPI_DESTNODE_SPEAKER", \ | ||
370 | "HPI_DESTNODE_COBRANET", \ | ||
371 | "HPI_DESTNODE_ANALOG" \ | ||
372 | } | ||
373 | compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_NONE + 1) == (8), | ||
374 | destnode_strings_match_defs); | ||
375 | |||
376 | #define HPI_CONTROL_CHANNEL_MODE_STRINGS \ | ||
377 | { \ | ||
378 | "XXX HPI_CHANNEL_MODE_ERROR XXX", \ | ||
379 | "HPI_CHANNEL_MODE_NORMAL", \ | ||
380 | "HPI_CHANNEL_MODE_SWAP", \ | ||
381 | "HPI_CHANNEL_MODE_LEFT_ONLY", \ | ||
382 | "HPI_CHANNEL_MODE_RIGHT_ONLY" \ | ||
383 | } | ||
384 | |||
385 | #endif /* _HPIDEBUG_H */ | ||
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c index 9b10d9a5c255..fb311d8c05bf 100644 --- a/sound/pci/asihpi/hpidspcd.c +++ b/sound/pci/asihpi/hpidspcd.c | |||
@@ -71,47 +71,50 @@ short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code, | |||
71 | int err; | 71 | int err; |
72 | 72 | ||
73 | sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); | 73 | sprintf(fw_name, "asihpi/dsp%04x.bin", adapter); |
74 | HPI_DEBUG_LOG(INFO, "requesting firmware for %s\n", fw_name); | ||
75 | 74 | ||
76 | err = request_firmware(&ps_firmware, fw_name, | 75 | err = request_firmware(&ps_firmware, fw_name, |
77 | &ps_dsp_code->ps_dev->dev); | 76 | &ps_dsp_code->ps_dev->dev); |
77 | |||
78 | if (err != 0) { | 78 | if (err != 0) { |
79 | HPI_DEBUG_LOG(ERROR, "%d, request_firmware failed for %s\n", | 79 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, |
80 | err, fw_name); | 80 | "%d, request_firmware failed for %s\n", err, |
81 | fw_name); | ||
81 | goto error1; | 82 | goto error1; |
82 | } | 83 | } |
83 | if (ps_firmware->size < sizeof(header)) { | 84 | if (ps_firmware->size < sizeof(header)) { |
84 | HPI_DEBUG_LOG(ERROR, "header size too small %s\n", fw_name); | 85 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, |
86 | "Header size too small %s\n", fw_name); | ||
85 | goto error2; | 87 | goto error2; |
86 | } | 88 | } |
87 | memcpy(&header, ps_firmware->data, sizeof(header)); | 89 | memcpy(&header, ps_firmware->data, sizeof(header)); |
88 | if (header.adapter != adapter) { | 90 | if (header.adapter != adapter) { |
89 | HPI_DEBUG_LOG(ERROR, "adapter type incorrect %4x != %4x\n", | 91 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, |
90 | header.adapter, adapter); | 92 | "Adapter type incorrect %4x != %4x\n", header.adapter, |
93 | adapter); | ||
91 | goto error2; | 94 | goto error2; |
92 | } | 95 | } |
93 | if (header.size != ps_firmware->size) { | 96 | if (header.size != ps_firmware->size) { |
94 | HPI_DEBUG_LOG(ERROR, "code size wrong %d != %ld\n", | 97 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, |
95 | header.size, (unsigned long)ps_firmware->size); | 98 | "Code size wrong %d != %ld\n", header.size, |
99 | (unsigned long)ps_firmware->size); | ||
96 | goto error2; | 100 | goto error2; |
97 | } | 101 | } |
98 | 102 | ||
99 | if (header.version / 10000 != HPI_VER_DECIMAL / 10000) { | 103 | if (header.version / 100 != HPI_VER_DECIMAL / 100) { |
100 | HPI_DEBUG_LOG(ERROR, | 104 | dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev, |
101 | "firmware major version mismatch " | 105 | "Incompatible firmware version " |
102 | "DSP image %d != driver %d\n", header.version, | 106 | "DSP image %d != Driver %d\n", header.version, |
103 | HPI_VER_DECIMAL); | 107 | HPI_VER_DECIMAL); |
104 | goto error2; | 108 | goto error2; |
105 | } | 109 | } |
106 | 110 | ||
107 | if (header.version != HPI_VER_DECIMAL) { | 111 | if (header.version != HPI_VER_DECIMAL) { |
108 | HPI_DEBUG_LOG(WARNING, | 112 | dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev, |
109 | "version mismatch DSP image %d != driver %d\n", | 113 | "Firmware: release version mismatch DSP image %d != Driver %d\n", |
110 | header.version, HPI_VER_DECIMAL); | 114 | header.version, HPI_VER_DECIMAL); |
111 | /* goto error2; still allow driver to load */ | ||
112 | } | 115 | } |
113 | 116 | ||
114 | HPI_DEBUG_LOG(INFO, "dsp code %s opened\n", fw_name); | 117 | HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name); |
115 | ps_dsp_code->ps_firmware = ps_firmware; | 118 | ps_dsp_code->ps_firmware = ps_firmware; |
116 | ps_dsp_code->block_length = header.size / sizeof(u32); | 119 | ps_dsp_code->block_length = header.size / sizeof(u32); |
117 | ps_dsp_code->word_count = sizeof(header) / sizeof(u32); | 120 | ps_dsp_code->word_count = sizeof(header) / sizeof(u32); |
@@ -148,7 +151,7 @@ void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code) | |||
148 | short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword) | 151 | short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword) |
149 | { | 152 | { |
150 | if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length) | 153 | if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length) |
151 | return (HPI_ERROR_DSP_FILE_FORMAT); | 154 | return HPI_ERROR_DSP_FILE_FORMAT; |
152 | 155 | ||
153 | *pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code-> | 156 | *pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code-> |
154 | word_count]; | 157 | word_count]; |
diff --git a/sound/pci/asihpi/hpidspcd.h b/sound/pci/asihpi/hpidspcd.h index d7c240398225..65f0ca732704 100644 --- a/sound/pci/asihpi/hpidspcd.h +++ b/sound/pci/asihpi/hpidspcd.h | |||
@@ -87,7 +87,7 @@ void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code); | |||
87 | */ | 87 | */ |
88 | short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, | 88 | short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, |
89 | /**< DSP code descriptor */ | 89 | /**< DSP code descriptor */ |
90 | u32 *pword /**< where to store the read word */ | 90 | u32 *pword /**< Where to store the read word */ |
91 | ); | 91 | ); |
92 | 92 | ||
93 | /** Get a block of dsp code into an internal buffer, and provide a pointer to | 93 | /** Get a block of dsp code into an internal buffer, and provide a pointer to |
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c index 1e92eb6dd509..c38fc9487560 100644 --- a/sound/pci/asihpi/hpifunc.c +++ b/sound/pci/asihpi/hpifunc.c | |||
@@ -30,16 +30,25 @@ u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index, | |||
30 | return handle.w; | 30 | return handle.w; |
31 | } | 31 | } |
32 | 32 | ||
33 | void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index, | 33 | static u16 hpi_handle_indexes(const u32 h, u16 *p1, u16 *p2) |
34 | u16 *pw_object_index) | ||
35 | { | 34 | { |
36 | union handle_word uhandle; | 35 | union handle_word uhandle; |
37 | uhandle.w = handle; | 36 | if (!h) |
37 | return HPI_ERROR_INVALID_HANDLE; | ||
38 | |||
39 | uhandle.w = h; | ||
40 | |||
41 | *p1 = (u16)uhandle.h.adapter_index; | ||
42 | if (p2) | ||
43 | *p2 = (u16)uhandle.h.obj_index; | ||
38 | 44 | ||
39 | if (pw_adapter_index) | 45 | return 0; |
40 | *pw_adapter_index = (u16)uhandle.h.adapter_index; | 46 | } |
41 | if (pw_object_index) | 47 | |
42 | *pw_object_index = (u16)uhandle.h.obj_index; | 48 | void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index, |
49 | u16 *pw_object_index) | ||
50 | { | ||
51 | hpi_handle_indexes(handle, pw_adapter_index, pw_object_index); | ||
43 | } | 52 | } |
44 | 53 | ||
45 | char hpi_handle_object(const u32 handle) | 54 | char hpi_handle_object(const u32 handle) |
@@ -49,22 +58,6 @@ char hpi_handle_object(const u32 handle) | |||
49 | return (char)uhandle.h.obj_type; | 58 | return (char)uhandle.h.obj_type; |
50 | } | 59 | } |
51 | 60 | ||
52 | #define u32TOINDEX(h, i1) \ | ||
53 | do {\ | ||
54 | if (h == 0) \ | ||
55 | return HPI_ERROR_INVALID_OBJ; \ | ||
56 | else \ | ||
57 | hpi_handle_to_indexes(h, i1, NULL); \ | ||
58 | } while (0) | ||
59 | |||
60 | #define u32TOINDEXES(h, i1, i2) \ | ||
61 | do {\ | ||
62 | if (h == 0) \ | ||
63 | return HPI_ERROR_INVALID_OBJ; \ | ||
64 | else \ | ||
65 | hpi_handle_to_indexes(h, i1, i2);\ | ||
66 | } while (0) | ||
67 | |||
68 | void hpi_format_to_msg(struct hpi_msg_format *pMF, | 61 | void hpi_format_to_msg(struct hpi_msg_format *pMF, |
69 | const struct hpi_format *pF) | 62 | const struct hpi_format *pF) |
70 | { | 63 | { |
@@ -94,52 +87,13 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR) | |||
94 | pSR->u.legacy_stream_info.state = pSR->u.stream_info.state; | 87 | pSR->u.legacy_stream_info.state = pSR->u.stream_info.state; |
95 | } | 88 | } |
96 | 89 | ||
97 | static struct hpi_hsubsys gh_subsys; | 90 | static inline void hpi_send_recvV1(struct hpi_message_header *m, |
98 | 91 | struct hpi_response_header *r) | |
99 | struct hpi_hsubsys *hpi_subsys_create(void) | ||
100 | { | 92 | { |
101 | struct hpi_message hm; | 93 | hpi_send_recv((struct hpi_message *)m, (struct hpi_response *)r); |
102 | struct hpi_response hr; | ||
103 | |||
104 | memset(&gh_subsys, 0, sizeof(struct hpi_hsubsys)); | ||
105 | |||
106 | { | ||
107 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
108 | HPI_SUBSYS_OPEN); | ||
109 | hpi_send_recv(&hm, &hr); | ||
110 | |||
111 | if (hr.error == 0) | ||
112 | return &gh_subsys; | ||
113 | |||
114 | } | ||
115 | return NULL; | ||
116 | } | ||
117 | |||
118 | void hpi_subsys_free(const struct hpi_hsubsys *ph_subsys) | ||
119 | { | ||
120 | struct hpi_message hm; | ||
121 | struct hpi_response hr; | ||
122 | |||
123 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
124 | HPI_SUBSYS_CLOSE); | ||
125 | hpi_send_recv(&hm, &hr); | ||
126 | |||
127 | } | 94 | } |
128 | 95 | ||
129 | u16 hpi_subsys_get_version(const struct hpi_hsubsys *ph_subsys, u32 *pversion) | 96 | u16 hpi_subsys_get_version_ex(u32 *pversion_ex) |
130 | { | ||
131 | struct hpi_message hm; | ||
132 | struct hpi_response hr; | ||
133 | |||
134 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
135 | HPI_SUBSYS_GET_VERSION); | ||
136 | hpi_send_recv(&hm, &hr); | ||
137 | *pversion = hr.u.s.version; | ||
138 | return hr.error; | ||
139 | } | ||
140 | |||
141 | u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys, | ||
142 | u32 *pversion_ex) | ||
143 | { | 97 | { |
144 | struct hpi_message hm; | 98 | struct hpi_message hm; |
145 | struct hpi_response hr; | 99 | struct hpi_response hr; |
@@ -151,51 +105,8 @@ u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys, | |||
151 | return hr.error; | 105 | return hr.error; |
152 | } | 106 | } |
153 | 107 | ||
154 | u16 hpi_subsys_get_info(const struct hpi_hsubsys *ph_subsys, u32 *pversion, | 108 | u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource, |
155 | u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length) | 109 | u16 *pw_adapter_index) |
156 | { | ||
157 | struct hpi_message hm; | ||
158 | struct hpi_response hr; | ||
159 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
160 | HPI_SUBSYS_GET_INFO); | ||
161 | |||
162 | hpi_send_recv(&hm, &hr); | ||
163 | |||
164 | *pversion = hr.u.s.version; | ||
165 | if (list_length > HPI_MAX_ADAPTERS) | ||
166 | memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list, | ||
167 | HPI_MAX_ADAPTERS); | ||
168 | else | ||
169 | memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list, list_length); | ||
170 | *pw_num_adapters = hr.u.s.num_adapters; | ||
171 | return hr.error; | ||
172 | } | ||
173 | |||
174 | u16 hpi_subsys_find_adapters(const struct hpi_hsubsys *ph_subsys, | ||
175 | u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length) | ||
176 | { | ||
177 | struct hpi_message hm; | ||
178 | struct hpi_response hr; | ||
179 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
180 | HPI_SUBSYS_FIND_ADAPTERS); | ||
181 | |||
182 | hpi_send_recv(&hm, &hr); | ||
183 | |||
184 | if (list_length > HPI_MAX_ADAPTERS) { | ||
185 | memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list, | ||
186 | HPI_MAX_ADAPTERS * sizeof(u16)); | ||
187 | memset(&aw_adapter_list[HPI_MAX_ADAPTERS], 0, | ||
188 | (list_length - HPI_MAX_ADAPTERS) * sizeof(u16)); | ||
189 | } else | ||
190 | memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list, | ||
191 | list_length * sizeof(u16)); | ||
192 | *pw_num_adapters = hr.u.s.num_adapters; | ||
193 | |||
194 | return hr.error; | ||
195 | } | ||
196 | |||
197 | u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys, | ||
198 | const struct hpi_resource *p_resource, u16 *pw_adapter_index) | ||
199 | { | 110 | { |
200 | struct hpi_message hm; | 111 | struct hpi_message hm; |
201 | struct hpi_response hr; | 112 | struct hpi_response hr; |
@@ -210,20 +121,18 @@ u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys, | |||
210 | return hr.error; | 121 | return hr.error; |
211 | } | 122 | } |
212 | 123 | ||
213 | u16 hpi_subsys_delete_adapter(const struct hpi_hsubsys *ph_subsys, | 124 | u16 hpi_subsys_delete_adapter(u16 adapter_index) |
214 | u16 adapter_index) | ||
215 | { | 125 | { |
216 | struct hpi_message hm; | 126 | struct hpi_message hm; |
217 | struct hpi_response hr; | 127 | struct hpi_response hr; |
218 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | 128 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, |
219 | HPI_SUBSYS_DELETE_ADAPTER); | 129 | HPI_SUBSYS_DELETE_ADAPTER); |
220 | hm.adapter_index = adapter_index; | 130 | hm.obj_index = adapter_index; |
221 | hpi_send_recv(&hm, &hr); | 131 | hpi_send_recv(&hm, &hr); |
222 | return hr.error; | 132 | return hr.error; |
223 | } | 133 | } |
224 | 134 | ||
225 | u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys, | 135 | u16 hpi_subsys_get_num_adapters(int *pn_num_adapters) |
226 | int *pn_num_adapters) | ||
227 | { | 136 | { |
228 | struct hpi_message hm; | 137 | struct hpi_message hm; |
229 | struct hpi_response hr; | 138 | struct hpi_response hr; |
@@ -234,35 +143,22 @@ u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys, | |||
234 | return hr.error; | 143 | return hr.error; |
235 | } | 144 | } |
236 | 145 | ||
237 | u16 hpi_subsys_get_adapter(const struct hpi_hsubsys *ph_subsys, int iterator, | 146 | u16 hpi_subsys_get_adapter(int iterator, u32 *padapter_index, |
238 | u32 *padapter_index, u16 *pw_adapter_type) | 147 | u16 *pw_adapter_type) |
239 | { | 148 | { |
240 | struct hpi_message hm; | 149 | struct hpi_message hm; |
241 | struct hpi_response hr; | 150 | struct hpi_response hr; |
242 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | 151 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, |
243 | HPI_SUBSYS_GET_ADAPTER); | 152 | HPI_SUBSYS_GET_ADAPTER); |
244 | hm.adapter_index = (u16)iterator; | 153 | hm.obj_index = (u16)iterator; |
245 | hpi_send_recv(&hm, &hr); | 154 | hpi_send_recv(&hm, &hr); |
246 | *padapter_index = (int)hr.u.s.adapter_index; | 155 | *padapter_index = (int)hr.u.s.adapter_index; |
247 | *pw_adapter_type = hr.u.s.aw_adapter_list[0]; | 156 | *pw_adapter_type = hr.u.s.adapter_type; |
248 | return hr.error; | ||
249 | } | ||
250 | 157 | ||
251 | u16 hpi_subsys_set_host_network_interface(const struct hpi_hsubsys *ph_subsys, | ||
252 | const char *sz_interface) | ||
253 | { | ||
254 | struct hpi_message hm; | ||
255 | struct hpi_response hr; | ||
256 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | ||
257 | HPI_SUBSYS_SET_NETWORK_INTERFACE); | ||
258 | if (sz_interface == NULL) | ||
259 | return HPI_ERROR_INVALID_RESOURCE; | ||
260 | hm.u.s.resource.r.net_if = sz_interface; | ||
261 | hpi_send_recv(&hm, &hr); | ||
262 | return hr.error; | 158 | return hr.error; |
263 | } | 159 | } |
264 | 160 | ||
265 | u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index) | 161 | u16 hpi_adapter_open(u16 adapter_index) |
266 | { | 162 | { |
267 | struct hpi_message hm; | 163 | struct hpi_message hm; |
268 | struct hpi_response hr; | 164 | struct hpi_response hr; |
@@ -276,7 +172,7 @@ u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index) | |||
276 | 172 | ||
277 | } | 173 | } |
278 | 174 | ||
279 | u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index) | 175 | u16 hpi_adapter_close(u16 adapter_index) |
280 | { | 176 | { |
281 | struct hpi_message hm; | 177 | struct hpi_message hm; |
282 | struct hpi_response hr; | 178 | struct hpi_response hr; |
@@ -289,15 +185,14 @@ u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index) | |||
289 | return hr.error; | 185 | return hr.error; |
290 | } | 186 | } |
291 | 187 | ||
292 | u16 hpi_adapter_set_mode(const struct hpi_hsubsys *ph_subsys, | 188 | u16 hpi_adapter_set_mode(u16 adapter_index, u32 adapter_mode) |
293 | u16 adapter_index, u32 adapter_mode) | ||
294 | { | 189 | { |
295 | return hpi_adapter_set_mode_ex(ph_subsys, adapter_index, adapter_mode, | 190 | return hpi_adapter_set_mode_ex(adapter_index, adapter_mode, |
296 | HPI_ADAPTER_MODE_SET); | 191 | HPI_ADAPTER_MODE_SET); |
297 | } | 192 | } |
298 | 193 | ||
299 | u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys, | 194 | u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode, |
300 | u16 adapter_index, u32 adapter_mode, u16 query_or_set) | 195 | u16 query_or_set) |
301 | { | 196 | { |
302 | struct hpi_message hm; | 197 | struct hpi_message hm; |
303 | struct hpi_response hr; | 198 | struct hpi_response hr; |
@@ -305,14 +200,13 @@ u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys, | |||
305 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | 200 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, |
306 | HPI_ADAPTER_SET_MODE); | 201 | HPI_ADAPTER_SET_MODE); |
307 | hm.adapter_index = adapter_index; | 202 | hm.adapter_index = adapter_index; |
308 | hm.u.a.adapter_mode = adapter_mode; | 203 | hm.u.ax.mode.adapter_mode = adapter_mode; |
309 | hm.u.a.assert_id = query_or_set; | 204 | hm.u.ax.mode.query_or_set = query_or_set; |
310 | hpi_send_recv(&hm, &hr); | 205 | hpi_send_recv(&hm, &hr); |
311 | return hr.error; | 206 | return hr.error; |
312 | } | 207 | } |
313 | 208 | ||
314 | u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys, | 209 | u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode) |
315 | u16 adapter_index, u32 *padapter_mode) | ||
316 | { | 210 | { |
317 | struct hpi_message hm; | 211 | struct hpi_message hm; |
318 | struct hpi_response hr; | 212 | struct hpi_response hr; |
@@ -321,13 +215,13 @@ u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys, | |||
321 | hm.adapter_index = adapter_index; | 215 | hm.adapter_index = adapter_index; |
322 | hpi_send_recv(&hm, &hr); | 216 | hpi_send_recv(&hm, &hr); |
323 | if (padapter_mode) | 217 | if (padapter_mode) |
324 | *padapter_mode = hr.u.a.serial_number; | 218 | *padapter_mode = hr.u.ax.mode.adapter_mode; |
325 | return hr.error; | 219 | return hr.error; |
326 | } | 220 | } |
327 | 221 | ||
328 | u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys, | 222 | u16 hpi_adapter_get_info(u16 adapter_index, u16 *pw_num_outstreams, |
329 | u16 adapter_index, u16 *pw_num_outstreams, u16 *pw_num_instreams, | 223 | u16 *pw_num_instreams, u16 *pw_version, u32 *pserial_number, |
330 | u16 *pw_version, u32 *pserial_number, u16 *pw_adapter_type) | 224 | u16 *pw_adapter_type) |
331 | { | 225 | { |
332 | struct hpi_message hm; | 226 | struct hpi_message hm; |
333 | struct hpi_response hr; | 227 | struct hpi_response hr; |
@@ -337,18 +231,17 @@ u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys, | |||
337 | 231 | ||
338 | hpi_send_recv(&hm, &hr); | 232 | hpi_send_recv(&hm, &hr); |
339 | 233 | ||
340 | *pw_adapter_type = hr.u.a.adapter_type; | 234 | *pw_adapter_type = hr.u.ax.info.adapter_type; |
341 | *pw_num_outstreams = hr.u.a.num_outstreams; | 235 | *pw_num_outstreams = hr.u.ax.info.num_outstreams; |
342 | *pw_num_instreams = hr.u.a.num_instreams; | 236 | *pw_num_instreams = hr.u.ax.info.num_instreams; |
343 | *pw_version = hr.u.a.version; | 237 | *pw_version = hr.u.ax.info.version; |
344 | *pserial_number = hr.u.a.serial_number; | 238 | *pserial_number = hr.u.ax.info.serial_number; |
345 | return hr.error; | 239 | return hr.error; |
346 | } | 240 | } |
347 | 241 | ||
348 | u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys, | 242 | u16 hpi_adapter_get_module_by_index(u16 adapter_index, u16 module_index, |
349 | u16 adapter_index, u16 module_index, u16 *pw_num_outputs, | 243 | u16 *pw_num_outputs, u16 *pw_num_inputs, u16 *pw_version, |
350 | u16 *pw_num_inputs, u16 *pw_version, u32 *pserial_number, | 244 | u32 *pserial_number, u16 *pw_module_type, u32 *ph_module) |
351 | u16 *pw_module_type, u32 *ph_module) | ||
352 | { | 245 | { |
353 | struct hpi_message hm; | 246 | struct hpi_message hm; |
354 | struct hpi_response hr; | 247 | struct hpi_response hr; |
@@ -360,173 +253,18 @@ u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys, | |||
360 | 253 | ||
361 | hpi_send_recv(&hm, &hr); | 254 | hpi_send_recv(&hm, &hr); |
362 | 255 | ||
363 | *pw_module_type = hr.u.a.adapter_type; | 256 | *pw_module_type = hr.u.ax.info.adapter_type; |
364 | *pw_num_outputs = hr.u.a.num_outstreams; | 257 | *pw_num_outputs = hr.u.ax.info.num_outstreams; |
365 | *pw_num_inputs = hr.u.a.num_instreams; | 258 | *pw_num_inputs = hr.u.ax.info.num_instreams; |
366 | *pw_version = hr.u.a.version; | 259 | *pw_version = hr.u.ax.info.version; |
367 | *pserial_number = hr.u.a.serial_number; | 260 | *pserial_number = hr.u.ax.info.serial_number; |
368 | *ph_module = 0; | 261 | *ph_module = 0; |
369 | 262 | ||
370 | return hr.error; | 263 | return hr.error; |
371 | } | 264 | } |
372 | 265 | ||
373 | u16 hpi_adapter_get_assert(const struct hpi_hsubsys *ph_subsys, | 266 | u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 parameter1, |
374 | u16 adapter_index, u16 *assert_present, char *psz_assert, | 267 | u16 parameter2) |
375 | u16 *pw_line_number) | ||
376 | { | ||
377 | struct hpi_message hm; | ||
378 | struct hpi_response hr; | ||
379 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
380 | HPI_ADAPTER_GET_ASSERT); | ||
381 | hm.adapter_index = adapter_index; | ||
382 | hpi_send_recv(&hm, &hr); | ||
383 | |||
384 | *assert_present = 0; | ||
385 | |||
386 | if (!hr.error) { | ||
387 | |||
388 | *pw_line_number = (u16)hr.u.a.serial_number; | ||
389 | if (*pw_line_number) { | ||
390 | |||
391 | int i; | ||
392 | char *src = (char *)hr.u.a.sz_adapter_assert; | ||
393 | char *dst = psz_assert; | ||
394 | |||
395 | *assert_present = 1; | ||
396 | |||
397 | for (i = 0; i < HPI_STRING_LEN; i++) { | ||
398 | char c; | ||
399 | c = *src++; | ||
400 | *dst++ = c; | ||
401 | if (c == 0) | ||
402 | break; | ||
403 | } | ||
404 | |||
405 | } | ||
406 | } | ||
407 | return hr.error; | ||
408 | } | ||
409 | |||
410 | u16 hpi_adapter_get_assert_ex(const struct hpi_hsubsys *ph_subsys, | ||
411 | u16 adapter_index, u16 *assert_present, char *psz_assert, | ||
412 | u32 *pline_number, u16 *pw_assert_on_dsp) | ||
413 | { | ||
414 | struct hpi_message hm; | ||
415 | struct hpi_response hr; | ||
416 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
417 | HPI_ADAPTER_GET_ASSERT); | ||
418 | hm.adapter_index = adapter_index; | ||
419 | |||
420 | hpi_send_recv(&hm, &hr); | ||
421 | |||
422 | *assert_present = 0; | ||
423 | |||
424 | if (!hr.error) { | ||
425 | |||
426 | *pline_number = hr.u.a.serial_number; | ||
427 | |||
428 | *assert_present = hr.u.a.adapter_type; | ||
429 | |||
430 | *pw_assert_on_dsp = hr.u.a.adapter_index; | ||
431 | |||
432 | if (!*assert_present && *pline_number) | ||
433 | |||
434 | *assert_present = 1; | ||
435 | |||
436 | if (*assert_present) { | ||
437 | |||
438 | int i; | ||
439 | char *src = (char *)hr.u.a.sz_adapter_assert; | ||
440 | char *dst = psz_assert; | ||
441 | |||
442 | for (i = 0; i < HPI_STRING_LEN; i++) { | ||
443 | char c; | ||
444 | c = *src++; | ||
445 | *dst++ = c; | ||
446 | if (c == 0) | ||
447 | break; | ||
448 | } | ||
449 | |||
450 | } else { | ||
451 | *psz_assert = 0; | ||
452 | } | ||
453 | } | ||
454 | return hr.error; | ||
455 | } | ||
456 | |||
457 | u16 hpi_adapter_test_assert(const struct hpi_hsubsys *ph_subsys, | ||
458 | u16 adapter_index, u16 assert_id) | ||
459 | { | ||
460 | struct hpi_message hm; | ||
461 | struct hpi_response hr; | ||
462 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
463 | HPI_ADAPTER_TEST_ASSERT); | ||
464 | hm.adapter_index = adapter_index; | ||
465 | hm.u.a.assert_id = assert_id; | ||
466 | |||
467 | hpi_send_recv(&hm, &hr); | ||
468 | |||
469 | return hr.error; | ||
470 | } | ||
471 | |||
472 | u16 hpi_adapter_enable_capability(const struct hpi_hsubsys *ph_subsys, | ||
473 | u16 adapter_index, u16 capability, u32 key) | ||
474 | { | ||
475 | struct hpi_message hm; | ||
476 | struct hpi_response hr; | ||
477 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
478 | HPI_ADAPTER_ENABLE_CAPABILITY); | ||
479 | hm.adapter_index = adapter_index; | ||
480 | hm.u.a.assert_id = capability; | ||
481 | hm.u.a.adapter_mode = key; | ||
482 | |||
483 | hpi_send_recv(&hm, &hr); | ||
484 | |||
485 | return hr.error; | ||
486 | } | ||
487 | |||
488 | u16 hpi_adapter_self_test(const struct hpi_hsubsys *ph_subsys, | ||
489 | u16 adapter_index) | ||
490 | { | ||
491 | struct hpi_message hm; | ||
492 | struct hpi_response hr; | ||
493 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
494 | HPI_ADAPTER_SELFTEST); | ||
495 | hm.adapter_index = adapter_index; | ||
496 | hpi_send_recv(&hm, &hr); | ||
497 | return hr.error; | ||
498 | } | ||
499 | |||
500 | u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys, | ||
501 | u16 adapter_index, u32 dsp_address, char *p_buffer, int *count_bytes) | ||
502 | { | ||
503 | struct hpi_message hm; | ||
504 | struct hpi_response hr; | ||
505 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | ||
506 | HPI_ADAPTER_DEBUG_READ); | ||
507 | |||
508 | hr.size = sizeof(hr); | ||
509 | |||
510 | hm.adapter_index = adapter_index; | ||
511 | hm.u.ax.debug_read.dsp_address = dsp_address; | ||
512 | |||
513 | if (*count_bytes > (int)sizeof(hr.u.bytes)) | ||
514 | *count_bytes = sizeof(hr.u.bytes); | ||
515 | |||
516 | hm.u.ax.debug_read.count_bytes = *count_bytes; | ||
517 | |||
518 | hpi_send_recv(&hm, &hr); | ||
519 | |||
520 | if (!hr.error) { | ||
521 | *count_bytes = hr.size - 12; | ||
522 | memcpy(p_buffer, &hr.u.bytes, *count_bytes); | ||
523 | } else | ||
524 | *count_bytes = 0; | ||
525 | return hr.error; | ||
526 | } | ||
527 | |||
528 | u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys, | ||
529 | u16 adapter_index, u16 property, u16 parameter1, u16 parameter2) | ||
530 | { | 268 | { |
531 | struct hpi_message hm; | 269 | struct hpi_message hm; |
532 | struct hpi_response hr; | 270 | struct hpi_response hr; |
@@ -542,9 +280,8 @@ u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys, | |||
542 | return hr.error; | 280 | return hr.error; |
543 | } | 281 | } |
544 | 282 | ||
545 | u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys, | 283 | u16 hpi_adapter_get_property(u16 adapter_index, u16 property, |
546 | u16 adapter_index, u16 property, u16 *pw_parameter1, | 284 | u16 *pw_parameter1, u16 *pw_parameter2) |
547 | u16 *pw_parameter2) | ||
548 | { | 285 | { |
549 | struct hpi_message hm; | 286 | struct hpi_message hm; |
550 | struct hpi_response hr; | 287 | struct hpi_response hr; |
@@ -564,9 +301,8 @@ u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys, | |||
564 | return hr.error; | 301 | return hr.error; |
565 | } | 302 | } |
566 | 303 | ||
567 | u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys, | 304 | u16 hpi_adapter_enumerate_property(u16 adapter_index, u16 index, |
568 | u16 adapter_index, u16 index, u16 what_to_enumerate, | 305 | u16 what_to_enumerate, u16 property_index, u32 *psetting) |
569 | u16 property_index, u32 *psetting) | ||
570 | { | 306 | { |
571 | return 0; | 307 | return 0; |
572 | } | 308 | } |
@@ -574,7 +310,7 @@ u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys, | |||
574 | u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, | 310 | u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, |
575 | u32 sample_rate, u32 bit_rate, u32 attributes) | 311 | u32 sample_rate, u32 bit_rate, u32 attributes) |
576 | { | 312 | { |
577 | u16 error = 0; | 313 | u16 err = 0; |
578 | struct hpi_msg_format fmt; | 314 | struct hpi_msg_format fmt; |
579 | 315 | ||
580 | switch (channels) { | 316 | switch (channels) { |
@@ -586,8 +322,8 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, | |||
586 | case 16: | 322 | case 16: |
587 | break; | 323 | break; |
588 | default: | 324 | default: |
589 | error = HPI_ERROR_INVALID_CHANNELS; | 325 | err = HPI_ERROR_INVALID_CHANNELS; |
590 | return error; | 326 | return err; |
591 | } | 327 | } |
592 | fmt.channels = channels; | 328 | fmt.channels = channels; |
593 | 329 | ||
@@ -610,17 +346,17 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, | |||
610 | case HPI_FORMAT_OEM2: | 346 | case HPI_FORMAT_OEM2: |
611 | break; | 347 | break; |
612 | default: | 348 | default: |
613 | error = HPI_ERROR_INVALID_FORMAT; | 349 | err = HPI_ERROR_INVALID_FORMAT; |
614 | return error; | 350 | return err; |
615 | } | 351 | } |
616 | fmt.format = format; | 352 | fmt.format = format; |
617 | 353 | ||
618 | if (sample_rate < 8000L) { | 354 | if (sample_rate < 8000L) { |
619 | error = HPI_ERROR_INCOMPATIBLE_SAMPLERATE; | 355 | err = HPI_ERROR_INCOMPATIBLE_SAMPLERATE; |
620 | sample_rate = 8000L; | 356 | sample_rate = 8000L; |
621 | } | 357 | } |
622 | if (sample_rate > 200000L) { | 358 | if (sample_rate > 200000L) { |
623 | error = HPI_ERROR_INCOMPATIBLE_SAMPLERATE; | 359 | err = HPI_ERROR_INCOMPATIBLE_SAMPLERATE; |
624 | sample_rate = 200000L; | 360 | sample_rate = 200000L; |
625 | } | 361 | } |
626 | fmt.sample_rate = sample_rate; | 362 | fmt.sample_rate = sample_rate; |
@@ -651,10 +387,10 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, | |||
651 | if ((channels == 1) | 387 | if ((channels == 1) |
652 | && (attributes != HPI_MPEG_MODE_DEFAULT)) { | 388 | && (attributes != HPI_MPEG_MODE_DEFAULT)) { |
653 | attributes = HPI_MPEG_MODE_DEFAULT; | 389 | attributes = HPI_MPEG_MODE_DEFAULT; |
654 | error = HPI_ERROR_INVALID_FORMAT; | 390 | err = HPI_ERROR_INVALID_FORMAT; |
655 | } else if (attributes > HPI_MPEG_MODE_DUALCHANNEL) { | 391 | } else if (attributes > HPI_MPEG_MODE_DUALCHANNEL) { |
656 | attributes = HPI_MPEG_MODE_DEFAULT; | 392 | attributes = HPI_MPEG_MODE_DEFAULT; |
657 | error = HPI_ERROR_INVALID_FORMAT; | 393 | err = HPI_ERROR_INVALID_FORMAT; |
658 | } | 394 | } |
659 | fmt.attributes = attributes; | 395 | fmt.attributes = attributes; |
660 | break; | 396 | break; |
@@ -663,7 +399,7 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format, | |||
663 | } | 399 | } |
664 | 400 | ||
665 | hpi_msg_to_format(p_format, &fmt); | 401 | hpi_msg_to_format(p_format, &fmt); |
666 | return error; | 402 | return err; |
667 | } | 403 | } |
668 | 404 | ||
669 | u16 hpi_stream_estimate_buffer_size(struct hpi_format *p_format, | 405 | u16 hpi_stream_estimate_buffer_size(struct hpi_format *p_format, |
@@ -712,8 +448,8 @@ u16 hpi_stream_estimate_buffer_size(struct hpi_format *p_format, | |||
712 | return 0; | 448 | return 0; |
713 | } | 449 | } |
714 | 450 | ||
715 | u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | 451 | u16 hpi_outstream_open(u16 adapter_index, u16 outstream_index, |
716 | u16 outstream_index, u32 *ph_outstream) | 452 | u32 *ph_outstream) |
717 | { | 453 | { |
718 | struct hpi_message hm; | 454 | struct hpi_message hm; |
719 | struct hpi_response hr; | 455 | struct hpi_response hr; |
@@ -733,38 +469,41 @@ u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | |||
733 | return hr.error; | 469 | return hr.error; |
734 | } | 470 | } |
735 | 471 | ||
736 | u16 hpi_outstream_close(const struct hpi_hsubsys *ph_subsys, u32 h_outstream) | 472 | u16 hpi_outstream_close(u32 h_outstream) |
737 | { | 473 | { |
738 | struct hpi_message hm; | 474 | struct hpi_message hm; |
739 | struct hpi_response hr; | 475 | struct hpi_response hr; |
740 | 476 | ||
741 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 477 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
742 | HPI_OSTREAM_HOSTBUFFER_FREE); | 478 | HPI_OSTREAM_HOSTBUFFER_FREE); |
743 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 479 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
480 | return HPI_ERROR_INVALID_HANDLE; | ||
481 | |||
744 | hpi_send_recv(&hm, &hr); | 482 | hpi_send_recv(&hm, &hr); |
745 | 483 | ||
746 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 484 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
747 | HPI_OSTREAM_GROUP_RESET); | 485 | HPI_OSTREAM_GROUP_RESET); |
748 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 486 | hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index); |
749 | hpi_send_recv(&hm, &hr); | 487 | hpi_send_recv(&hm, &hr); |
750 | 488 | ||
751 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 489 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
752 | HPI_OSTREAM_CLOSE); | 490 | HPI_OSTREAM_CLOSE); |
753 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 491 | hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index); |
754 | hpi_send_recv(&hm, &hr); | 492 | hpi_send_recv(&hm, &hr); |
755 | 493 | ||
756 | return hr.error; | 494 | return hr.error; |
757 | } | 495 | } |
758 | 496 | ||
759 | u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys, | 497 | u16 hpi_outstream_get_info_ex(u32 h_outstream, u16 *pw_state, |
760 | u32 h_outstream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_to_play, | 498 | u32 *pbuffer_size, u32 *pdata_to_play, u32 *psamples_played, |
761 | u32 *psamples_played, u32 *pauxiliary_data_to_play) | 499 | u32 *pauxiliary_data_to_play) |
762 | { | 500 | { |
763 | struct hpi_message hm; | 501 | struct hpi_message hm; |
764 | struct hpi_response hr; | 502 | struct hpi_response hr; |
765 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 503 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
766 | HPI_OSTREAM_GET_INFO); | 504 | HPI_OSTREAM_GET_INFO); |
767 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 505 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
506 | return HPI_ERROR_INVALID_HANDLE; | ||
768 | 507 | ||
769 | hpi_send_recv(&hm, &hr); | 508 | hpi_send_recv(&hm, &hr); |
770 | 509 | ||
@@ -782,15 +521,15 @@ u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys, | |||
782 | return hr.error; | 521 | return hr.error; |
783 | } | 522 | } |
784 | 523 | ||
785 | u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys, | 524 | u16 hpi_outstream_write_buf(u32 h_outstream, const u8 *pb_data, |
786 | u32 h_outstream, const u8 *pb_data, u32 bytes_to_write, | 525 | u32 bytes_to_write, const struct hpi_format *p_format) |
787 | const struct hpi_format *p_format) | ||
788 | { | 526 | { |
789 | struct hpi_message hm; | 527 | struct hpi_message hm; |
790 | struct hpi_response hr; | 528 | struct hpi_response hr; |
791 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 529 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
792 | HPI_OSTREAM_WRITE); | 530 | HPI_OSTREAM_WRITE); |
793 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 531 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
532 | return HPI_ERROR_INVALID_HANDLE; | ||
794 | hm.u.d.u.data.pb_data = (u8 *)pb_data; | 533 | hm.u.d.u.data.pb_data = (u8 *)pb_data; |
795 | hm.u.d.u.data.data_size = bytes_to_write; | 534 | hm.u.d.u.data.data_size = bytes_to_write; |
796 | 535 | ||
@@ -801,82 +540,85 @@ u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys, | |||
801 | return hr.error; | 540 | return hr.error; |
802 | } | 541 | } |
803 | 542 | ||
804 | u16 hpi_outstream_start(const struct hpi_hsubsys *ph_subsys, u32 h_outstream) | 543 | u16 hpi_outstream_start(u32 h_outstream) |
805 | { | 544 | { |
806 | struct hpi_message hm; | 545 | struct hpi_message hm; |
807 | struct hpi_response hr; | 546 | struct hpi_response hr; |
808 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 547 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
809 | HPI_OSTREAM_START); | 548 | HPI_OSTREAM_START); |
810 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 549 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
550 | return HPI_ERROR_INVALID_HANDLE; | ||
811 | 551 | ||
812 | hpi_send_recv(&hm, &hr); | 552 | hpi_send_recv(&hm, &hr); |
813 | 553 | ||
814 | return hr.error; | 554 | return hr.error; |
815 | } | 555 | } |
816 | 556 | ||
817 | u16 hpi_outstream_wait_start(const struct hpi_hsubsys *ph_subsys, | 557 | u16 hpi_outstream_wait_start(u32 h_outstream) |
818 | u32 h_outstream) | ||
819 | { | 558 | { |
820 | struct hpi_message hm; | 559 | struct hpi_message hm; |
821 | struct hpi_response hr; | 560 | struct hpi_response hr; |
822 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 561 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
823 | HPI_OSTREAM_WAIT_START); | 562 | HPI_OSTREAM_WAIT_START); |
824 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 563 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
564 | return HPI_ERROR_INVALID_HANDLE; | ||
825 | 565 | ||
826 | hpi_send_recv(&hm, &hr); | 566 | hpi_send_recv(&hm, &hr); |
827 | 567 | ||
828 | return hr.error; | 568 | return hr.error; |
829 | } | 569 | } |
830 | 570 | ||
831 | u16 hpi_outstream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_outstream) | 571 | u16 hpi_outstream_stop(u32 h_outstream) |
832 | { | 572 | { |
833 | struct hpi_message hm; | 573 | struct hpi_message hm; |
834 | struct hpi_response hr; | 574 | struct hpi_response hr; |
835 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 575 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
836 | HPI_OSTREAM_STOP); | 576 | HPI_OSTREAM_STOP); |
837 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 577 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
578 | return HPI_ERROR_INVALID_HANDLE; | ||
838 | 579 | ||
839 | hpi_send_recv(&hm, &hr); | 580 | hpi_send_recv(&hm, &hr); |
840 | 581 | ||
841 | return hr.error; | 582 | return hr.error; |
842 | } | 583 | } |
843 | 584 | ||
844 | u16 hpi_outstream_sinegen(const struct hpi_hsubsys *ph_subsys, | 585 | u16 hpi_outstream_sinegen(u32 h_outstream) |
845 | u32 h_outstream) | ||
846 | { | 586 | { |
847 | struct hpi_message hm; | 587 | struct hpi_message hm; |
848 | struct hpi_response hr; | 588 | struct hpi_response hr; |
849 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 589 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
850 | HPI_OSTREAM_SINEGEN); | 590 | HPI_OSTREAM_SINEGEN); |
851 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 591 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
592 | return HPI_ERROR_INVALID_HANDLE; | ||
852 | 593 | ||
853 | hpi_send_recv(&hm, &hr); | 594 | hpi_send_recv(&hm, &hr); |
854 | 595 | ||
855 | return hr.error; | 596 | return hr.error; |
856 | } | 597 | } |
857 | 598 | ||
858 | u16 hpi_outstream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_outstream) | 599 | u16 hpi_outstream_reset(u32 h_outstream) |
859 | { | 600 | { |
860 | struct hpi_message hm; | 601 | struct hpi_message hm; |
861 | struct hpi_response hr; | 602 | struct hpi_response hr; |
862 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 603 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
863 | HPI_OSTREAM_RESET); | 604 | HPI_OSTREAM_RESET); |
864 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 605 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
606 | return HPI_ERROR_INVALID_HANDLE; | ||
865 | 607 | ||
866 | hpi_send_recv(&hm, &hr); | 608 | hpi_send_recv(&hm, &hr); |
867 | 609 | ||
868 | return hr.error; | 610 | return hr.error; |
869 | } | 611 | } |
870 | 612 | ||
871 | u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys, | 613 | u16 hpi_outstream_query_format(u32 h_outstream, struct hpi_format *p_format) |
872 | u32 h_outstream, struct hpi_format *p_format) | ||
873 | { | 614 | { |
874 | struct hpi_message hm; | 615 | struct hpi_message hm; |
875 | struct hpi_response hr; | 616 | struct hpi_response hr; |
876 | 617 | ||
877 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 618 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
878 | HPI_OSTREAM_QUERY_FORMAT); | 619 | HPI_OSTREAM_QUERY_FORMAT); |
879 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 620 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
621 | return HPI_ERROR_INVALID_HANDLE; | ||
880 | 622 | ||
881 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); | 623 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); |
882 | 624 | ||
@@ -885,15 +627,15 @@ u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys, | |||
885 | return hr.error; | 627 | return hr.error; |
886 | } | 628 | } |
887 | 629 | ||
888 | u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys, | 630 | u16 hpi_outstream_set_format(u32 h_outstream, struct hpi_format *p_format) |
889 | u32 h_outstream, struct hpi_format *p_format) | ||
890 | { | 631 | { |
891 | struct hpi_message hm; | 632 | struct hpi_message hm; |
892 | struct hpi_response hr; | 633 | struct hpi_response hr; |
893 | 634 | ||
894 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 635 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
895 | HPI_OSTREAM_SET_FORMAT); | 636 | HPI_OSTREAM_SET_FORMAT); |
896 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 637 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
638 | return HPI_ERROR_INVALID_HANDLE; | ||
897 | 639 | ||
898 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); | 640 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); |
899 | 641 | ||
@@ -902,15 +644,15 @@ u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys, | |||
902 | return hr.error; | 644 | return hr.error; |
903 | } | 645 | } |
904 | 646 | ||
905 | u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys, | 647 | u16 hpi_outstream_set_velocity(u32 h_outstream, short velocity) |
906 | u32 h_outstream, short velocity) | ||
907 | { | 648 | { |
908 | struct hpi_message hm; | 649 | struct hpi_message hm; |
909 | struct hpi_response hr; | 650 | struct hpi_response hr; |
910 | 651 | ||
911 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 652 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
912 | HPI_OSTREAM_SET_VELOCITY); | 653 | HPI_OSTREAM_SET_VELOCITY); |
913 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 654 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
655 | return HPI_ERROR_INVALID_HANDLE; | ||
914 | hm.u.d.u.velocity = velocity; | 656 | hm.u.d.u.velocity = velocity; |
915 | 657 | ||
916 | hpi_send_recv(&hm, &hr); | 658 | hpi_send_recv(&hm, &hr); |
@@ -918,15 +660,16 @@ u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys, | |||
918 | return hr.error; | 660 | return hr.error; |
919 | } | 661 | } |
920 | 662 | ||
921 | u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys, | 663 | u16 hpi_outstream_set_punch_in_out(u32 h_outstream, u32 punch_in_sample, |
922 | u32 h_outstream, u32 punch_in_sample, u32 punch_out_sample) | 664 | u32 punch_out_sample) |
923 | { | 665 | { |
924 | struct hpi_message hm; | 666 | struct hpi_message hm; |
925 | struct hpi_response hr; | 667 | struct hpi_response hr; |
926 | 668 | ||
927 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 669 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
928 | HPI_OSTREAM_SET_PUNCHINOUT); | 670 | HPI_OSTREAM_SET_PUNCHINOUT); |
929 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 671 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
672 | return HPI_ERROR_INVALID_HANDLE; | ||
930 | 673 | ||
931 | hm.u.d.u.pio.punch_in_sample = punch_in_sample; | 674 | hm.u.d.u.pio.punch_in_sample = punch_in_sample; |
932 | hm.u.d.u.pio.punch_out_sample = punch_out_sample; | 675 | hm.u.d.u.pio.punch_out_sample = punch_out_sample; |
@@ -936,29 +679,29 @@ u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys, | |||
936 | return hr.error; | 679 | return hr.error; |
937 | } | 680 | } |
938 | 681 | ||
939 | u16 hpi_outstream_ancillary_reset(const struct hpi_hsubsys *ph_subsys, | 682 | u16 hpi_outstream_ancillary_reset(u32 h_outstream, u16 mode) |
940 | u32 h_outstream, u16 mode) | ||
941 | { | 683 | { |
942 | struct hpi_message hm; | 684 | struct hpi_message hm; |
943 | struct hpi_response hr; | 685 | struct hpi_response hr; |
944 | 686 | ||
945 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 687 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
946 | HPI_OSTREAM_ANC_RESET); | 688 | HPI_OSTREAM_ANC_RESET); |
947 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 689 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
690 | return HPI_ERROR_INVALID_HANDLE; | ||
948 | hm.u.d.u.data.format.channels = mode; | 691 | hm.u.d.u.data.format.channels = mode; |
949 | hpi_send_recv(&hm, &hr); | 692 | hpi_send_recv(&hm, &hr); |
950 | return hr.error; | 693 | return hr.error; |
951 | } | 694 | } |
952 | 695 | ||
953 | u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys, | 696 | u16 hpi_outstream_ancillary_get_info(u32 h_outstream, u32 *pframes_available) |
954 | u32 h_outstream, u32 *pframes_available) | ||
955 | { | 697 | { |
956 | struct hpi_message hm; | 698 | struct hpi_message hm; |
957 | struct hpi_response hr; | 699 | struct hpi_response hr; |
958 | 700 | ||
959 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 701 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
960 | HPI_OSTREAM_ANC_GET_INFO); | 702 | HPI_OSTREAM_ANC_GET_INFO); |
961 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 703 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
704 | return HPI_ERROR_INVALID_HANDLE; | ||
962 | hpi_send_recv(&hm, &hr); | 705 | hpi_send_recv(&hm, &hr); |
963 | if (hr.error == 0) { | 706 | if (hr.error == 0) { |
964 | if (pframes_available) | 707 | if (pframes_available) |
@@ -969,8 +712,8 @@ u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys, | |||
969 | return hr.error; | 712 | return hr.error; |
970 | } | 713 | } |
971 | 714 | ||
972 | u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys, | 715 | u16 hpi_outstream_ancillary_read(u32 h_outstream, |
973 | u32 h_outstream, struct hpi_anc_frame *p_anc_frame_buffer, | 716 | struct hpi_anc_frame *p_anc_frame_buffer, |
974 | u32 anc_frame_buffer_size_in_bytes, | 717 | u32 anc_frame_buffer_size_in_bytes, |
975 | u32 number_of_ancillary_frames_to_read) | 718 | u32 number_of_ancillary_frames_to_read) |
976 | { | 719 | { |
@@ -979,7 +722,8 @@ u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys, | |||
979 | 722 | ||
980 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 723 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
981 | HPI_OSTREAM_ANC_READ); | 724 | HPI_OSTREAM_ANC_READ); |
982 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 725 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
726 | return HPI_ERROR_INVALID_HANDLE; | ||
983 | hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer; | 727 | hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer; |
984 | hm.u.d.u.data.data_size = | 728 | hm.u.d.u.data.data_size = |
985 | number_of_ancillary_frames_to_read * | 729 | number_of_ancillary_frames_to_read * |
@@ -987,19 +731,19 @@ u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys, | |||
987 | if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes) | 731 | if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes) |
988 | hpi_send_recv(&hm, &hr); | 732 | hpi_send_recv(&hm, &hr); |
989 | else | 733 | else |
990 | hr.error = HPI_ERROR_INVALID_DATA_TRANSFER; | 734 | hr.error = HPI_ERROR_INVALID_DATASIZE; |
991 | return hr.error; | 735 | return hr.error; |
992 | } | 736 | } |
993 | 737 | ||
994 | u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys, | 738 | u16 hpi_outstream_set_time_scale(u32 h_outstream, u32 time_scale) |
995 | u32 h_outstream, u32 time_scale) | ||
996 | { | 739 | { |
997 | struct hpi_message hm; | 740 | struct hpi_message hm; |
998 | struct hpi_response hr; | 741 | struct hpi_response hr; |
999 | 742 | ||
1000 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 743 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
1001 | HPI_OSTREAM_SET_TIMESCALE); | 744 | HPI_OSTREAM_SET_TIMESCALE); |
1002 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 745 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
746 | return HPI_ERROR_INVALID_HANDLE; | ||
1003 | 747 | ||
1004 | hm.u.d.u.time_scale = time_scale; | 748 | hm.u.d.u.time_scale = time_scale; |
1005 | 749 | ||
@@ -1008,22 +752,21 @@ u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys, | |||
1008 | return hr.error; | 752 | return hr.error; |
1009 | } | 753 | } |
1010 | 754 | ||
1011 | u16 hpi_outstream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys, | 755 | u16 hpi_outstream_host_buffer_allocate(u32 h_outstream, u32 size_in_bytes) |
1012 | u32 h_outstream, u32 size_in_bytes) | ||
1013 | { | 756 | { |
1014 | struct hpi_message hm; | 757 | struct hpi_message hm; |
1015 | struct hpi_response hr; | 758 | struct hpi_response hr; |
1016 | 759 | ||
1017 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 760 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
1018 | HPI_OSTREAM_HOSTBUFFER_ALLOC); | 761 | HPI_OSTREAM_HOSTBUFFER_ALLOC); |
1019 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 762 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
763 | return HPI_ERROR_INVALID_HANDLE; | ||
1020 | hm.u.d.u.data.data_size = size_in_bytes; | 764 | hm.u.d.u.data.data_size = size_in_bytes; |
1021 | hpi_send_recv(&hm, &hr); | 765 | hpi_send_recv(&hm, &hr); |
1022 | return hr.error; | 766 | return hr.error; |
1023 | } | 767 | } |
1024 | 768 | ||
1025 | u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | 769 | u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer, |
1026 | u32 h_outstream, u8 **pp_buffer, | ||
1027 | struct hpi_hostbuffer_status **pp_status) | 770 | struct hpi_hostbuffer_status **pp_status) |
1028 | { | 771 | { |
1029 | struct hpi_message hm; | 772 | struct hpi_message hm; |
@@ -1031,7 +774,8 @@ u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | |||
1031 | 774 | ||
1032 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 775 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
1033 | HPI_OSTREAM_HOSTBUFFER_GET_INFO); | 776 | HPI_OSTREAM_HOSTBUFFER_GET_INFO); |
1034 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 777 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
778 | return HPI_ERROR_INVALID_HANDLE; | ||
1035 | hpi_send_recv(&hm, &hr); | 779 | hpi_send_recv(&hm, &hr); |
1036 | 780 | ||
1037 | if (hr.error == 0) { | 781 | if (hr.error == 0) { |
@@ -1043,21 +787,20 @@ u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | |||
1043 | return hr.error; | 787 | return hr.error; |
1044 | } | 788 | } |
1045 | 789 | ||
1046 | u16 hpi_outstream_host_buffer_free(const struct hpi_hsubsys *ph_subsys, | 790 | u16 hpi_outstream_host_buffer_free(u32 h_outstream) |
1047 | u32 h_outstream) | ||
1048 | { | 791 | { |
1049 | struct hpi_message hm; | 792 | struct hpi_message hm; |
1050 | struct hpi_response hr; | 793 | struct hpi_response hr; |
1051 | 794 | ||
1052 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 795 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
1053 | HPI_OSTREAM_HOSTBUFFER_FREE); | 796 | HPI_OSTREAM_HOSTBUFFER_FREE); |
1054 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 797 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
798 | return HPI_ERROR_INVALID_HANDLE; | ||
1055 | hpi_send_recv(&hm, &hr); | 799 | hpi_send_recv(&hm, &hr); |
1056 | return hr.error; | 800 | return hr.error; |
1057 | } | 801 | } |
1058 | 802 | ||
1059 | u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys, | 803 | u16 hpi_outstream_group_add(u32 h_outstream, u32 h_stream) |
1060 | u32 h_outstream, u32 h_stream) | ||
1061 | { | 804 | { |
1062 | struct hpi_message hm; | 805 | struct hpi_message hm; |
1063 | struct hpi_response hr; | 806 | struct hpi_response hr; |
@@ -1066,22 +809,22 @@ u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys, | |||
1066 | 809 | ||
1067 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 810 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
1068 | HPI_OSTREAM_GROUP_ADD); | 811 | HPI_OSTREAM_GROUP_ADD); |
1069 | hr.error = 0; | 812 | |
1070 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 813 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
814 | return HPI_ERROR_INVALID_HANDLE; | ||
815 | |||
816 | if (hpi_handle_indexes(h_stream, &adapter, | ||
817 | &hm.u.d.u.stream.stream_index)) | ||
818 | return HPI_ERROR_INVALID_HANDLE; | ||
819 | |||
1071 | c_obj_type = hpi_handle_object(h_stream); | 820 | c_obj_type = hpi_handle_object(h_stream); |
1072 | switch (c_obj_type) { | 821 | switch (c_obj_type) { |
1073 | case HPI_OBJ_OSTREAM: | 822 | case HPI_OBJ_OSTREAM: |
1074 | hm.u.d.u.stream.object_type = HPI_OBJ_OSTREAM; | ||
1075 | u32TOINDEXES(h_stream, &adapter, | ||
1076 | &hm.u.d.u.stream.stream_index); | ||
1077 | break; | ||
1078 | case HPI_OBJ_ISTREAM: | 823 | case HPI_OBJ_ISTREAM: |
1079 | hm.u.d.u.stream.object_type = HPI_OBJ_ISTREAM; | 824 | hm.u.d.u.stream.object_type = c_obj_type; |
1080 | u32TOINDEXES(h_stream, &adapter, | ||
1081 | &hm.u.d.u.stream.stream_index); | ||
1082 | break; | 825 | break; |
1083 | default: | 826 | default: |
1084 | return HPI_ERROR_INVALID_STREAM; | 827 | return HPI_ERROR_INVALID_OBJ; |
1085 | } | 828 | } |
1086 | if (adapter != hm.adapter_index) | 829 | if (adapter != hm.adapter_index) |
1087 | return HPI_ERROR_NO_INTERADAPTER_GROUPS; | 830 | return HPI_ERROR_NO_INTERADAPTER_GROUPS; |
@@ -1090,15 +833,16 @@ u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys, | |||
1090 | return hr.error; | 833 | return hr.error; |
1091 | } | 834 | } |
1092 | 835 | ||
1093 | u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys, | 836 | u16 hpi_outstream_group_get_map(u32 h_outstream, u32 *poutstream_map, |
1094 | u32 h_outstream, u32 *poutstream_map, u32 *pinstream_map) | 837 | u32 *pinstream_map) |
1095 | { | 838 | { |
1096 | struct hpi_message hm; | 839 | struct hpi_message hm; |
1097 | struct hpi_response hr; | 840 | struct hpi_response hr; |
1098 | 841 | ||
1099 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 842 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
1100 | HPI_OSTREAM_GROUP_GETMAP); | 843 | HPI_OSTREAM_GROUP_GETMAP); |
1101 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 844 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
845 | return HPI_ERROR_INVALID_HANDLE; | ||
1102 | hpi_send_recv(&hm, &hr); | 846 | hpi_send_recv(&hm, &hr); |
1103 | 847 | ||
1104 | if (poutstream_map) | 848 | if (poutstream_map) |
@@ -1109,21 +853,20 @@ u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys, | |||
1109 | return hr.error; | 853 | return hr.error; |
1110 | } | 854 | } |
1111 | 855 | ||
1112 | u16 hpi_outstream_group_reset(const struct hpi_hsubsys *ph_subsys, | 856 | u16 hpi_outstream_group_reset(u32 h_outstream) |
1113 | u32 h_outstream) | ||
1114 | { | 857 | { |
1115 | struct hpi_message hm; | 858 | struct hpi_message hm; |
1116 | struct hpi_response hr; | 859 | struct hpi_response hr; |
1117 | 860 | ||
1118 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 861 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
1119 | HPI_OSTREAM_GROUP_RESET); | 862 | HPI_OSTREAM_GROUP_RESET); |
1120 | u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index); | 863 | if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index)) |
864 | return HPI_ERROR_INVALID_HANDLE; | ||
1121 | hpi_send_recv(&hm, &hr); | 865 | hpi_send_recv(&hm, &hr); |
1122 | return hr.error; | 866 | return hr.error; |
1123 | } | 867 | } |
1124 | 868 | ||
1125 | u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | 869 | u16 hpi_instream_open(u16 adapter_index, u16 instream_index, u32 *ph_instream) |
1126 | u16 instream_index, u32 *ph_instream) | ||
1127 | { | 870 | { |
1128 | struct hpi_message hm; | 871 | struct hpi_message hm; |
1129 | struct hpi_response hr; | 872 | struct hpi_response hr; |
@@ -1145,38 +888,40 @@ u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | |||
1145 | return hr.error; | 888 | return hr.error; |
1146 | } | 889 | } |
1147 | 890 | ||
1148 | u16 hpi_instream_close(const struct hpi_hsubsys *ph_subsys, u32 h_instream) | 891 | u16 hpi_instream_close(u32 h_instream) |
1149 | { | 892 | { |
1150 | struct hpi_message hm; | 893 | struct hpi_message hm; |
1151 | struct hpi_response hr; | 894 | struct hpi_response hr; |
1152 | 895 | ||
1153 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 896 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1154 | HPI_ISTREAM_HOSTBUFFER_FREE); | 897 | HPI_ISTREAM_HOSTBUFFER_FREE); |
1155 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 898 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
899 | return HPI_ERROR_INVALID_HANDLE; | ||
1156 | hpi_send_recv(&hm, &hr); | 900 | hpi_send_recv(&hm, &hr); |
1157 | 901 | ||
1158 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 902 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1159 | HPI_ISTREAM_GROUP_RESET); | 903 | HPI_ISTREAM_GROUP_RESET); |
1160 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 904 | hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index); |
1161 | hpi_send_recv(&hm, &hr); | 905 | hpi_send_recv(&hm, &hr); |
1162 | 906 | ||
1163 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 907 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1164 | HPI_ISTREAM_CLOSE); | 908 | HPI_ISTREAM_CLOSE); |
1165 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 909 | hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index); |
1166 | hpi_send_recv(&hm, &hr); | 910 | hpi_send_recv(&hm, &hr); |
1167 | 911 | ||
1168 | return hr.error; | 912 | return hr.error; |
1169 | } | 913 | } |
1170 | 914 | ||
1171 | u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys, | 915 | u16 hpi_instream_query_format(u32 h_instream, |
1172 | u32 h_instream, const struct hpi_format *p_format) | 916 | const struct hpi_format *p_format) |
1173 | { | 917 | { |
1174 | struct hpi_message hm; | 918 | struct hpi_message hm; |
1175 | struct hpi_response hr; | 919 | struct hpi_response hr; |
1176 | 920 | ||
1177 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 921 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1178 | HPI_ISTREAM_QUERY_FORMAT); | 922 | HPI_ISTREAM_QUERY_FORMAT); |
1179 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 923 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
924 | return HPI_ERROR_INVALID_HANDLE; | ||
1180 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); | 925 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); |
1181 | 926 | ||
1182 | hpi_send_recv(&hm, &hr); | 927 | hpi_send_recv(&hm, &hr); |
@@ -1184,15 +929,15 @@ u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys, | |||
1184 | return hr.error; | 929 | return hr.error; |
1185 | } | 930 | } |
1186 | 931 | ||
1187 | u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys, | 932 | u16 hpi_instream_set_format(u32 h_instream, const struct hpi_format *p_format) |
1188 | u32 h_instream, const struct hpi_format *p_format) | ||
1189 | { | 933 | { |
1190 | struct hpi_message hm; | 934 | struct hpi_message hm; |
1191 | struct hpi_response hr; | 935 | struct hpi_response hr; |
1192 | 936 | ||
1193 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 937 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1194 | HPI_ISTREAM_SET_FORMAT); | 938 | HPI_ISTREAM_SET_FORMAT); |
1195 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 939 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
940 | return HPI_ERROR_INVALID_HANDLE; | ||
1196 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); | 941 | hpi_format_to_msg(&hm.u.d.u.data.format, p_format); |
1197 | 942 | ||
1198 | hpi_send_recv(&hm, &hr); | 943 | hpi_send_recv(&hm, &hr); |
@@ -1200,15 +945,15 @@ u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys, | |||
1200 | return hr.error; | 945 | return hr.error; |
1201 | } | 946 | } |
1202 | 947 | ||
1203 | u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream, | 948 | u16 hpi_instream_read_buf(u32 h_instream, u8 *pb_data, u32 bytes_to_read) |
1204 | u8 *pb_data, u32 bytes_to_read) | ||
1205 | { | 949 | { |
1206 | struct hpi_message hm; | 950 | struct hpi_message hm; |
1207 | struct hpi_response hr; | 951 | struct hpi_response hr; |
1208 | 952 | ||
1209 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 953 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1210 | HPI_ISTREAM_READ); | 954 | HPI_ISTREAM_READ); |
1211 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 955 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
956 | return HPI_ERROR_INVALID_HANDLE; | ||
1212 | hm.u.d.u.data.data_size = bytes_to_read; | 957 | hm.u.d.u.data.data_size = bytes_to_read; |
1213 | hm.u.d.u.data.pb_data = pb_data; | 958 | hm.u.d.u.data.pb_data = pb_data; |
1214 | 959 | ||
@@ -1217,72 +962,76 @@ u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream, | |||
1217 | return hr.error; | 962 | return hr.error; |
1218 | } | 963 | } |
1219 | 964 | ||
1220 | u16 hpi_instream_start(const struct hpi_hsubsys *ph_subsys, u32 h_instream) | 965 | u16 hpi_instream_start(u32 h_instream) |
1221 | { | 966 | { |
1222 | struct hpi_message hm; | 967 | struct hpi_message hm; |
1223 | struct hpi_response hr; | 968 | struct hpi_response hr; |
1224 | 969 | ||
1225 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 970 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1226 | HPI_ISTREAM_START); | 971 | HPI_ISTREAM_START); |
1227 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 972 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
973 | return HPI_ERROR_INVALID_HANDLE; | ||
1228 | 974 | ||
1229 | hpi_send_recv(&hm, &hr); | 975 | hpi_send_recv(&hm, &hr); |
1230 | 976 | ||
1231 | return hr.error; | 977 | return hr.error; |
1232 | } | 978 | } |
1233 | 979 | ||
1234 | u16 hpi_instream_wait_start(const struct hpi_hsubsys *ph_subsys, | 980 | u16 hpi_instream_wait_start(u32 h_instream) |
1235 | u32 h_instream) | ||
1236 | { | 981 | { |
1237 | struct hpi_message hm; | 982 | struct hpi_message hm; |
1238 | struct hpi_response hr; | 983 | struct hpi_response hr; |
1239 | 984 | ||
1240 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 985 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1241 | HPI_ISTREAM_WAIT_START); | 986 | HPI_ISTREAM_WAIT_START); |
1242 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 987 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
988 | return HPI_ERROR_INVALID_HANDLE; | ||
1243 | 989 | ||
1244 | hpi_send_recv(&hm, &hr); | 990 | hpi_send_recv(&hm, &hr); |
1245 | 991 | ||
1246 | return hr.error; | 992 | return hr.error; |
1247 | } | 993 | } |
1248 | 994 | ||
1249 | u16 hpi_instream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_instream) | 995 | u16 hpi_instream_stop(u32 h_instream) |
1250 | { | 996 | { |
1251 | struct hpi_message hm; | 997 | struct hpi_message hm; |
1252 | struct hpi_response hr; | 998 | struct hpi_response hr; |
1253 | 999 | ||
1254 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1000 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1255 | HPI_ISTREAM_STOP); | 1001 | HPI_ISTREAM_STOP); |
1256 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1002 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1003 | return HPI_ERROR_INVALID_HANDLE; | ||
1257 | 1004 | ||
1258 | hpi_send_recv(&hm, &hr); | 1005 | hpi_send_recv(&hm, &hr); |
1259 | 1006 | ||
1260 | return hr.error; | 1007 | return hr.error; |
1261 | } | 1008 | } |
1262 | 1009 | ||
1263 | u16 hpi_instream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_instream) | 1010 | u16 hpi_instream_reset(u32 h_instream) |
1264 | { | 1011 | { |
1265 | struct hpi_message hm; | 1012 | struct hpi_message hm; |
1266 | struct hpi_response hr; | 1013 | struct hpi_response hr; |
1267 | 1014 | ||
1268 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1015 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1269 | HPI_ISTREAM_RESET); | 1016 | HPI_ISTREAM_RESET); |
1270 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1017 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1018 | return HPI_ERROR_INVALID_HANDLE; | ||
1271 | 1019 | ||
1272 | hpi_send_recv(&hm, &hr); | 1020 | hpi_send_recv(&hm, &hr); |
1273 | 1021 | ||
1274 | return hr.error; | 1022 | return hr.error; |
1275 | } | 1023 | } |
1276 | 1024 | ||
1277 | u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys, | 1025 | u16 hpi_instream_get_info_ex(u32 h_instream, u16 *pw_state, u32 *pbuffer_size, |
1278 | u32 h_instream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_recorded, | 1026 | u32 *pdata_recorded, u32 *psamples_recorded, |
1279 | u32 *psamples_recorded, u32 *pauxiliary_data_recorded) | 1027 | u32 *pauxiliary_data_recorded) |
1280 | { | 1028 | { |
1281 | struct hpi_message hm; | 1029 | struct hpi_message hm; |
1282 | struct hpi_response hr; | 1030 | struct hpi_response hr; |
1283 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1031 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1284 | HPI_ISTREAM_GET_INFO); | 1032 | HPI_ISTREAM_GET_INFO); |
1285 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1033 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1034 | return HPI_ERROR_INVALID_HANDLE; | ||
1286 | 1035 | ||
1287 | hpi_send_recv(&hm, &hr); | 1036 | hpi_send_recv(&hm, &hr); |
1288 | 1037 | ||
@@ -1300,15 +1049,15 @@ u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys, | |||
1300 | return hr.error; | 1049 | return hr.error; |
1301 | } | 1050 | } |
1302 | 1051 | ||
1303 | u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys, | 1052 | u16 hpi_instream_ancillary_reset(u32 h_instream, u16 bytes_per_frame, |
1304 | u32 h_instream, u16 bytes_per_frame, u16 mode, u16 alignment, | 1053 | u16 mode, u16 alignment, u16 idle_bit) |
1305 | u16 idle_bit) | ||
1306 | { | 1054 | { |
1307 | struct hpi_message hm; | 1055 | struct hpi_message hm; |
1308 | struct hpi_response hr; | 1056 | struct hpi_response hr; |
1309 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1057 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1310 | HPI_ISTREAM_ANC_RESET); | 1058 | HPI_ISTREAM_ANC_RESET); |
1311 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1059 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1060 | return HPI_ERROR_INVALID_HANDLE; | ||
1312 | hm.u.d.u.data.format.attributes = bytes_per_frame; | 1061 | hm.u.d.u.data.format.attributes = bytes_per_frame; |
1313 | hm.u.d.u.data.format.format = (mode << 8) | (alignment & 0xff); | 1062 | hm.u.d.u.data.format.format = (mode << 8) | (alignment & 0xff); |
1314 | hm.u.d.u.data.format.channels = idle_bit; | 1063 | hm.u.d.u.data.format.channels = idle_bit; |
@@ -1316,14 +1065,14 @@ u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys, | |||
1316 | return hr.error; | 1065 | return hr.error; |
1317 | } | 1066 | } |
1318 | 1067 | ||
1319 | u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys, | 1068 | u16 hpi_instream_ancillary_get_info(u32 h_instream, u32 *pframe_space) |
1320 | u32 h_instream, u32 *pframe_space) | ||
1321 | { | 1069 | { |
1322 | struct hpi_message hm; | 1070 | struct hpi_message hm; |
1323 | struct hpi_response hr; | 1071 | struct hpi_response hr; |
1324 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1072 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1325 | HPI_ISTREAM_ANC_GET_INFO); | 1073 | HPI_ISTREAM_ANC_GET_INFO); |
1326 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1074 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1075 | return HPI_ERROR_INVALID_HANDLE; | ||
1327 | hpi_send_recv(&hm, &hr); | 1076 | hpi_send_recv(&hm, &hr); |
1328 | if (pframe_space) | 1077 | if (pframe_space) |
1329 | *pframe_space = | 1078 | *pframe_space = |
@@ -1333,8 +1082,8 @@ u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys, | |||
1333 | return hr.error; | 1082 | return hr.error; |
1334 | } | 1083 | } |
1335 | 1084 | ||
1336 | u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys, | 1085 | u16 hpi_instream_ancillary_write(u32 h_instream, |
1337 | u32 h_instream, const struct hpi_anc_frame *p_anc_frame_buffer, | 1086 | const struct hpi_anc_frame *p_anc_frame_buffer, |
1338 | u32 anc_frame_buffer_size_in_bytes, | 1087 | u32 anc_frame_buffer_size_in_bytes, |
1339 | u32 number_of_ancillary_frames_to_write) | 1088 | u32 number_of_ancillary_frames_to_write) |
1340 | { | 1089 | { |
@@ -1343,7 +1092,8 @@ u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys, | |||
1343 | 1092 | ||
1344 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1093 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1345 | HPI_ISTREAM_ANC_WRITE); | 1094 | HPI_ISTREAM_ANC_WRITE); |
1346 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1095 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1096 | return HPI_ERROR_INVALID_HANDLE; | ||
1347 | hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer; | 1097 | hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer; |
1348 | hm.u.d.u.data.data_size = | 1098 | hm.u.d.u.data.data_size = |
1349 | number_of_ancillary_frames_to_write * | 1099 | number_of_ancillary_frames_to_write * |
@@ -1351,12 +1101,11 @@ u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys, | |||
1351 | if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes) | 1101 | if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes) |
1352 | hpi_send_recv(&hm, &hr); | 1102 | hpi_send_recv(&hm, &hr); |
1353 | else | 1103 | else |
1354 | hr.error = HPI_ERROR_INVALID_DATA_TRANSFER; | 1104 | hr.error = HPI_ERROR_INVALID_DATASIZE; |
1355 | return hr.error; | 1105 | return hr.error; |
1356 | } | 1106 | } |
1357 | 1107 | ||
1358 | u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys, | 1108 | u16 hpi_instream_host_buffer_allocate(u32 h_instream, u32 size_in_bytes) |
1359 | u32 h_instream, u32 size_in_bytes) | ||
1360 | { | 1109 | { |
1361 | 1110 | ||
1362 | struct hpi_message hm; | 1111 | struct hpi_message hm; |
@@ -1364,14 +1113,14 @@ u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys, | |||
1364 | 1113 | ||
1365 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1114 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1366 | HPI_ISTREAM_HOSTBUFFER_ALLOC); | 1115 | HPI_ISTREAM_HOSTBUFFER_ALLOC); |
1367 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1116 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1117 | return HPI_ERROR_INVALID_HANDLE; | ||
1368 | hm.u.d.u.data.data_size = size_in_bytes; | 1118 | hm.u.d.u.data.data_size = size_in_bytes; |
1369 | hpi_send_recv(&hm, &hr); | 1119 | hpi_send_recv(&hm, &hr); |
1370 | return hr.error; | 1120 | return hr.error; |
1371 | } | 1121 | } |
1372 | 1122 | ||
1373 | u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | 1123 | u16 hpi_instream_host_buffer_get_info(u32 h_instream, u8 **pp_buffer, |
1374 | u32 h_instream, u8 **pp_buffer, | ||
1375 | struct hpi_hostbuffer_status **pp_status) | 1124 | struct hpi_hostbuffer_status **pp_status) |
1376 | { | 1125 | { |
1377 | struct hpi_message hm; | 1126 | struct hpi_message hm; |
@@ -1379,7 +1128,8 @@ u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | |||
1379 | 1128 | ||
1380 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1129 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1381 | HPI_ISTREAM_HOSTBUFFER_GET_INFO); | 1130 | HPI_ISTREAM_HOSTBUFFER_GET_INFO); |
1382 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1131 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1132 | return HPI_ERROR_INVALID_HANDLE; | ||
1383 | hpi_send_recv(&hm, &hr); | 1133 | hpi_send_recv(&hm, &hr); |
1384 | 1134 | ||
1385 | if (hr.error == 0) { | 1135 | if (hr.error == 0) { |
@@ -1391,8 +1141,7 @@ u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys, | |||
1391 | return hr.error; | 1141 | return hr.error; |
1392 | } | 1142 | } |
1393 | 1143 | ||
1394 | u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys, | 1144 | u16 hpi_instream_host_buffer_free(u32 h_instream) |
1395 | u32 h_instream) | ||
1396 | { | 1145 | { |
1397 | 1146 | ||
1398 | struct hpi_message hm; | 1147 | struct hpi_message hm; |
@@ -1400,13 +1149,13 @@ u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys, | |||
1400 | 1149 | ||
1401 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1150 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1402 | HPI_ISTREAM_HOSTBUFFER_FREE); | 1151 | HPI_ISTREAM_HOSTBUFFER_FREE); |
1403 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1152 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1153 | return HPI_ERROR_INVALID_HANDLE; | ||
1404 | hpi_send_recv(&hm, &hr); | 1154 | hpi_send_recv(&hm, &hr); |
1405 | return hr.error; | 1155 | return hr.error; |
1406 | } | 1156 | } |
1407 | 1157 | ||
1408 | u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys, | 1158 | u16 hpi_instream_group_add(u32 h_instream, u32 h_stream) |
1409 | u32 h_instream, u32 h_stream) | ||
1410 | { | 1159 | { |
1411 | struct hpi_message hm; | 1160 | struct hpi_message hm; |
1412 | struct hpi_response hr; | 1161 | struct hpi_response hr; |
@@ -1416,22 +1165,23 @@ u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys, | |||
1416 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1165 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1417 | HPI_ISTREAM_GROUP_ADD); | 1166 | HPI_ISTREAM_GROUP_ADD); |
1418 | hr.error = 0; | 1167 | hr.error = 0; |
1419 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1168 | |
1169 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) | ||
1170 | return HPI_ERROR_INVALID_HANDLE; | ||
1171 | |||
1172 | if (hpi_handle_indexes(h_stream, &adapter, | ||
1173 | &hm.u.d.u.stream.stream_index)) | ||
1174 | return HPI_ERROR_INVALID_HANDLE; | ||
1175 | |||
1420 | c_obj_type = hpi_handle_object(h_stream); | 1176 | c_obj_type = hpi_handle_object(h_stream); |
1421 | 1177 | ||
1422 | switch (c_obj_type) { | 1178 | switch (c_obj_type) { |
1423 | case HPI_OBJ_OSTREAM: | 1179 | case HPI_OBJ_OSTREAM: |
1424 | hm.u.d.u.stream.object_type = HPI_OBJ_OSTREAM; | ||
1425 | u32TOINDEXES(h_stream, &adapter, | ||
1426 | &hm.u.d.u.stream.stream_index); | ||
1427 | break; | ||
1428 | case HPI_OBJ_ISTREAM: | 1180 | case HPI_OBJ_ISTREAM: |
1429 | hm.u.d.u.stream.object_type = HPI_OBJ_ISTREAM; | 1181 | hm.u.d.u.stream.object_type = c_obj_type; |
1430 | u32TOINDEXES(h_stream, &adapter, | ||
1431 | &hm.u.d.u.stream.stream_index); | ||
1432 | break; | 1182 | break; |
1433 | default: | 1183 | default: |
1434 | return HPI_ERROR_INVALID_STREAM; | 1184 | return HPI_ERROR_INVALID_OBJ; |
1435 | } | 1185 | } |
1436 | 1186 | ||
1437 | if (adapter != hm.adapter_index) | 1187 | if (adapter != hm.adapter_index) |
@@ -1441,15 +1191,16 @@ u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys, | |||
1441 | return hr.error; | 1191 | return hr.error; |
1442 | } | 1192 | } |
1443 | 1193 | ||
1444 | u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys, | 1194 | u16 hpi_instream_group_get_map(u32 h_instream, u32 *poutstream_map, |
1445 | u32 h_instream, u32 *poutstream_map, u32 *pinstream_map) | 1195 | u32 *pinstream_map) |
1446 | { | 1196 | { |
1447 | struct hpi_message hm; | 1197 | struct hpi_message hm; |
1448 | struct hpi_response hr; | 1198 | struct hpi_response hr; |
1449 | 1199 | ||
1450 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1200 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1451 | HPI_ISTREAM_HOSTBUFFER_FREE); | 1201 | HPI_ISTREAM_HOSTBUFFER_FREE); |
1452 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1202 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1203 | return HPI_ERROR_INVALID_HANDLE; | ||
1453 | hpi_send_recv(&hm, &hr); | 1204 | hpi_send_recv(&hm, &hr); |
1454 | 1205 | ||
1455 | if (poutstream_map) | 1206 | if (poutstream_map) |
@@ -1460,21 +1211,20 @@ u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys, | |||
1460 | return hr.error; | 1211 | return hr.error; |
1461 | } | 1212 | } |
1462 | 1213 | ||
1463 | u16 hpi_instream_group_reset(const struct hpi_hsubsys *ph_subsys, | 1214 | u16 hpi_instream_group_reset(u32 h_instream) |
1464 | u32 h_instream) | ||
1465 | { | 1215 | { |
1466 | struct hpi_message hm; | 1216 | struct hpi_message hm; |
1467 | struct hpi_response hr; | 1217 | struct hpi_response hr; |
1468 | 1218 | ||
1469 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 1219 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
1470 | HPI_ISTREAM_GROUP_RESET); | 1220 | HPI_ISTREAM_GROUP_RESET); |
1471 | u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index); | 1221 | if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index)) |
1222 | return HPI_ERROR_INVALID_HANDLE; | ||
1472 | hpi_send_recv(&hm, &hr); | 1223 | hpi_send_recv(&hm, &hr); |
1473 | return hr.error; | 1224 | return hr.error; |
1474 | } | 1225 | } |
1475 | 1226 | ||
1476 | u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | 1227 | u16 hpi_mixer_open(u16 adapter_index, u32 *ph_mixer) |
1477 | u32 *ph_mixer) | ||
1478 | { | 1228 | { |
1479 | struct hpi_message hm; | 1229 | struct hpi_message hm; |
1480 | struct hpi_response hr; | 1230 | struct hpi_response hr; |
@@ -1492,25 +1242,29 @@ u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | |||
1492 | return hr.error; | 1242 | return hr.error; |
1493 | } | 1243 | } |
1494 | 1244 | ||
1495 | u16 hpi_mixer_close(const struct hpi_hsubsys *ph_subsys, u32 h_mixer) | 1245 | u16 hpi_mixer_close(u32 h_mixer) |
1496 | { | 1246 | { |
1497 | struct hpi_message hm; | 1247 | struct hpi_message hm; |
1498 | struct hpi_response hr; | 1248 | struct hpi_response hr; |
1249 | |||
1499 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE); | 1250 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE); |
1500 | u32TOINDEX(h_mixer, &hm.adapter_index); | 1251 | if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) |
1252 | return HPI_ERROR_INVALID_HANDLE; | ||
1253 | |||
1501 | hpi_send_recv(&hm, &hr); | 1254 | hpi_send_recv(&hm, &hr); |
1502 | return hr.error; | 1255 | return hr.error; |
1503 | } | 1256 | } |
1504 | 1257 | ||
1505 | u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer, | 1258 | u16 hpi_mixer_get_control(u32 h_mixer, u16 src_node_type, |
1506 | u16 src_node_type, u16 src_node_type_index, u16 dst_node_type, | 1259 | u16 src_node_type_index, u16 dst_node_type, u16 dst_node_type_index, |
1507 | u16 dst_node_type_index, u16 control_type, u32 *ph_control) | 1260 | u16 control_type, u32 *ph_control) |
1508 | { | 1261 | { |
1509 | struct hpi_message hm; | 1262 | struct hpi_message hm; |
1510 | struct hpi_response hr; | 1263 | struct hpi_response hr; |
1511 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, | 1264 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, |
1512 | HPI_MIXER_GET_CONTROL); | 1265 | HPI_MIXER_GET_CONTROL); |
1513 | u32TOINDEX(h_mixer, &hm.adapter_index); | 1266 | if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) |
1267 | return HPI_ERROR_INVALID_HANDLE; | ||
1514 | hm.u.m.node_type1 = src_node_type; | 1268 | hm.u.m.node_type1 = src_node_type; |
1515 | hm.u.m.node_index1 = src_node_type_index; | 1269 | hm.u.m.node_index1 = src_node_type_index; |
1516 | hm.u.m.node_type2 = dst_node_type; | 1270 | hm.u.m.node_type2 = dst_node_type; |
@@ -1528,16 +1282,16 @@ u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer, | |||
1528 | return hr.error; | 1282 | return hr.error; |
1529 | } | 1283 | } |
1530 | 1284 | ||
1531 | u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys, | 1285 | u16 hpi_mixer_get_control_by_index(u32 h_mixer, u16 control_index, |
1532 | u32 h_mixer, u16 control_index, u16 *pw_src_node_type, | 1286 | u16 *pw_src_node_type, u16 *pw_src_node_index, u16 *pw_dst_node_type, |
1533 | u16 *pw_src_node_index, u16 *pw_dst_node_type, u16 *pw_dst_node_index, | 1287 | u16 *pw_dst_node_index, u16 *pw_control_type, u32 *ph_control) |
1534 | u16 *pw_control_type, u32 *ph_control) | ||
1535 | { | 1288 | { |
1536 | struct hpi_message hm; | 1289 | struct hpi_message hm; |
1537 | struct hpi_response hr; | 1290 | struct hpi_response hr; |
1538 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, | 1291 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, |
1539 | HPI_MIXER_GET_CONTROL_BY_INDEX); | 1292 | HPI_MIXER_GET_CONTROL_BY_INDEX); |
1540 | u32TOINDEX(h_mixer, &hm.adapter_index); | 1293 | if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) |
1294 | return HPI_ERROR_INVALID_HANDLE; | ||
1541 | hm.u.m.control_index = control_index; | 1295 | hm.u.m.control_index = control_index; |
1542 | hpi_send_recv(&hm, &hr); | 1296 | hpi_send_recv(&hm, &hr); |
1543 | 1297 | ||
@@ -1562,13 +1316,14 @@ u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys, | |||
1562 | return hr.error; | 1316 | return hr.error; |
1563 | } | 1317 | } |
1564 | 1318 | ||
1565 | u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer, | 1319 | u16 hpi_mixer_store(u32 h_mixer, enum HPI_MIXER_STORE_COMMAND command, |
1566 | enum HPI_MIXER_STORE_COMMAND command, u16 index) | 1320 | u16 index) |
1567 | { | 1321 | { |
1568 | struct hpi_message hm; | 1322 | struct hpi_message hm; |
1569 | struct hpi_response hr; | 1323 | struct hpi_response hr; |
1570 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_STORE); | 1324 | hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_STORE); |
1571 | u32TOINDEX(h_mixer, &hm.adapter_index); | 1325 | if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL)) |
1326 | return HPI_ERROR_INVALID_HANDLE; | ||
1572 | hm.u.mx.store.command = command; | 1327 | hm.u.mx.store.command = command; |
1573 | hm.u.mx.store.index = index; | 1328 | hm.u.mx.store.index = index; |
1574 | hpi_send_recv(&hm, &hr); | 1329 | hpi_send_recv(&hm, &hr); |
@@ -1576,16 +1331,16 @@ u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer, | |||
1576 | } | 1331 | } |
1577 | 1332 | ||
1578 | static | 1333 | static |
1579 | u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys, | 1334 | u16 hpi_control_param_set(const u32 h_control, const u16 attrib, |
1580 | const u32 h_control, const u16 attrib, const u32 param1, | 1335 | const u32 param1, const u32 param2) |
1581 | const u32 param2) | ||
1582 | { | 1336 | { |
1583 | struct hpi_message hm; | 1337 | struct hpi_message hm; |
1584 | struct hpi_response hr; | 1338 | struct hpi_response hr; |
1585 | 1339 | ||
1586 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1340 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1587 | HPI_CONTROL_SET_STATE); | 1341 | HPI_CONTROL_SET_STATE); |
1588 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1342 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1343 | return HPI_ERROR_INVALID_HANDLE; | ||
1589 | hm.u.c.attribute = attrib; | 1344 | hm.u.c.attribute = attrib; |
1590 | hm.u.c.param1 = param1; | 1345 | hm.u.c.param1 = param1; |
1591 | hm.u.c.param2 = param2; | 1346 | hm.u.c.param2 = param2; |
@@ -1601,7 +1356,8 @@ static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0, | |||
1601 | 1356 | ||
1602 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1357 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1603 | HPI_CONTROL_SET_STATE); | 1358 | HPI_CONTROL_SET_STATE); |
1604 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1359 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1360 | return HPI_ERROR_INVALID_HANDLE; | ||
1605 | hm.u.c.attribute = attrib; | 1361 | hm.u.c.attribute = attrib; |
1606 | hm.u.c.an_log_value[0] = sv0; | 1362 | hm.u.c.an_log_value[0] = sv0; |
1607 | hm.u.c.an_log_value[1] = sv1; | 1363 | hm.u.c.an_log_value[1] = sv1; |
@@ -1610,16 +1366,16 @@ static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0, | |||
1610 | } | 1366 | } |
1611 | 1367 | ||
1612 | static | 1368 | static |
1613 | u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys, | 1369 | u16 hpi_control_param_get(const u32 h_control, const u16 attrib, u32 param1, |
1614 | const u32 h_control, const u16 attrib, u32 param1, u32 param2, | 1370 | u32 param2, u32 *pparam1, u32 *pparam2) |
1615 | u32 *pparam1, u32 *pparam2) | ||
1616 | { | 1371 | { |
1617 | struct hpi_message hm; | 1372 | struct hpi_message hm; |
1618 | struct hpi_response hr; | 1373 | struct hpi_response hr; |
1619 | 1374 | ||
1620 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1375 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1621 | HPI_CONTROL_GET_STATE); | 1376 | HPI_CONTROL_GET_STATE); |
1622 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1377 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1378 | return HPI_ERROR_INVALID_HANDLE; | ||
1623 | hm.u.c.attribute = attrib; | 1379 | hm.u.c.attribute = attrib; |
1624 | hm.u.c.param1 = param1; | 1380 | hm.u.c.param1 = param1; |
1625 | hm.u.c.param2 = param2; | 1381 | hm.u.c.param2 = param2; |
@@ -1632,19 +1388,20 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys, | |||
1632 | return hr.error; | 1388 | return hr.error; |
1633 | } | 1389 | } |
1634 | 1390 | ||
1635 | #define hpi_control_param1_get(s, h, a, p1) \ | 1391 | #define hpi_control_param1_get(h, a, p1) \ |
1636 | hpi_control_param_get(s, h, a, 0, 0, p1, NULL) | 1392 | hpi_control_param_get(h, a, 0, 0, p1, NULL) |
1637 | #define hpi_control_param2_get(s, h, a, p1, p2) \ | 1393 | #define hpi_control_param2_get(h, a, p1, p2) \ |
1638 | hpi_control_param_get(s, h, a, 0, 0, p1, p2) | 1394 | hpi_control_param_get(h, a, 0, 0, p1, p2) |
1639 | 1395 | ||
1640 | static u16 hpi_control_log_get2(const struct hpi_hsubsys *ph_subsys, | 1396 | static u16 hpi_control_log_get2(u32 h_control, u16 attrib, short *sv0, |
1641 | u32 h_control, u16 attrib, short *sv0, short *sv1) | 1397 | short *sv1) |
1642 | { | 1398 | { |
1643 | struct hpi_message hm; | 1399 | struct hpi_message hm; |
1644 | struct hpi_response hr; | 1400 | struct hpi_response hr; |
1645 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1401 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1646 | HPI_CONTROL_GET_STATE); | 1402 | HPI_CONTROL_GET_STATE); |
1647 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1403 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1404 | return HPI_ERROR_INVALID_HANDLE; | ||
1648 | hm.u.c.attribute = attrib; | 1405 | hm.u.c.attribute = attrib; |
1649 | 1406 | ||
1650 | hpi_send_recv(&hm, &hr); | 1407 | hpi_send_recv(&hm, &hr); |
@@ -1655,8 +1412,7 @@ static u16 hpi_control_log_get2(const struct hpi_hsubsys *ph_subsys, | |||
1655 | } | 1412 | } |
1656 | 1413 | ||
1657 | static | 1414 | static |
1658 | u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys, | 1415 | u16 hpi_control_query(const u32 h_control, const u16 attrib, const u32 index, |
1659 | const u32 h_control, const u16 attrib, const u32 index, | ||
1660 | const u32 param, u32 *psetting) | 1416 | const u32 param, u32 *psetting) |
1661 | { | 1417 | { |
1662 | struct hpi_message hm; | 1418 | struct hpi_message hm; |
@@ -1664,7 +1420,8 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys, | |||
1664 | 1420 | ||
1665 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1421 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1666 | HPI_CONTROL_GET_INFO); | 1422 | HPI_CONTROL_GET_INFO); |
1667 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1423 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1424 | return HPI_ERROR_INVALID_HANDLE; | ||
1668 | 1425 | ||
1669 | hm.u.c.attribute = attrib; | 1426 | hm.u.c.attribute = attrib; |
1670 | hm.u.c.param1 = index; | 1427 | hm.u.c.param1 = index; |
@@ -1682,7 +1439,7 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute, | |||
1682 | unsigned int sub_string_index = 0, j = 0; | 1439 | unsigned int sub_string_index = 0, j = 0; |
1683 | char c = 0; | 1440 | char c = 0; |
1684 | unsigned int n = 0; | 1441 | unsigned int n = 0; |
1685 | u16 hE = 0; | 1442 | u16 err = 0; |
1686 | 1443 | ||
1687 | if ((string_length < 1) || (string_length > 256)) | 1444 | if ((string_length < 1) || (string_length > 256)) |
1688 | return HPI_ERROR_INVALID_CONTROL_VALUE; | 1445 | return HPI_ERROR_INVALID_CONTROL_VALUE; |
@@ -1693,7 +1450,9 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute, | |||
1693 | 1450 | ||
1694 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1451 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1695 | HPI_CONTROL_GET_STATE); | 1452 | HPI_CONTROL_GET_STATE); |
1696 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1453 | if (hpi_handle_indexes(h_control, &hm.adapter_index, |
1454 | &hm.obj_index)) | ||
1455 | return HPI_ERROR_INVALID_HANDLE; | ||
1697 | hm.u.c.attribute = attribute; | 1456 | hm.u.c.attribute = attribute; |
1698 | hm.u.c.param1 = sub_string_index; | 1457 | hm.u.c.param1 = sub_string_index; |
1699 | hm.u.c.param2 = 0; | 1458 | hm.u.c.param2 = 0; |
@@ -1705,7 +1464,7 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute, | |||
1705 | return HPI_ERROR_INVALID_CONTROL_VALUE; | 1464 | return HPI_ERROR_INVALID_CONTROL_VALUE; |
1706 | 1465 | ||
1707 | if (hr.error) { | 1466 | if (hr.error) { |
1708 | hE = hr.error; | 1467 | err = hr.error; |
1709 | break; | 1468 | break; |
1710 | } | 1469 | } |
1711 | for (j = 0; j < 8; j++) { | 1470 | for (j = 0; j < 8; j++) { |
@@ -1714,7 +1473,7 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute, | |||
1714 | n++; | 1473 | n++; |
1715 | if (n >= string_length) { | 1474 | if (n >= string_length) { |
1716 | psz_string[string_length - 1] = 0; | 1475 | psz_string[string_length - 1] = 0; |
1717 | hE = HPI_ERROR_INVALID_CONTROL_VALUE; | 1476 | err = HPI_ERROR_INVALID_CONTROL_VALUE; |
1718 | break; | 1477 | break; |
1719 | } | 1478 | } |
1720 | if (c == 0) | 1479 | if (c == 0) |
@@ -1730,57 +1489,52 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute, | |||
1730 | if (c == 0) | 1489 | if (c == 0) |
1731 | break; | 1490 | break; |
1732 | } | 1491 | } |
1733 | return hE; | 1492 | return err; |
1734 | } | 1493 | } |
1735 | 1494 | ||
1736 | u16 HPI_AESEBU__receiver_query_format(const struct hpi_hsubsys *ph_subsys, | 1495 | u16 hpi_aesebu_receiver_query_format(const u32 h_aes_rx, const u32 index, |
1737 | const u32 h_aes_rx, const u32 index, u16 *pw_format) | 1496 | u16 *pw_format) |
1738 | { | 1497 | { |
1739 | u32 qr; | 1498 | u32 qr; |
1740 | u16 err; | 1499 | u16 err; |
1741 | 1500 | ||
1742 | err = hpi_control_query(ph_subsys, h_aes_rx, HPI_AESEBURX_FORMAT, | 1501 | err = hpi_control_query(h_aes_rx, HPI_AESEBURX_FORMAT, index, 0, &qr); |
1743 | index, 0, &qr); | ||
1744 | *pw_format = (u16)qr; | 1502 | *pw_format = (u16)qr; |
1745 | return err; | 1503 | return err; |
1746 | } | 1504 | } |
1747 | 1505 | ||
1748 | u16 HPI_AESEBU__receiver_set_format(const struct hpi_hsubsys *ph_subsys, | 1506 | u16 hpi_aesebu_receiver_set_format(u32 h_control, u16 format) |
1749 | u32 h_control, u16 format) | ||
1750 | { | 1507 | { |
1751 | return hpi_control_param_set(ph_subsys, h_control, | 1508 | return hpi_control_param_set(h_control, HPI_AESEBURX_FORMAT, format, |
1752 | HPI_AESEBURX_FORMAT, format, 0); | 1509 | 0); |
1753 | } | 1510 | } |
1754 | 1511 | ||
1755 | u16 HPI_AESEBU__receiver_get_format(const struct hpi_hsubsys *ph_subsys, | 1512 | u16 hpi_aesebu_receiver_get_format(u32 h_control, u16 *pw_format) |
1756 | u32 h_control, u16 *pw_format) | ||
1757 | { | 1513 | { |
1758 | u16 err; | 1514 | u16 err; |
1759 | u32 param; | 1515 | u32 param; |
1760 | 1516 | ||
1761 | err = hpi_control_param1_get(ph_subsys, h_control, | 1517 | err = hpi_control_param1_get(h_control, HPI_AESEBURX_FORMAT, ¶m); |
1762 | HPI_AESEBURX_FORMAT, ¶m); | ||
1763 | if (!err && pw_format) | 1518 | if (!err && pw_format) |
1764 | *pw_format = (u16)param; | 1519 | *pw_format = (u16)param; |
1765 | 1520 | ||
1766 | return err; | 1521 | return err; |
1767 | } | 1522 | } |
1768 | 1523 | ||
1769 | u16 HPI_AESEBU__receiver_get_sample_rate(const struct hpi_hsubsys *ph_subsys, | 1524 | u16 hpi_aesebu_receiver_get_sample_rate(u32 h_control, u32 *psample_rate) |
1770 | u32 h_control, u32 *psample_rate) | ||
1771 | { | 1525 | { |
1772 | return hpi_control_param1_get(ph_subsys, h_control, | 1526 | return hpi_control_param1_get(h_control, HPI_AESEBURX_SAMPLERATE, |
1773 | HPI_AESEBURX_SAMPLERATE, psample_rate); | 1527 | psample_rate); |
1774 | } | 1528 | } |
1775 | 1529 | ||
1776 | u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys, | 1530 | u16 hpi_aesebu_receiver_get_user_data(u32 h_control, u16 index, u16 *pw_data) |
1777 | u32 h_control, u16 index, u16 *pw_data) | ||
1778 | { | 1531 | { |
1779 | struct hpi_message hm; | 1532 | struct hpi_message hm; |
1780 | struct hpi_response hr; | 1533 | struct hpi_response hr; |
1781 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1534 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1782 | HPI_CONTROL_GET_STATE); | 1535 | HPI_CONTROL_GET_STATE); |
1783 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1536 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1537 | return HPI_ERROR_INVALID_HANDLE; | ||
1784 | hm.u.c.attribute = HPI_AESEBURX_USERDATA; | 1538 | hm.u.c.attribute = HPI_AESEBURX_USERDATA; |
1785 | hm.u.c.param1 = index; | 1539 | hm.u.c.param1 = index; |
1786 | 1540 | ||
@@ -1791,14 +1545,15 @@ u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys, | |||
1791 | return hr.error; | 1545 | return hr.error; |
1792 | } | 1546 | } |
1793 | 1547 | ||
1794 | u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys | 1548 | u16 hpi_aesebu_receiver_get_channel_status(u32 h_control, u16 index, |
1795 | *ph_subsys, u32 h_control, u16 index, u16 *pw_data) | 1549 | u16 *pw_data) |
1796 | { | 1550 | { |
1797 | struct hpi_message hm; | 1551 | struct hpi_message hm; |
1798 | struct hpi_response hr; | 1552 | struct hpi_response hr; |
1799 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1553 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1800 | HPI_CONTROL_GET_STATE); | 1554 | HPI_CONTROL_GET_STATE); |
1801 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1555 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1556 | return HPI_ERROR_INVALID_HANDLE; | ||
1802 | hm.u.c.attribute = HPI_AESEBURX_CHANNELSTATUS; | 1557 | hm.u.c.attribute = HPI_AESEBURX_CHANNELSTATUS; |
1803 | hm.u.c.param1 = index; | 1558 | hm.u.c.param1 = index; |
1804 | 1559 | ||
@@ -1809,101 +1564,93 @@ u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys | |||
1809 | return hr.error; | 1564 | return hr.error; |
1810 | } | 1565 | } |
1811 | 1566 | ||
1812 | u16 HPI_AESEBU__receiver_get_error_status(const struct hpi_hsubsys *ph_subsys, | 1567 | u16 hpi_aesebu_receiver_get_error_status(u32 h_control, u16 *pw_error_data) |
1813 | u32 h_control, u16 *pw_error_data) | ||
1814 | { | 1568 | { |
1815 | u32 error_data = 0; | 1569 | u32 error_data = 0; |
1816 | u16 error = 0; | 1570 | u16 err = 0; |
1817 | 1571 | ||
1818 | error = hpi_control_param1_get(ph_subsys, h_control, | 1572 | err = hpi_control_param1_get(h_control, HPI_AESEBURX_ERRORSTATUS, |
1819 | HPI_AESEBURX_ERRORSTATUS, &error_data); | 1573 | &error_data); |
1820 | if (pw_error_data) | 1574 | if (pw_error_data) |
1821 | *pw_error_data = (u16)error_data; | 1575 | *pw_error_data = (u16)error_data; |
1822 | return error; | 1576 | return err; |
1823 | } | 1577 | } |
1824 | 1578 | ||
1825 | u16 HPI_AESEBU__transmitter_set_sample_rate(const struct hpi_hsubsys | 1579 | u16 hpi_aesebu_transmitter_set_sample_rate(u32 h_control, u32 sample_rate) |
1826 | *ph_subsys, u32 h_control, u32 sample_rate) | ||
1827 | { | 1580 | { |
1828 | return hpi_control_param_set(ph_subsys, h_control, | 1581 | return hpi_control_param_set(h_control, HPI_AESEBUTX_SAMPLERATE, |
1829 | HPI_AESEBUTX_SAMPLERATE, sample_rate, 0); | 1582 | sample_rate, 0); |
1830 | } | 1583 | } |
1831 | 1584 | ||
1832 | u16 HPI_AESEBU__transmitter_set_user_data(const struct hpi_hsubsys *ph_subsys, | 1585 | u16 hpi_aesebu_transmitter_set_user_data(u32 h_control, u16 index, u16 data) |
1833 | u32 h_control, u16 index, u16 data) | ||
1834 | { | 1586 | { |
1835 | return hpi_control_param_set(ph_subsys, h_control, | 1587 | return hpi_control_param_set(h_control, HPI_AESEBUTX_USERDATA, index, |
1836 | HPI_AESEBUTX_USERDATA, index, data); | 1588 | data); |
1837 | } | 1589 | } |
1838 | 1590 | ||
1839 | u16 HPI_AESEBU__transmitter_set_channel_status(const struct hpi_hsubsys | 1591 | u16 hpi_aesebu_transmitter_set_channel_status(u32 h_control, u16 index, |
1840 | *ph_subsys, u32 h_control, u16 index, u16 data) | 1592 | u16 data) |
1841 | { | 1593 | { |
1842 | return hpi_control_param_set(ph_subsys, h_control, | 1594 | return hpi_control_param_set(h_control, HPI_AESEBUTX_CHANNELSTATUS, |
1843 | HPI_AESEBUTX_CHANNELSTATUS, index, data); | 1595 | index, data); |
1844 | } | 1596 | } |
1845 | 1597 | ||
1846 | u16 HPI_AESEBU__transmitter_get_channel_status(const struct hpi_hsubsys | 1598 | u16 hpi_aesebu_transmitter_get_channel_status(u32 h_control, u16 index, |
1847 | *ph_subsys, u32 h_control, u16 index, u16 *pw_data) | 1599 | u16 *pw_data) |
1848 | { | 1600 | { |
1849 | return HPI_ERROR_INVALID_OPERATION; | 1601 | return HPI_ERROR_INVALID_OPERATION; |
1850 | } | 1602 | } |
1851 | 1603 | ||
1852 | u16 HPI_AESEBU__transmitter_query_format(const struct hpi_hsubsys *ph_subsys, | 1604 | u16 hpi_aesebu_transmitter_query_format(const u32 h_aes_tx, const u32 index, |
1853 | const u32 h_aes_tx, const u32 index, u16 *pw_format) | 1605 | u16 *pw_format) |
1854 | { | 1606 | { |
1855 | u32 qr; | 1607 | u32 qr; |
1856 | u16 err; | 1608 | u16 err; |
1857 | 1609 | ||
1858 | err = hpi_control_query(ph_subsys, h_aes_tx, HPI_AESEBUTX_FORMAT, | 1610 | err = hpi_control_query(h_aes_tx, HPI_AESEBUTX_FORMAT, index, 0, &qr); |
1859 | index, 0, &qr); | ||
1860 | *pw_format = (u16)qr; | 1611 | *pw_format = (u16)qr; |
1861 | return err; | 1612 | return err; |
1862 | } | 1613 | } |
1863 | 1614 | ||
1864 | u16 HPI_AESEBU__transmitter_set_format(const struct hpi_hsubsys *ph_subsys, | 1615 | u16 hpi_aesebu_transmitter_set_format(u32 h_control, u16 output_format) |
1865 | u32 h_control, u16 output_format) | ||
1866 | { | 1616 | { |
1867 | return hpi_control_param_set(ph_subsys, h_control, | 1617 | return hpi_control_param_set(h_control, HPI_AESEBUTX_FORMAT, |
1868 | HPI_AESEBUTX_FORMAT, output_format, 0); | 1618 | output_format, 0); |
1869 | } | 1619 | } |
1870 | 1620 | ||
1871 | u16 HPI_AESEBU__transmitter_get_format(const struct hpi_hsubsys *ph_subsys, | 1621 | u16 hpi_aesebu_transmitter_get_format(u32 h_control, u16 *pw_output_format) |
1872 | u32 h_control, u16 *pw_output_format) | ||
1873 | { | 1622 | { |
1874 | u16 err; | 1623 | u16 err; |
1875 | u32 param; | 1624 | u32 param; |
1876 | 1625 | ||
1877 | err = hpi_control_param1_get(ph_subsys, h_control, | 1626 | err = hpi_control_param1_get(h_control, HPI_AESEBUTX_FORMAT, ¶m); |
1878 | HPI_AESEBUTX_FORMAT, ¶m); | ||
1879 | if (!err && pw_output_format) | 1627 | if (!err && pw_output_format) |
1880 | *pw_output_format = (u16)param; | 1628 | *pw_output_format = (u16)param; |
1881 | 1629 | ||
1882 | return err; | 1630 | return err; |
1883 | } | 1631 | } |
1884 | 1632 | ||
1885 | u16 hpi_bitstream_set_clock_edge(const struct hpi_hsubsys *ph_subsys, | 1633 | u16 hpi_bitstream_set_clock_edge(u32 h_control, u16 edge_type) |
1886 | u32 h_control, u16 edge_type) | ||
1887 | { | 1634 | { |
1888 | return hpi_control_param_set(ph_subsys, h_control, | 1635 | return hpi_control_param_set(h_control, HPI_BITSTREAM_CLOCK_EDGE, |
1889 | HPI_BITSTREAM_CLOCK_EDGE, edge_type, 0); | 1636 | edge_type, 0); |
1890 | } | 1637 | } |
1891 | 1638 | ||
1892 | u16 hpi_bitstream_set_data_polarity(const struct hpi_hsubsys *ph_subsys, | 1639 | u16 hpi_bitstream_set_data_polarity(u32 h_control, u16 polarity) |
1893 | u32 h_control, u16 polarity) | ||
1894 | { | 1640 | { |
1895 | return hpi_control_param_set(ph_subsys, h_control, | 1641 | return hpi_control_param_set(h_control, HPI_BITSTREAM_DATA_POLARITY, |
1896 | HPI_BITSTREAM_DATA_POLARITY, polarity, 0); | 1642 | polarity, 0); |
1897 | } | 1643 | } |
1898 | 1644 | ||
1899 | u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys, | 1645 | u16 hpi_bitstream_get_activity(u32 h_control, u16 *pw_clk_activity, |
1900 | u32 h_control, u16 *pw_clk_activity, u16 *pw_data_activity) | 1646 | u16 *pw_data_activity) |
1901 | { | 1647 | { |
1902 | struct hpi_message hm; | 1648 | struct hpi_message hm; |
1903 | struct hpi_response hr; | 1649 | struct hpi_response hr; |
1904 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1650 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
1905 | HPI_CONTROL_GET_STATE); | 1651 | HPI_CONTROL_GET_STATE); |
1906 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1652 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1653 | return HPI_ERROR_INVALID_HANDLE; | ||
1907 | hm.u.c.attribute = HPI_BITSTREAM_ACTIVITY; | 1654 | hm.u.c.attribute = HPI_BITSTREAM_ACTIVITY; |
1908 | hpi_send_recv(&hm, &hr); | 1655 | hpi_send_recv(&hm, &hr); |
1909 | if (pw_clk_activity) | 1656 | if (pw_clk_activity) |
@@ -1913,45 +1660,43 @@ u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys, | |||
1913 | return hr.error; | 1660 | return hr.error; |
1914 | } | 1661 | } |
1915 | 1662 | ||
1916 | u16 hpi_channel_mode_query_mode(const struct hpi_hsubsys *ph_subsys, | 1663 | u16 hpi_channel_mode_query_mode(const u32 h_mode, const u32 index, |
1917 | const u32 h_mode, const u32 index, u16 *pw_mode) | 1664 | u16 *pw_mode) |
1918 | { | 1665 | { |
1919 | u32 qr; | 1666 | u32 qr; |
1920 | u16 err; | 1667 | u16 err; |
1921 | 1668 | ||
1922 | err = hpi_control_query(ph_subsys, h_mode, HPI_CHANNEL_MODE_MODE, | 1669 | err = hpi_control_query(h_mode, HPI_CHANNEL_MODE_MODE, index, 0, &qr); |
1923 | index, 0, &qr); | ||
1924 | *pw_mode = (u16)qr; | 1670 | *pw_mode = (u16)qr; |
1925 | return err; | 1671 | return err; |
1926 | } | 1672 | } |
1927 | 1673 | ||
1928 | u16 hpi_channel_mode_set(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1674 | u16 hpi_channel_mode_set(u32 h_control, u16 mode) |
1929 | u16 mode) | ||
1930 | { | 1675 | { |
1931 | return hpi_control_param_set(ph_subsys, h_control, | 1676 | return hpi_control_param_set(h_control, HPI_CHANNEL_MODE_MODE, mode, |
1932 | HPI_CHANNEL_MODE_MODE, mode, 0); | 1677 | 0); |
1933 | } | 1678 | } |
1934 | 1679 | ||
1935 | u16 hpi_channel_mode_get(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1680 | u16 hpi_channel_mode_get(u32 h_control, u16 *mode) |
1936 | u16 *mode) | ||
1937 | { | 1681 | { |
1938 | u32 mode32 = 0; | 1682 | u32 mode32 = 0; |
1939 | u16 error = hpi_control_param1_get(ph_subsys, h_control, | 1683 | u16 err = hpi_control_param1_get(h_control, |
1940 | HPI_CHANNEL_MODE_MODE, &mode32); | 1684 | HPI_CHANNEL_MODE_MODE, &mode32); |
1941 | if (mode) | 1685 | if (mode) |
1942 | *mode = (u16)mode32; | 1686 | *mode = (u16)mode32; |
1943 | return error; | 1687 | return err; |
1944 | } | 1688 | } |
1945 | 1689 | ||
1946 | u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1690 | u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count, |
1947 | u32 hmi_address, u32 byte_count, u8 *pb_data) | 1691 | u8 *pb_data) |
1948 | { | 1692 | { |
1949 | struct hpi_message hm; | 1693 | struct hpi_message hm; |
1950 | struct hpi_response hr; | 1694 | struct hpi_response hr; |
1951 | 1695 | ||
1952 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, | 1696 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, |
1953 | HPI_CONTROL_SET_STATE); | 1697 | HPI_CONTROL_SET_STATE); |
1954 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1698 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1699 | return HPI_ERROR_INVALID_HANDLE; | ||
1955 | 1700 | ||
1956 | hm.u.cx.u.cobranet_data.byte_count = byte_count; | 1701 | hm.u.cx.u.cobranet_data.byte_count = byte_count; |
1957 | hm.u.cx.u.cobranet_data.hmi_address = hmi_address; | 1702 | hm.u.cx.u.cobranet_data.hmi_address = hmi_address; |
@@ -1969,15 +1714,16 @@ u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
1969 | return hr.error; | 1714 | return hr.error; |
1970 | } | 1715 | } |
1971 | 1716 | ||
1972 | u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1717 | u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count, |
1973 | u32 hmi_address, u32 max_byte_count, u32 *pbyte_count, u8 *pb_data) | 1718 | u32 *pbyte_count, u8 *pb_data) |
1974 | { | 1719 | { |
1975 | struct hpi_message hm; | 1720 | struct hpi_message hm; |
1976 | struct hpi_response hr; | 1721 | struct hpi_response hr; |
1977 | 1722 | ||
1978 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, | 1723 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, |
1979 | HPI_CONTROL_GET_STATE); | 1724 | HPI_CONTROL_GET_STATE); |
1980 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1725 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1726 | return HPI_ERROR_INVALID_HANDLE; | ||
1981 | 1727 | ||
1982 | hm.u.cx.u.cobranet_data.byte_count = max_byte_count; | 1728 | hm.u.cx.u.cobranet_data.byte_count = max_byte_count; |
1983 | hm.u.cx.u.cobranet_data.hmi_address = hmi_address; | 1729 | hm.u.cx.u.cobranet_data.hmi_address = hmi_address; |
@@ -2008,16 +1754,16 @@ u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
2008 | return hr.error; | 1754 | return hr.error; |
2009 | } | 1755 | } |
2010 | 1756 | ||
2011 | u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys, | 1757 | u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus, |
2012 | u32 h_control, u32 *pstatus, u32 *preadable_size, | 1758 | u32 *preadable_size, u32 *pwriteable_size) |
2013 | u32 *pwriteable_size) | ||
2014 | { | 1759 | { |
2015 | struct hpi_message hm; | 1760 | struct hpi_message hm; |
2016 | struct hpi_response hr; | 1761 | struct hpi_response hr; |
2017 | 1762 | ||
2018 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, | 1763 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX, |
2019 | HPI_CONTROL_GET_STATE); | 1764 | HPI_CONTROL_GET_STATE); |
2020 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1765 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1766 | return HPI_ERROR_INVALID_HANDLE; | ||
2021 | 1767 | ||
2022 | hm.u.cx.attribute = HPI_COBRANET_GET_STATUS; | 1768 | hm.u.cx.attribute = HPI_COBRANET_GET_STATUS; |
2023 | 1769 | ||
@@ -2035,177 +1781,176 @@ u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys, | |||
2035 | return hr.error; | 1781 | return hr.error; |
2036 | } | 1782 | } |
2037 | 1783 | ||
2038 | u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys, | 1784 | u16 hpi_cobranet_get_ip_address(u32 h_control, u32 *pdw_ip_address) |
2039 | u32 h_control, u32 *pi_paddress) | ||
2040 | { | 1785 | { |
2041 | u32 byte_count; | 1786 | u32 byte_count; |
2042 | u32 iP; | 1787 | u32 iP; |
2043 | u16 error; | 1788 | u16 err; |
2044 | 1789 | ||
2045 | error = hpi_cobranet_hmi_read(ph_subsys, h_control, | 1790 | err = hpi_cobranet_hmi_read(h_control, |
2046 | HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count, | 1791 | HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count, |
2047 | (u8 *)&iP); | 1792 | (u8 *)&iP); |
2048 | 1793 | ||
2049 | *pi_paddress = | 1794 | *pdw_ip_address = |
2050 | ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP & | 1795 | ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP & |
2051 | 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8); | 1796 | 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8); |
2052 | 1797 | ||
2053 | if (error) | 1798 | if (err) |
2054 | *pi_paddress = 0; | 1799 | *pdw_ip_address = 0; |
2055 | 1800 | ||
2056 | return error; | 1801 | return err; |
2057 | 1802 | ||
2058 | } | 1803 | } |
2059 | 1804 | ||
2060 | u16 hpi_cobranet_setI_paddress(const struct hpi_hsubsys *ph_subsys, | 1805 | u16 hpi_cobranet_set_ip_address(u32 h_control, u32 dw_ip_address) |
2061 | u32 h_control, u32 i_paddress) | ||
2062 | { | 1806 | { |
2063 | u32 iP; | 1807 | u32 iP; |
2064 | u16 error; | 1808 | u16 err; |
2065 | 1809 | ||
2066 | iP = ((i_paddress & 0xff000000) >> 8) | ((i_paddress & 0x00ff0000) << | 1810 | iP = ((dw_ip_address & 0xff000000) >> 8) | ((dw_ip_address & |
2067 | 8) | ((i_paddress & 0x0000ff00) >> 8) | ((i_paddress & | 1811 | 0x00ff0000) << 8) | ((dw_ip_address & 0x0000ff00) >> |
2068 | 0x000000ff) << 8); | 1812 | 8) | ((dw_ip_address & 0x000000ff) << 8); |
2069 | 1813 | ||
2070 | error = hpi_cobranet_hmi_write(ph_subsys, h_control, | 1814 | err = hpi_cobranet_hmi_write(h_control, |
2071 | HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, (u8 *)&iP); | 1815 | HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, (u8 *)&iP); |
2072 | 1816 | ||
2073 | return error; | 1817 | return err; |
2074 | 1818 | ||
2075 | } | 1819 | } |
2076 | 1820 | ||
2077 | u16 hpi_cobranet_get_staticI_paddress(const struct hpi_hsubsys *ph_subsys, | 1821 | u16 hpi_cobranet_get_static_ip_address(u32 h_control, u32 *pdw_ip_address) |
2078 | u32 h_control, u32 *pi_paddress) | ||
2079 | { | 1822 | { |
2080 | u32 byte_count; | 1823 | u32 byte_count; |
2081 | u32 iP; | 1824 | u32 iP; |
2082 | u16 error; | 1825 | u16 err; |
2083 | error = hpi_cobranet_hmi_read(ph_subsys, h_control, | 1826 | err = hpi_cobranet_hmi_read(h_control, |
2084 | HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, &byte_count, | 1827 | HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, &byte_count, |
2085 | (u8 *)&iP); | 1828 | (u8 *)&iP); |
2086 | 1829 | ||
2087 | *pi_paddress = | 1830 | *pdw_ip_address = |
2088 | ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP & | 1831 | ((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP & |
2089 | 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8); | 1832 | 0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8); |
2090 | 1833 | ||
2091 | if (error) | 1834 | if (err) |
2092 | *pi_paddress = 0; | 1835 | *pdw_ip_address = 0; |
2093 | 1836 | ||
2094 | return error; | 1837 | return err; |
2095 | 1838 | ||
2096 | } | 1839 | } |
2097 | 1840 | ||
2098 | u16 hpi_cobranet_set_staticI_paddress(const struct hpi_hsubsys *ph_subsys, | 1841 | u16 hpi_cobranet_set_static_ip_address(u32 h_control, u32 dw_ip_address) |
2099 | u32 h_control, u32 i_paddress) | ||
2100 | { | 1842 | { |
2101 | u32 iP; | 1843 | u32 iP; |
2102 | u16 error; | 1844 | u16 err; |
2103 | 1845 | ||
2104 | iP = ((i_paddress & 0xff000000) >> 8) | ((i_paddress & 0x00ff0000) << | 1846 | iP = ((dw_ip_address & 0xff000000) >> 8) | ((dw_ip_address & |
2105 | 8) | ((i_paddress & 0x0000ff00) >> 8) | ((i_paddress & | 1847 | 0x00ff0000) << 8) | ((dw_ip_address & 0x0000ff00) >> |
2106 | 0x000000ff) << 8); | 1848 | 8) | ((dw_ip_address & 0x000000ff) << 8); |
2107 | 1849 | ||
2108 | error = hpi_cobranet_hmi_write(ph_subsys, h_control, | 1850 | err = hpi_cobranet_hmi_write(h_control, |
2109 | HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, (u8 *)&iP); | 1851 | HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, (u8 *)&iP); |
2110 | 1852 | ||
2111 | return error; | 1853 | return err; |
2112 | 1854 | ||
2113 | } | 1855 | } |
2114 | 1856 | ||
2115 | u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys, | 1857 | u16 hpi_cobranet_get_macaddress(u32 h_control, u32 *p_mac_msbs, |
2116 | u32 h_control, u32 *pmAC_MS_bs, u32 *pmAC_LS_bs) | 1858 | u32 *p_mac_lsbs) |
2117 | { | 1859 | { |
2118 | u32 byte_count; | 1860 | u32 byte_count; |
2119 | u16 error; | 1861 | u16 err; |
2120 | u32 mAC; | 1862 | u32 mac; |
2121 | 1863 | ||
2122 | error = hpi_cobranet_hmi_read(ph_subsys, h_control, | 1864 | err = hpi_cobranet_hmi_read(h_control, |
2123 | HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count, | 1865 | HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count, |
2124 | (u8 *)&mAC); | 1866 | (u8 *)&mac); |
2125 | *pmAC_MS_bs = | 1867 | |
2126 | ((mAC & 0xff000000) >> 8) | ((mAC & 0x00ff0000) << 8) | ((mAC | 1868 | if (!err) { |
2127 | & 0x0000ff00) >> 8) | ((mAC & 0x000000ff) << 8); | 1869 | *p_mac_msbs = |
2128 | error += hpi_cobranet_hmi_read(ph_subsys, h_control, | 1870 | ((mac & 0xff000000) >> 8) | ((mac & 0x00ff0000) << 8) |
2129 | HPI_COBRANET_HMI_cobra_if_phy_address + 1, 4, &byte_count, | 1871 | | ((mac & 0x0000ff00) >> 8) | ((mac & 0x000000ff) << |
2130 | (u8 *)&mAC); | 1872 | 8); |
2131 | *pmAC_LS_bs = | 1873 | |
2132 | ((mAC & 0xff000000) >> 8) | ((mAC & 0x00ff0000) << 8) | ((mAC | 1874 | err = hpi_cobranet_hmi_read(h_control, |
2133 | & 0x0000ff00) >> 8) | ((mAC & 0x000000ff) << 8); | 1875 | HPI_COBRANET_HMI_cobra_if_phy_address + 1, 4, |
2134 | 1876 | &byte_count, (u8 *)&mac); | |
2135 | if (error) { | ||
2136 | *pmAC_MS_bs = 0; | ||
2137 | *pmAC_LS_bs = 0; | ||
2138 | } | 1877 | } |
2139 | 1878 | ||
2140 | return error; | 1879 | if (!err) { |
1880 | *p_mac_lsbs = | ||
1881 | ((mac & 0xff000000) >> 8) | ((mac & 0x00ff0000) << 8) | ||
1882 | | ((mac & 0x0000ff00) >> 8) | ((mac & 0x000000ff) << | ||
1883 | 8); | ||
1884 | } else { | ||
1885 | *p_mac_msbs = 0; | ||
1886 | *p_mac_lsbs = 0; | ||
1887 | } | ||
1888 | |||
1889 | return err; | ||
2141 | } | 1890 | } |
2142 | 1891 | ||
2143 | u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys, | 1892 | u16 hpi_compander_set_enable(u32 h_control, u32 enable) |
2144 | u32 h_control, u32 enable) | ||
2145 | { | 1893 | { |
2146 | return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE, | 1894 | return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable, |
2147 | enable, 0); | 1895 | 0); |
2148 | } | 1896 | } |
2149 | 1897 | ||
2150 | u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys, | 1898 | u16 hpi_compander_get_enable(u32 h_control, u32 *enable) |
2151 | u32 h_control, u32 *enable) | ||
2152 | { | 1899 | { |
2153 | return hpi_control_param1_get(ph_subsys, h_control, | 1900 | return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable); |
2154 | HPI_GENERIC_ENABLE, enable); | ||
2155 | } | 1901 | } |
2156 | 1902 | ||
2157 | u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys, | 1903 | u16 hpi_compander_set_makeup_gain(u32 h_control, short makeup_gain0_01dB) |
2158 | u32 h_control, short makeup_gain0_01dB) | ||
2159 | { | 1904 | { |
2160 | return hpi_control_log_set2(h_control, HPI_COMPANDER_MAKEUPGAIN, | 1905 | return hpi_control_log_set2(h_control, HPI_COMPANDER_MAKEUPGAIN, |
2161 | makeup_gain0_01dB, 0); | 1906 | makeup_gain0_01dB, 0); |
2162 | } | 1907 | } |
2163 | 1908 | ||
2164 | u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys, | 1909 | u16 hpi_compander_get_makeup_gain(u32 h_control, short *makeup_gain0_01dB) |
2165 | u32 h_control, short *makeup_gain0_01dB) | ||
2166 | { | 1910 | { |
2167 | return hpi_control_log_get2(ph_subsys, h_control, | 1911 | return hpi_control_log_get2(h_control, HPI_COMPANDER_MAKEUPGAIN, |
2168 | HPI_COMPANDER_MAKEUPGAIN, makeup_gain0_01dB, NULL); | 1912 | makeup_gain0_01dB, NULL); |
2169 | } | 1913 | } |
2170 | 1914 | ||
2171 | u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys | 1915 | u16 hpi_compander_set_attack_time_constant(u32 h_control, unsigned int index, |
2172 | *ph_subsys, u32 h_control, unsigned int index, u32 attack) | 1916 | u32 attack) |
2173 | { | 1917 | { |
2174 | return hpi_control_param_set(ph_subsys, h_control, | 1918 | return hpi_control_param_set(h_control, HPI_COMPANDER_ATTACK, attack, |
2175 | HPI_COMPANDER_ATTACK, attack, index); | 1919 | index); |
2176 | } | 1920 | } |
2177 | 1921 | ||
2178 | u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys | 1922 | u16 hpi_compander_get_attack_time_constant(u32 h_control, unsigned int index, |
2179 | *ph_subsys, u32 h_control, unsigned int index, u32 *attack) | 1923 | u32 *attack) |
2180 | { | 1924 | { |
2181 | return hpi_control_param_get(ph_subsys, h_control, | 1925 | return hpi_control_param_get(h_control, HPI_COMPANDER_ATTACK, 0, |
2182 | HPI_COMPANDER_ATTACK, 0, index, attack, NULL); | 1926 | index, attack, NULL); |
2183 | } | 1927 | } |
2184 | 1928 | ||
2185 | u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys, | 1929 | u16 hpi_compander_set_decay_time_constant(u32 h_control, unsigned int index, |
2186 | u32 h_control, unsigned int index, u32 decay) | 1930 | u32 decay) |
2187 | { | 1931 | { |
2188 | return hpi_control_param_set(ph_subsys, h_control, | 1932 | return hpi_control_param_set(h_control, HPI_COMPANDER_DECAY, decay, |
2189 | HPI_COMPANDER_DECAY, decay, index); | 1933 | index); |
2190 | } | 1934 | } |
2191 | 1935 | ||
2192 | u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys, | 1936 | u16 hpi_compander_get_decay_time_constant(u32 h_control, unsigned int index, |
2193 | u32 h_control, unsigned int index, u32 *decay) | 1937 | u32 *decay) |
2194 | { | 1938 | { |
2195 | return hpi_control_param_get(ph_subsys, h_control, | 1939 | return hpi_control_param_get(h_control, HPI_COMPANDER_DECAY, 0, index, |
2196 | HPI_COMPANDER_DECAY, 0, index, decay, NULL); | 1940 | decay, NULL); |
2197 | 1941 | ||
2198 | } | 1942 | } |
2199 | 1943 | ||
2200 | u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys, | 1944 | u16 hpi_compander_set_threshold(u32 h_control, unsigned int index, |
2201 | u32 h_control, unsigned int index, short threshold0_01dB) | 1945 | short threshold0_01dB) |
2202 | { | 1946 | { |
2203 | struct hpi_message hm; | 1947 | struct hpi_message hm; |
2204 | struct hpi_response hr; | 1948 | struct hpi_response hr; |
2205 | 1949 | ||
2206 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1950 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2207 | HPI_CONTROL_SET_STATE); | 1951 | HPI_CONTROL_SET_STATE); |
2208 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1952 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1953 | return HPI_ERROR_INVALID_HANDLE; | ||
2209 | hm.u.c.attribute = HPI_COMPANDER_THRESHOLD; | 1954 | hm.u.c.attribute = HPI_COMPANDER_THRESHOLD; |
2210 | hm.u.c.param2 = index; | 1955 | hm.u.c.param2 = index; |
2211 | hm.u.c.an_log_value[0] = threshold0_01dB; | 1956 | hm.u.c.an_log_value[0] = threshold0_01dB; |
@@ -2215,15 +1960,16 @@ u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys, | |||
2215 | return hr.error; | 1960 | return hr.error; |
2216 | } | 1961 | } |
2217 | 1962 | ||
2218 | u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys, | 1963 | u16 hpi_compander_get_threshold(u32 h_control, unsigned int index, |
2219 | u32 h_control, unsigned int index, short *threshold0_01dB) | 1964 | short *threshold0_01dB) |
2220 | { | 1965 | { |
2221 | struct hpi_message hm; | 1966 | struct hpi_message hm; |
2222 | struct hpi_response hr; | 1967 | struct hpi_response hr; |
2223 | 1968 | ||
2224 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 1969 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2225 | HPI_CONTROL_GET_STATE); | 1970 | HPI_CONTROL_GET_STATE); |
2226 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 1971 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
1972 | return HPI_ERROR_INVALID_HANDLE; | ||
2227 | hm.u.c.attribute = HPI_COMPANDER_THRESHOLD; | 1973 | hm.u.c.attribute = HPI_COMPANDER_THRESHOLD; |
2228 | hm.u.c.param2 = index; | 1974 | hm.u.c.param2 = index; |
2229 | 1975 | ||
@@ -2233,29 +1979,28 @@ u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys, | |||
2233 | return hr.error; | 1979 | return hr.error; |
2234 | } | 1980 | } |
2235 | 1981 | ||
2236 | u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys, | 1982 | u16 hpi_compander_set_ratio(u32 h_control, u32 index, u32 ratio100) |
2237 | u32 h_control, u32 index, u32 ratio100) | ||
2238 | { | 1983 | { |
2239 | return hpi_control_param_set(ph_subsys, h_control, | 1984 | return hpi_control_param_set(h_control, HPI_COMPANDER_RATIO, ratio100, |
2240 | HPI_COMPANDER_RATIO, ratio100, index); | 1985 | index); |
2241 | } | 1986 | } |
2242 | 1987 | ||
2243 | u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys, | 1988 | u16 hpi_compander_get_ratio(u32 h_control, u32 index, u32 *ratio100) |
2244 | u32 h_control, u32 index, u32 *ratio100) | ||
2245 | { | 1989 | { |
2246 | return hpi_control_param_get(ph_subsys, h_control, | 1990 | return hpi_control_param_get(h_control, HPI_COMPANDER_RATIO, 0, index, |
2247 | HPI_COMPANDER_RATIO, 0, index, ratio100, NULL); | 1991 | ratio100, NULL); |
2248 | } | 1992 | } |
2249 | 1993 | ||
2250 | u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 1994 | u16 hpi_level_query_range(u32 h_control, short *min_gain_01dB, |
2251 | short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB) | 1995 | short *max_gain_01dB, short *step_gain_01dB) |
2252 | { | 1996 | { |
2253 | struct hpi_message hm; | 1997 | struct hpi_message hm; |
2254 | struct hpi_response hr; | 1998 | struct hpi_response hr; |
2255 | 1999 | ||
2256 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2000 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2257 | HPI_CONTROL_GET_STATE); | 2001 | HPI_CONTROL_GET_STATE); |
2258 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2002 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2003 | return HPI_ERROR_INVALID_HANDLE; | ||
2259 | hm.u.c.attribute = HPI_LEVEL_RANGE; | 2004 | hm.u.c.attribute = HPI_LEVEL_RANGE; |
2260 | 2005 | ||
2261 | hpi_send_recv(&hm, &hr); | 2006 | hpi_send_recv(&hm, &hr); |
@@ -2273,31 +2018,27 @@ u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
2273 | return hr.error; | 2018 | return hr.error; |
2274 | } | 2019 | } |
2275 | 2020 | ||
2276 | u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2021 | u16 hpi_level_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] |
2277 | short an_gain0_01dB[HPI_MAX_CHANNELS] | ||
2278 | ) | 2022 | ) |
2279 | { | 2023 | { |
2280 | return hpi_control_log_set2(h_control, HPI_LEVEL_GAIN, | 2024 | return hpi_control_log_set2(h_control, HPI_LEVEL_GAIN, |
2281 | an_gain0_01dB[0], an_gain0_01dB[1]); | 2025 | an_gain0_01dB[0], an_gain0_01dB[1]); |
2282 | } | 2026 | } |
2283 | 2027 | ||
2284 | u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2028 | u16 hpi_level_get_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS] |
2285 | short an_gain0_01dB[HPI_MAX_CHANNELS] | ||
2286 | ) | 2029 | ) |
2287 | { | 2030 | { |
2288 | return hpi_control_log_get2(ph_subsys, h_control, HPI_LEVEL_GAIN, | 2031 | return hpi_control_log_get2(h_control, HPI_LEVEL_GAIN, |
2289 | &an_gain0_01dB[0], &an_gain0_01dB[1]); | 2032 | &an_gain0_01dB[0], &an_gain0_01dB[1]); |
2290 | } | 2033 | } |
2291 | 2034 | ||
2292 | u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys, | 2035 | u16 hpi_meter_query_channels(const u32 h_meter, u32 *p_channels) |
2293 | const u32 h_meter, u32 *p_channels) | ||
2294 | { | 2036 | { |
2295 | return hpi_control_query(ph_subsys, h_meter, HPI_METER_NUM_CHANNELS, | 2037 | return hpi_control_query(h_meter, HPI_METER_NUM_CHANNELS, 0, 0, |
2296 | 0, 0, p_channels); | 2038 | p_channels); |
2297 | } | 2039 | } |
2298 | 2040 | ||
2299 | u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2041 | u16 hpi_meter_get_peak(u32 h_control, short an_peakdB[HPI_MAX_CHANNELS] |
2300 | short an_peakdB[HPI_MAX_CHANNELS] | ||
2301 | ) | 2042 | ) |
2302 | { | 2043 | { |
2303 | short i = 0; | 2044 | short i = 0; |
@@ -2307,7 +2048,8 @@ u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
2307 | 2048 | ||
2308 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2049 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2309 | HPI_CONTROL_GET_STATE); | 2050 | HPI_CONTROL_GET_STATE); |
2310 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2051 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2052 | return HPI_ERROR_INVALID_HANDLE; | ||
2311 | hm.obj_index = hm.obj_index; | 2053 | hm.obj_index = hm.obj_index; |
2312 | hm.u.c.attribute = HPI_METER_PEAK; | 2054 | hm.u.c.attribute = HPI_METER_PEAK; |
2313 | 2055 | ||
@@ -2322,8 +2064,7 @@ u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
2322 | return hr.error; | 2064 | return hr.error; |
2323 | } | 2065 | } |
2324 | 2066 | ||
2325 | u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2067 | u16 hpi_meter_get_rms(u32 h_control, short an_rmsdB[HPI_MAX_CHANNELS] |
2326 | short an_rmsdB[HPI_MAX_CHANNELS] | ||
2327 | ) | 2068 | ) |
2328 | { | 2069 | { |
2329 | short i = 0; | 2070 | short i = 0; |
@@ -2333,7 +2074,8 @@ u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
2333 | 2074 | ||
2334 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2075 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2335 | HPI_CONTROL_GET_STATE); | 2076 | HPI_CONTROL_GET_STATE); |
2336 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2077 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2078 | return HPI_ERROR_INVALID_HANDLE; | ||
2337 | hm.u.c.attribute = HPI_METER_RMS; | 2079 | hm.u.c.attribute = HPI_METER_RMS; |
2338 | 2080 | ||
2339 | hpi_send_recv(&hm, &hr); | 2081 | hpi_send_recv(&hm, &hr); |
@@ -2348,22 +2090,20 @@ u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
2348 | return hr.error; | 2090 | return hr.error; |
2349 | } | 2091 | } |
2350 | 2092 | ||
2351 | u16 hpi_meter_set_rms_ballistics(const struct hpi_hsubsys *ph_subsys, | 2093 | u16 hpi_meter_set_rms_ballistics(u32 h_control, u16 attack, u16 decay) |
2352 | u32 h_control, u16 attack, u16 decay) | ||
2353 | { | 2094 | { |
2354 | return hpi_control_param_set(ph_subsys, h_control, | 2095 | return hpi_control_param_set(h_control, HPI_METER_RMS_BALLISTICS, |
2355 | HPI_METER_RMS_BALLISTICS, attack, decay); | 2096 | attack, decay); |
2356 | } | 2097 | } |
2357 | 2098 | ||
2358 | u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys, | 2099 | u16 hpi_meter_get_rms_ballistics(u32 h_control, u16 *pn_attack, u16 *pn_decay) |
2359 | u32 h_control, u16 *pn_attack, u16 *pn_decay) | ||
2360 | { | 2100 | { |
2361 | u32 attack; | 2101 | u32 attack; |
2362 | u32 decay; | 2102 | u32 decay; |
2363 | u16 error; | 2103 | u16 error; |
2364 | 2104 | ||
2365 | error = hpi_control_param2_get(ph_subsys, h_control, | 2105 | error = hpi_control_param2_get(h_control, HPI_METER_RMS_BALLISTICS, |
2366 | HPI_METER_RMS_BALLISTICS, &attack, &decay); | 2106 | &attack, &decay); |
2367 | 2107 | ||
2368 | if (pn_attack) | 2108 | if (pn_attack) |
2369 | *pn_attack = (unsigned short)attack; | 2109 | *pn_attack = (unsigned short)attack; |
@@ -2373,22 +2113,21 @@ u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys, | |||
2373 | return error; | 2113 | return error; |
2374 | } | 2114 | } |
2375 | 2115 | ||
2376 | u16 hpi_meter_set_peak_ballistics(const struct hpi_hsubsys *ph_subsys, | 2116 | u16 hpi_meter_set_peak_ballistics(u32 h_control, u16 attack, u16 decay) |
2377 | u32 h_control, u16 attack, u16 decay) | ||
2378 | { | 2117 | { |
2379 | return hpi_control_param_set(ph_subsys, h_control, | 2118 | return hpi_control_param_set(h_control, HPI_METER_PEAK_BALLISTICS, |
2380 | HPI_METER_PEAK_BALLISTICS, attack, decay); | 2119 | attack, decay); |
2381 | } | 2120 | } |
2382 | 2121 | ||
2383 | u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys, | 2122 | u16 hpi_meter_get_peak_ballistics(u32 h_control, u16 *pn_attack, |
2384 | u32 h_control, u16 *pn_attack, u16 *pn_decay) | 2123 | u16 *pn_decay) |
2385 | { | 2124 | { |
2386 | u32 attack; | 2125 | u32 attack; |
2387 | u32 decay; | 2126 | u32 decay; |
2388 | u16 error; | 2127 | u16 error; |
2389 | 2128 | ||
2390 | error = hpi_control_param2_get(ph_subsys, h_control, | 2129 | error = hpi_control_param2_get(h_control, HPI_METER_PEAK_BALLISTICS, |
2391 | HPI_METER_PEAK_BALLISTICS, &attack, &decay); | 2130 | &attack, &decay); |
2392 | 2131 | ||
2393 | if (pn_attack) | 2132 | if (pn_attack) |
2394 | *pn_attack = (short)attack; | 2133 | *pn_attack = (short)attack; |
@@ -2398,55 +2137,53 @@ u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys, | |||
2398 | return error; | 2137 | return error; |
2399 | } | 2138 | } |
2400 | 2139 | ||
2401 | u16 hpi_microphone_set_phantom_power(const struct hpi_hsubsys *ph_subsys, | 2140 | u16 hpi_microphone_set_phantom_power(u32 h_control, u16 on_off) |
2402 | u32 h_control, u16 on_off) | ||
2403 | { | 2141 | { |
2404 | return hpi_control_param_set(ph_subsys, h_control, | 2142 | return hpi_control_param_set(h_control, HPI_MICROPHONE_PHANTOM_POWER, |
2405 | HPI_MICROPHONE_PHANTOM_POWER, (u32)on_off, 0); | 2143 | (u32)on_off, 0); |
2406 | } | 2144 | } |
2407 | 2145 | ||
2408 | u16 hpi_microphone_get_phantom_power(const struct hpi_hsubsys *ph_subsys, | 2146 | u16 hpi_microphone_get_phantom_power(u32 h_control, u16 *pw_on_off) |
2409 | u32 h_control, u16 *pw_on_off) | ||
2410 | { | 2147 | { |
2411 | u16 error = 0; | 2148 | u16 error = 0; |
2412 | u32 on_off = 0; | 2149 | u32 on_off = 0; |
2413 | error = hpi_control_param1_get(ph_subsys, h_control, | 2150 | error = hpi_control_param1_get(h_control, |
2414 | HPI_MICROPHONE_PHANTOM_POWER, &on_off); | 2151 | HPI_MICROPHONE_PHANTOM_POWER, &on_off); |
2415 | if (pw_on_off) | 2152 | if (pw_on_off) |
2416 | *pw_on_off = (u16)on_off; | 2153 | *pw_on_off = (u16)on_off; |
2417 | return error; | 2154 | return error; |
2418 | } | 2155 | } |
2419 | 2156 | ||
2420 | u16 hpi_multiplexer_set_source(const struct hpi_hsubsys *ph_subsys, | 2157 | u16 hpi_multiplexer_set_source(u32 h_control, u16 source_node_type, |
2421 | u32 h_control, u16 source_node_type, u16 source_node_index) | 2158 | u16 source_node_index) |
2422 | { | 2159 | { |
2423 | return hpi_control_param_set(ph_subsys, h_control, | 2160 | return hpi_control_param_set(h_control, HPI_MULTIPLEXER_SOURCE, |
2424 | HPI_MULTIPLEXER_SOURCE, source_node_type, source_node_index); | 2161 | source_node_type, source_node_index); |
2425 | } | 2162 | } |
2426 | 2163 | ||
2427 | u16 hpi_multiplexer_get_source(const struct hpi_hsubsys *ph_subsys, | 2164 | u16 hpi_multiplexer_get_source(u32 h_control, u16 *source_node_type, |
2428 | u32 h_control, u16 *source_node_type, u16 *source_node_index) | 2165 | u16 *source_node_index) |
2429 | { | 2166 | { |
2430 | u32 node, index; | 2167 | u32 node, index; |
2431 | u16 error = hpi_control_param2_get(ph_subsys, h_control, | 2168 | u16 err = hpi_control_param2_get(h_control, |
2432 | HPI_MULTIPLEXER_SOURCE, &node, | 2169 | HPI_MULTIPLEXER_SOURCE, &node, |
2433 | &index); | 2170 | &index); |
2434 | if (source_node_type) | 2171 | if (source_node_type) |
2435 | *source_node_type = (u16)node; | 2172 | *source_node_type = (u16)node; |
2436 | if (source_node_index) | 2173 | if (source_node_index) |
2437 | *source_node_index = (u16)index; | 2174 | *source_node_index = (u16)index; |
2438 | return error; | 2175 | return err; |
2439 | } | 2176 | } |
2440 | 2177 | ||
2441 | u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys, | 2178 | u16 hpi_multiplexer_query_source(u32 h_control, u16 index, |
2442 | u32 h_control, u16 index, u16 *source_node_type, | 2179 | u16 *source_node_type, u16 *source_node_index) |
2443 | u16 *source_node_index) | ||
2444 | { | 2180 | { |
2445 | struct hpi_message hm; | 2181 | struct hpi_message hm; |
2446 | struct hpi_response hr; | 2182 | struct hpi_response hr; |
2447 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2183 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2448 | HPI_CONTROL_GET_STATE); | 2184 | HPI_CONTROL_GET_STATE); |
2449 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2185 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2186 | return HPI_ERROR_INVALID_HANDLE; | ||
2450 | hm.u.c.attribute = HPI_MULTIPLEXER_QUERYSOURCE; | 2187 | hm.u.c.attribute = HPI_MULTIPLEXER_QUERYSOURCE; |
2451 | hm.u.c.param1 = index; | 2188 | hm.u.c.param1 = index; |
2452 | 2189 | ||
@@ -2459,15 +2196,15 @@ u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys, | |||
2459 | return hr.error; | 2196 | return hr.error; |
2460 | } | 2197 | } |
2461 | 2198 | ||
2462 | u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys, | 2199 | u16 hpi_parametric_eq_get_info(u32 h_control, u16 *pw_number_of_bands, |
2463 | u32 h_control, u16 *pw_number_of_bands, u16 *pw_on_off) | 2200 | u16 *pw_on_off) |
2464 | { | 2201 | { |
2465 | u32 oB = 0; | 2202 | u32 oB = 0; |
2466 | u32 oO = 0; | 2203 | u32 oO = 0; |
2467 | u16 error = 0; | 2204 | u16 error = 0; |
2468 | 2205 | ||
2469 | error = hpi_control_param2_get(ph_subsys, h_control, | 2206 | error = hpi_control_param2_get(h_control, HPI_EQUALIZER_NUM_FILTERS, |
2470 | HPI_EQUALIZER_NUM_FILTERS, &oO, &oB); | 2207 | &oO, &oB); |
2471 | if (pw_number_of_bands) | 2208 | if (pw_number_of_bands) |
2472 | *pw_number_of_bands = (u16)oB; | 2209 | *pw_number_of_bands = (u16)oB; |
2473 | if (pw_on_off) | 2210 | if (pw_on_off) |
@@ -2475,23 +2212,22 @@ u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys, | |||
2475 | return error; | 2212 | return error; |
2476 | } | 2213 | } |
2477 | 2214 | ||
2478 | u16 hpi_parametricEQ__set_state(const struct hpi_hsubsys *ph_subsys, | 2215 | u16 hpi_parametric_eq_set_state(u32 h_control, u16 on_off) |
2479 | u32 h_control, u16 on_off) | ||
2480 | { | 2216 | { |
2481 | return hpi_control_param_set(ph_subsys, h_control, | 2217 | return hpi_control_param_set(h_control, HPI_EQUALIZER_NUM_FILTERS, |
2482 | HPI_EQUALIZER_NUM_FILTERS, on_off, 0); | 2218 | on_off, 0); |
2483 | } | 2219 | } |
2484 | 2220 | ||
2485 | u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys, | 2221 | u16 hpi_parametric_eq_get_band(u32 h_control, u16 index, u16 *pn_type, |
2486 | u32 h_control, u16 index, u16 *pn_type, u32 *pfrequency_hz, | 2222 | u32 *pfrequency_hz, short *pnQ100, short *pn_gain0_01dB) |
2487 | short *pnQ100, short *pn_gain0_01dB) | ||
2488 | { | 2223 | { |
2489 | struct hpi_message hm; | 2224 | struct hpi_message hm; |
2490 | struct hpi_response hr; | 2225 | struct hpi_response hr; |
2491 | 2226 | ||
2492 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2227 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2493 | HPI_CONTROL_GET_STATE); | 2228 | HPI_CONTROL_GET_STATE); |
2494 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2229 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2230 | return HPI_ERROR_INVALID_HANDLE; | ||
2495 | hm.u.c.attribute = HPI_EQUALIZER_FILTER; | 2231 | hm.u.c.attribute = HPI_EQUALIZER_FILTER; |
2496 | hm.u.c.param2 = index; | 2232 | hm.u.c.param2 = index; |
2497 | 2233 | ||
@@ -2509,16 +2245,16 @@ u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys, | |||
2509 | return hr.error; | 2245 | return hr.error; |
2510 | } | 2246 | } |
2511 | 2247 | ||
2512 | u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys, | 2248 | u16 hpi_parametric_eq_set_band(u32 h_control, u16 index, u16 type, |
2513 | u32 h_control, u16 index, u16 type, u32 frequency_hz, short q100, | 2249 | u32 frequency_hz, short q100, short gain0_01dB) |
2514 | short gain0_01dB) | ||
2515 | { | 2250 | { |
2516 | struct hpi_message hm; | 2251 | struct hpi_message hm; |
2517 | struct hpi_response hr; | 2252 | struct hpi_response hr; |
2518 | 2253 | ||
2519 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2254 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2520 | HPI_CONTROL_SET_STATE); | 2255 | HPI_CONTROL_SET_STATE); |
2521 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2256 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2257 | return HPI_ERROR_INVALID_HANDLE; | ||
2522 | 2258 | ||
2523 | hm.u.c.param1 = frequency_hz; | 2259 | hm.u.c.param1 = frequency_hz; |
2524 | hm.u.c.param2 = (index & 0xFFFFL) + ((u32)type << 16); | 2260 | hm.u.c.param2 = (index & 0xFFFFL) + ((u32)type << 16); |
@@ -2531,8 +2267,7 @@ u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys, | |||
2531 | return hr.error; | 2267 | return hr.error; |
2532 | } | 2268 | } |
2533 | 2269 | ||
2534 | u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys, | 2270 | u16 hpi_parametric_eq_get_coeffs(u32 h_control, u16 index, short coeffs[5] |
2535 | u32 h_control, u16 index, short coeffs[5] | ||
2536 | ) | 2271 | ) |
2537 | { | 2272 | { |
2538 | struct hpi_message hm; | 2273 | struct hpi_message hm; |
@@ -2540,7 +2275,8 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys, | |||
2540 | 2275 | ||
2541 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2276 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2542 | HPI_CONTROL_GET_STATE); | 2277 | HPI_CONTROL_GET_STATE); |
2543 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2278 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2279 | return HPI_ERROR_INVALID_HANDLE; | ||
2544 | hm.u.c.attribute = HPI_EQUALIZER_COEFFICIENTS; | 2280 | hm.u.c.attribute = HPI_EQUALIZER_COEFFICIENTS; |
2545 | hm.u.c.param2 = index; | 2281 | hm.u.c.param2 = index; |
2546 | 2282 | ||
@@ -2555,444 +2291,388 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys, | |||
2555 | return hr.error; | 2291 | return hr.error; |
2556 | } | 2292 | } |
2557 | 2293 | ||
2558 | u16 hpi_sample_clock_query_source(const struct hpi_hsubsys *ph_subsys, | 2294 | u16 hpi_sample_clock_query_source(const u32 h_clock, const u32 index, |
2559 | const u32 h_clock, const u32 index, u16 *pw_source) | 2295 | u16 *pw_source) |
2560 | { | 2296 | { |
2561 | u32 qr; | 2297 | u32 qr; |
2562 | u16 err; | 2298 | u16 err; |
2563 | 2299 | ||
2564 | err = hpi_control_query(ph_subsys, h_clock, HPI_SAMPLECLOCK_SOURCE, | 2300 | err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_SOURCE, index, 0, |
2565 | index, 0, &qr); | 2301 | &qr); |
2566 | *pw_source = (u16)qr; | 2302 | *pw_source = (u16)qr; |
2567 | return err; | 2303 | return err; |
2568 | } | 2304 | } |
2569 | 2305 | ||
2570 | u16 hpi_sample_clock_set_source(const struct hpi_hsubsys *ph_subsys, | 2306 | u16 hpi_sample_clock_set_source(u32 h_control, u16 source) |
2571 | u32 h_control, u16 source) | ||
2572 | { | 2307 | { |
2573 | return hpi_control_param_set(ph_subsys, h_control, | 2308 | return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_SOURCE, |
2574 | HPI_SAMPLECLOCK_SOURCE, source, 0); | 2309 | source, 0); |
2575 | } | 2310 | } |
2576 | 2311 | ||
2577 | u16 hpi_sample_clock_get_source(const struct hpi_hsubsys *ph_subsys, | 2312 | u16 hpi_sample_clock_get_source(u32 h_control, u16 *pw_source) |
2578 | u32 h_control, u16 *pw_source) | ||
2579 | { | 2313 | { |
2580 | u16 error = 0; | 2314 | u16 err = 0; |
2581 | u32 source = 0; | 2315 | u32 source = 0; |
2582 | error = hpi_control_param1_get(ph_subsys, h_control, | 2316 | err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SOURCE, |
2583 | HPI_SAMPLECLOCK_SOURCE, &source); | 2317 | &source); |
2584 | if (!error) | 2318 | if (!err) |
2585 | if (pw_source) | 2319 | if (pw_source) |
2586 | *pw_source = (u16)source; | 2320 | *pw_source = (u16)source; |
2587 | return error; | 2321 | return err; |
2588 | } | 2322 | } |
2589 | 2323 | ||
2590 | u16 hpi_sample_clock_query_source_index(const struct hpi_hsubsys *ph_subsys, | 2324 | u16 hpi_sample_clock_query_source_index(const u32 h_clock, const u32 index, |
2591 | const u32 h_clock, const u32 index, const u32 source, | 2325 | const u32 source, u16 *pw_source_index) |
2592 | u16 *pw_source_index) | ||
2593 | { | 2326 | { |
2594 | u32 qr; | 2327 | u32 qr; |
2595 | u16 err; | 2328 | u16 err; |
2596 | 2329 | ||
2597 | err = hpi_control_query(ph_subsys, h_clock, | 2330 | err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_SOURCE_INDEX, index, |
2598 | HPI_SAMPLECLOCK_SOURCE_INDEX, index, source, &qr); | 2331 | source, &qr); |
2599 | *pw_source_index = (u16)qr; | 2332 | *pw_source_index = (u16)qr; |
2600 | return err; | 2333 | return err; |
2601 | } | 2334 | } |
2602 | 2335 | ||
2603 | u16 hpi_sample_clock_set_source_index(const struct hpi_hsubsys *ph_subsys, | 2336 | u16 hpi_sample_clock_set_source_index(u32 h_control, u16 source_index) |
2604 | u32 h_control, u16 source_index) | ||
2605 | { | 2337 | { |
2606 | return hpi_control_param_set(ph_subsys, h_control, | 2338 | return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_SOURCE_INDEX, |
2607 | HPI_SAMPLECLOCK_SOURCE_INDEX, source_index, 0); | 2339 | source_index, 0); |
2608 | } | 2340 | } |
2609 | 2341 | ||
2610 | u16 hpi_sample_clock_get_source_index(const struct hpi_hsubsys *ph_subsys, | 2342 | u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index) |
2611 | u32 h_control, u16 *pw_source_index) | ||
2612 | { | 2343 | { |
2613 | u16 error = 0; | 2344 | u16 err = 0; |
2614 | u32 source_index = 0; | 2345 | u32 source_index = 0; |
2615 | error = hpi_control_param1_get(ph_subsys, h_control, | 2346 | err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SOURCE_INDEX, |
2616 | HPI_SAMPLECLOCK_SOURCE_INDEX, &source_index); | 2347 | &source_index); |
2617 | if (!error) | 2348 | if (!err) |
2618 | if (pw_source_index) | 2349 | if (pw_source_index) |
2619 | *pw_source_index = (u16)source_index; | 2350 | *pw_source_index = (u16)source_index; |
2620 | return error; | 2351 | return err; |
2621 | } | 2352 | } |
2622 | 2353 | ||
2623 | u16 hpi_sample_clock_query_local_rate(const struct hpi_hsubsys *ph_subsys, | 2354 | u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index, |
2624 | const u32 h_clock, const u32 index, u32 *prate) | 2355 | u32 *prate) |
2625 | { | 2356 | { |
2626 | u16 err; | 2357 | u16 err; |
2627 | err = hpi_control_query(ph_subsys, h_clock, | 2358 | err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, |
2628 | HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, index, 0, prate); | 2359 | index, 0, prate); |
2629 | 2360 | ||
2630 | return err; | 2361 | return err; |
2631 | } | 2362 | } |
2632 | 2363 | ||
2633 | u16 hpi_sample_clock_set_local_rate(const struct hpi_hsubsys *ph_subsys, | 2364 | u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate) |
2634 | u32 h_control, u32 sample_rate) | ||
2635 | { | 2365 | { |
2636 | return hpi_control_param_set(ph_subsys, h_control, | 2366 | return hpi_control_param_set(h_control, |
2637 | HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, sample_rate, 0); | 2367 | HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, sample_rate, 0); |
2638 | } | 2368 | } |
2639 | 2369 | ||
2640 | u16 hpi_sample_clock_get_local_rate(const struct hpi_hsubsys *ph_subsys, | 2370 | u16 hpi_sample_clock_get_local_rate(u32 h_control, u32 *psample_rate) |
2641 | u32 h_control, u32 *psample_rate) | ||
2642 | { | 2371 | { |
2643 | u16 error = 0; | 2372 | u16 err = 0; |
2644 | u32 sample_rate = 0; | 2373 | u32 sample_rate = 0; |
2645 | error = hpi_control_param1_get(ph_subsys, h_control, | 2374 | err = hpi_control_param1_get(h_control, |
2646 | HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, &sample_rate); | 2375 | HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, &sample_rate); |
2647 | if (!error) | 2376 | if (!err) |
2648 | if (psample_rate) | 2377 | if (psample_rate) |
2649 | *psample_rate = sample_rate; | 2378 | *psample_rate = sample_rate; |
2650 | return error; | 2379 | return err; |
2651 | } | 2380 | } |
2652 | 2381 | ||
2653 | u16 hpi_sample_clock_get_sample_rate(const struct hpi_hsubsys *ph_subsys, | 2382 | u16 hpi_sample_clock_get_sample_rate(u32 h_control, u32 *psample_rate) |
2654 | u32 h_control, u32 *psample_rate) | ||
2655 | { | 2383 | { |
2656 | u16 error = 0; | 2384 | u16 err = 0; |
2657 | u32 sample_rate = 0; | 2385 | u32 sample_rate = 0; |
2658 | error = hpi_control_param1_get(ph_subsys, h_control, | 2386 | err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SAMPLERATE, |
2659 | HPI_SAMPLECLOCK_SAMPLERATE, &sample_rate); | 2387 | &sample_rate); |
2660 | if (!error) | 2388 | if (!err) |
2661 | if (psample_rate) | 2389 | if (psample_rate) |
2662 | *psample_rate = sample_rate; | 2390 | *psample_rate = sample_rate; |
2663 | return error; | 2391 | return err; |
2664 | } | 2392 | } |
2665 | 2393 | ||
2666 | u16 hpi_sample_clock_set_auto(const struct hpi_hsubsys *ph_subsys, | 2394 | u16 hpi_sample_clock_set_auto(u32 h_control, u32 enable) |
2667 | u32 h_control, u32 enable) | ||
2668 | { | 2395 | { |
2669 | return hpi_control_param_set(ph_subsys, h_control, | 2396 | return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_AUTO, enable, |
2670 | HPI_SAMPLECLOCK_AUTO, enable, 0); | 2397 | 0); |
2671 | } | 2398 | } |
2672 | 2399 | ||
2673 | u16 hpi_sample_clock_get_auto(const struct hpi_hsubsys *ph_subsys, | 2400 | u16 hpi_sample_clock_get_auto(u32 h_control, u32 *penable) |
2674 | u32 h_control, u32 *penable) | ||
2675 | { | 2401 | { |
2676 | return hpi_control_param1_get(ph_subsys, h_control, | 2402 | return hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_AUTO, |
2677 | HPI_SAMPLECLOCK_AUTO, penable); | 2403 | penable); |
2678 | } | 2404 | } |
2679 | 2405 | ||
2680 | u16 hpi_sample_clock_set_local_rate_lock(const struct hpi_hsubsys *ph_subsys, | 2406 | u16 hpi_sample_clock_set_local_rate_lock(u32 h_control, u32 lock) |
2681 | u32 h_control, u32 lock) | ||
2682 | { | 2407 | { |
2683 | return hpi_control_param_set(ph_subsys, h_control, | 2408 | return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_LOCAL_LOCK, |
2684 | HPI_SAMPLECLOCK_LOCAL_LOCK, lock, 0); | 2409 | lock, 0); |
2685 | } | 2410 | } |
2686 | 2411 | ||
2687 | u16 hpi_sample_clock_get_local_rate_lock(const struct hpi_hsubsys *ph_subsys, | 2412 | u16 hpi_sample_clock_get_local_rate_lock(u32 h_control, u32 *plock) |
2688 | u32 h_control, u32 *plock) | ||
2689 | { | 2413 | { |
2690 | return hpi_control_param1_get(ph_subsys, h_control, | 2414 | return hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_LOCAL_LOCK, |
2691 | HPI_SAMPLECLOCK_LOCAL_LOCK, plock); | 2415 | plock); |
2692 | } | 2416 | } |
2693 | 2417 | ||
2694 | u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys, | 2418 | u16 hpi_tone_detector_get_frequency(u32 h_control, u32 index, u32 *frequency) |
2695 | u32 h_control, u32 index, u32 *frequency) | ||
2696 | { | 2419 | { |
2697 | return hpi_control_param_get(ph_subsys, h_control, | 2420 | return hpi_control_param_get(h_control, HPI_TONEDETECTOR_FREQUENCY, |
2698 | HPI_TONEDETECTOR_FREQUENCY, index, 0, frequency, NULL); | 2421 | index, 0, frequency, NULL); |
2699 | } | 2422 | } |
2700 | 2423 | ||
2701 | u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys, | 2424 | u16 hpi_tone_detector_get_state(u32 h_control, u32 *state) |
2702 | u32 h_control, u32 *state) | ||
2703 | { | 2425 | { |
2704 | return hpi_control_param1_get(ph_subsys, h_control, | 2426 | return hpi_control_param1_get(h_control, HPI_TONEDETECTOR_STATE, |
2705 | HPI_TONEDETECTOR_STATE, state); | 2427 | state); |
2706 | } | 2428 | } |
2707 | 2429 | ||
2708 | u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys, | 2430 | u16 hpi_tone_detector_set_enable(u32 h_control, u32 enable) |
2709 | u32 h_control, u32 enable) | ||
2710 | { | 2431 | { |
2711 | return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE, | 2432 | return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable, |
2712 | (u32)enable, 0); | 2433 | 0); |
2713 | } | 2434 | } |
2714 | 2435 | ||
2715 | u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys, | 2436 | u16 hpi_tone_detector_get_enable(u32 h_control, u32 *enable) |
2716 | u32 h_control, u32 *enable) | ||
2717 | { | 2437 | { |
2718 | return hpi_control_param1_get(ph_subsys, h_control, | 2438 | return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable); |
2719 | HPI_GENERIC_ENABLE, enable); | ||
2720 | } | 2439 | } |
2721 | 2440 | ||
2722 | u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, | 2441 | u16 hpi_tone_detector_set_event_enable(u32 h_control, u32 event_enable) |
2723 | u32 h_control, u32 event_enable) | ||
2724 | { | 2442 | { |
2725 | return hpi_control_param_set(ph_subsys, h_control, | 2443 | return hpi_control_param_set(h_control, HPI_GENERIC_EVENT_ENABLE, |
2726 | HPI_GENERIC_EVENT_ENABLE, (u32)event_enable, 0); | 2444 | (u32)event_enable, 0); |
2727 | } | 2445 | } |
2728 | 2446 | ||
2729 | u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, | 2447 | u16 hpi_tone_detector_get_event_enable(u32 h_control, u32 *event_enable) |
2730 | u32 h_control, u32 *event_enable) | ||
2731 | { | 2448 | { |
2732 | return hpi_control_param1_get(ph_subsys, h_control, | 2449 | return hpi_control_param1_get(h_control, HPI_GENERIC_EVENT_ENABLE, |
2733 | HPI_GENERIC_EVENT_ENABLE, event_enable); | 2450 | event_enable); |
2734 | } | 2451 | } |
2735 | 2452 | ||
2736 | u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, | 2453 | u16 hpi_tone_detector_set_threshold(u32 h_control, int threshold) |
2737 | u32 h_control, int threshold) | ||
2738 | { | 2454 | { |
2739 | return hpi_control_param_set(ph_subsys, h_control, | 2455 | return hpi_control_param_set(h_control, HPI_TONEDETECTOR_THRESHOLD, |
2740 | HPI_TONEDETECTOR_THRESHOLD, (u32)threshold, 0); | 2456 | (u32)threshold, 0); |
2741 | } | 2457 | } |
2742 | 2458 | ||
2743 | u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, | 2459 | u16 hpi_tone_detector_get_threshold(u32 h_control, int *threshold) |
2744 | u32 h_control, int *threshold) | ||
2745 | { | 2460 | { |
2746 | return hpi_control_param1_get(ph_subsys, h_control, | 2461 | return hpi_control_param1_get(h_control, HPI_TONEDETECTOR_THRESHOLD, |
2747 | HPI_TONEDETECTOR_THRESHOLD, (u32 *)threshold); | 2462 | (u32 *)threshold); |
2748 | } | 2463 | } |
2749 | 2464 | ||
2750 | u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys, | 2465 | u16 hpi_silence_detector_get_state(u32 h_control, u32 *state) |
2751 | u32 h_control, u32 *state) | ||
2752 | { | 2466 | { |
2753 | return hpi_control_param1_get(ph_subsys, h_control, | 2467 | return hpi_control_param1_get(h_control, HPI_SILENCEDETECTOR_STATE, |
2754 | HPI_SILENCEDETECTOR_STATE, state); | 2468 | state); |
2755 | } | 2469 | } |
2756 | 2470 | ||
2757 | u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys, | 2471 | u16 hpi_silence_detector_set_enable(u32 h_control, u32 enable) |
2758 | u32 h_control, u32 enable) | ||
2759 | { | 2472 | { |
2760 | return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE, | 2473 | return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable, |
2761 | (u32)enable, 0); | 2474 | 0); |
2762 | } | 2475 | } |
2763 | 2476 | ||
2764 | u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys, | 2477 | u16 hpi_silence_detector_get_enable(u32 h_control, u32 *enable) |
2765 | u32 h_control, u32 *enable) | ||
2766 | { | 2478 | { |
2767 | return hpi_control_param1_get(ph_subsys, h_control, | 2479 | return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable); |
2768 | HPI_GENERIC_ENABLE, enable); | ||
2769 | } | 2480 | } |
2770 | 2481 | ||
2771 | u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys, | 2482 | u16 hpi_silence_detector_set_event_enable(u32 h_control, u32 event_enable) |
2772 | u32 h_control, u32 event_enable) | ||
2773 | { | 2483 | { |
2774 | return hpi_control_param_set(ph_subsys, h_control, | 2484 | return hpi_control_param_set(h_control, HPI_GENERIC_EVENT_ENABLE, |
2775 | HPI_GENERIC_EVENT_ENABLE, event_enable, 0); | 2485 | event_enable, 0); |
2776 | } | 2486 | } |
2777 | 2487 | ||
2778 | u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys, | 2488 | u16 hpi_silence_detector_get_event_enable(u32 h_control, u32 *event_enable) |
2779 | u32 h_control, u32 *event_enable) | ||
2780 | { | 2489 | { |
2781 | return hpi_control_param1_get(ph_subsys, h_control, | 2490 | return hpi_control_param1_get(h_control, HPI_GENERIC_EVENT_ENABLE, |
2782 | HPI_GENERIC_EVENT_ENABLE, event_enable); | 2491 | event_enable); |
2783 | } | 2492 | } |
2784 | 2493 | ||
2785 | u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys, | 2494 | u16 hpi_silence_detector_set_delay(u32 h_control, u32 delay) |
2786 | u32 h_control, u32 delay) | ||
2787 | { | 2495 | { |
2788 | return hpi_control_param_set(ph_subsys, h_control, | 2496 | return hpi_control_param_set(h_control, HPI_SILENCEDETECTOR_DELAY, |
2789 | HPI_SILENCEDETECTOR_DELAY, delay, 0); | 2497 | delay, 0); |
2790 | } | 2498 | } |
2791 | 2499 | ||
2792 | u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys, | 2500 | u16 hpi_silence_detector_get_delay(u32 h_control, u32 *delay) |
2793 | u32 h_control, u32 *delay) | ||
2794 | { | 2501 | { |
2795 | return hpi_control_param1_get(ph_subsys, h_control, | 2502 | return hpi_control_param1_get(h_control, HPI_SILENCEDETECTOR_DELAY, |
2796 | HPI_SILENCEDETECTOR_DELAY, delay); | 2503 | delay); |
2797 | } | 2504 | } |
2798 | 2505 | ||
2799 | u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys, | 2506 | u16 hpi_silence_detector_set_threshold(u32 h_control, int threshold) |
2800 | u32 h_control, int threshold) | ||
2801 | { | 2507 | { |
2802 | return hpi_control_param_set(ph_subsys, h_control, | 2508 | return hpi_control_param_set(h_control, HPI_SILENCEDETECTOR_THRESHOLD, |
2803 | HPI_SILENCEDETECTOR_THRESHOLD, threshold, 0); | 2509 | threshold, 0); |
2804 | } | 2510 | } |
2805 | 2511 | ||
2806 | u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys, | 2512 | u16 hpi_silence_detector_get_threshold(u32 h_control, int *threshold) |
2807 | u32 h_control, int *threshold) | ||
2808 | { | 2513 | { |
2809 | return hpi_control_param1_get(ph_subsys, h_control, | 2514 | return hpi_control_param1_get(h_control, |
2810 | HPI_SILENCEDETECTOR_THRESHOLD, (u32 *)threshold); | 2515 | HPI_SILENCEDETECTOR_THRESHOLD, (u32 *)threshold); |
2811 | } | 2516 | } |
2812 | 2517 | ||
2813 | u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys, | 2518 | u16 hpi_tuner_query_band(const u32 h_tuner, const u32 index, u16 *pw_band) |
2814 | const u32 h_tuner, const u32 index, u16 *pw_band) | ||
2815 | { | 2519 | { |
2816 | u32 qr; | 2520 | u32 qr; |
2817 | u16 err; | 2521 | u16 err; |
2818 | 2522 | ||
2819 | err = hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_BAND, index, 0, | 2523 | err = hpi_control_query(h_tuner, HPI_TUNER_BAND, index, 0, &qr); |
2820 | &qr); | ||
2821 | *pw_band = (u16)qr; | 2524 | *pw_band = (u16)qr; |
2822 | return err; | 2525 | return err; |
2823 | } | 2526 | } |
2824 | 2527 | ||
2825 | u16 hpi_tuner_set_band(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2528 | u16 hpi_tuner_set_band(u32 h_control, u16 band) |
2826 | u16 band) | ||
2827 | { | 2529 | { |
2828 | return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_BAND, | 2530 | return hpi_control_param_set(h_control, HPI_TUNER_BAND, band, 0); |
2829 | band, 0); | ||
2830 | } | 2531 | } |
2831 | 2532 | ||
2832 | u16 hpi_tuner_get_band(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2533 | u16 hpi_tuner_get_band(u32 h_control, u16 *pw_band) |
2833 | u16 *pw_band) | ||
2834 | { | 2534 | { |
2835 | u32 band = 0; | 2535 | u32 band = 0; |
2836 | u16 error = 0; | 2536 | u16 error = 0; |
2837 | 2537 | ||
2838 | error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_BAND, | 2538 | error = hpi_control_param1_get(h_control, HPI_TUNER_BAND, &band); |
2839 | &band); | ||
2840 | if (pw_band) | 2539 | if (pw_band) |
2841 | *pw_band = (u16)band; | 2540 | *pw_band = (u16)band; |
2842 | return error; | 2541 | return error; |
2843 | } | 2542 | } |
2844 | 2543 | ||
2845 | u16 hpi_tuner_query_frequency(const struct hpi_hsubsys *ph_subsys, | 2544 | u16 hpi_tuner_query_frequency(const u32 h_tuner, const u32 index, |
2846 | const u32 h_tuner, const u32 index, const u16 band, u32 *pfreq) | 2545 | const u16 band, u32 *pfreq) |
2847 | { | 2546 | { |
2848 | return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_FREQ, index, | 2547 | return hpi_control_query(h_tuner, HPI_TUNER_FREQ, index, band, pfreq); |
2849 | band, pfreq); | ||
2850 | } | 2548 | } |
2851 | 2549 | ||
2852 | u16 hpi_tuner_set_frequency(const struct hpi_hsubsys *ph_subsys, | 2550 | u16 hpi_tuner_set_frequency(u32 h_control, u32 freq_ink_hz) |
2853 | u32 h_control, u32 freq_ink_hz) | ||
2854 | { | 2551 | { |
2855 | return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_FREQ, | 2552 | return hpi_control_param_set(h_control, HPI_TUNER_FREQ, freq_ink_hz, |
2856 | freq_ink_hz, 0); | 2553 | 0); |
2857 | } | 2554 | } |
2858 | 2555 | ||
2859 | u16 hpi_tuner_get_frequency(const struct hpi_hsubsys *ph_subsys, | 2556 | u16 hpi_tuner_get_frequency(u32 h_control, u32 *pw_freq_ink_hz) |
2860 | u32 h_control, u32 *pw_freq_ink_hz) | ||
2861 | { | 2557 | { |
2862 | return hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_FREQ, | 2558 | return hpi_control_param1_get(h_control, HPI_TUNER_FREQ, |
2863 | pw_freq_ink_hz); | 2559 | pw_freq_ink_hz); |
2864 | } | 2560 | } |
2865 | 2561 | ||
2866 | u16 hpi_tuner_query_gain(const struct hpi_hsubsys *ph_subsys, | 2562 | u16 hpi_tuner_query_gain(const u32 h_tuner, const u32 index, u16 *pw_gain) |
2867 | const u32 h_tuner, const u32 index, u16 *pw_gain) | ||
2868 | { | 2563 | { |
2869 | u32 qr; | 2564 | u32 qr; |
2870 | u16 err; | 2565 | u16 err; |
2871 | 2566 | ||
2872 | err = hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_BAND, index, 0, | 2567 | err = hpi_control_query(h_tuner, HPI_TUNER_BAND, index, 0, &qr); |
2873 | &qr); | ||
2874 | *pw_gain = (u16)qr; | 2568 | *pw_gain = (u16)qr; |
2875 | return err; | 2569 | return err; |
2876 | } | 2570 | } |
2877 | 2571 | ||
2878 | u16 hpi_tuner_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2572 | u16 hpi_tuner_set_gain(u32 h_control, short gain) |
2879 | short gain) | ||
2880 | { | 2573 | { |
2881 | return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_GAIN, | 2574 | return hpi_control_param_set(h_control, HPI_TUNER_GAIN, gain, 0); |
2882 | gain, 0); | ||
2883 | } | 2575 | } |
2884 | 2576 | ||
2885 | u16 hpi_tuner_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2577 | u16 hpi_tuner_get_gain(u32 h_control, short *pn_gain) |
2886 | short *pn_gain) | ||
2887 | { | 2578 | { |
2888 | u32 gain = 0; | 2579 | u32 gain = 0; |
2889 | u16 error = 0; | 2580 | u16 error = 0; |
2890 | 2581 | ||
2891 | error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_GAIN, | 2582 | error = hpi_control_param1_get(h_control, HPI_TUNER_GAIN, &gain); |
2892 | &gain); | ||
2893 | if (pn_gain) | 2583 | if (pn_gain) |
2894 | *pn_gain = (u16)gain; | 2584 | *pn_gain = (u16)gain; |
2895 | return error; | 2585 | return error; |
2896 | } | 2586 | } |
2897 | 2587 | ||
2898 | u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2588 | u16 hpi_tuner_get_rf_level(u32 h_control, short *pw_level) |
2899 | short *pw_level) | ||
2900 | { | 2589 | { |
2901 | struct hpi_message hm; | 2590 | struct hpi_message hm; |
2902 | struct hpi_response hr; | 2591 | struct hpi_response hr; |
2903 | 2592 | ||
2904 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2593 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2905 | HPI_CONTROL_GET_STATE); | 2594 | HPI_CONTROL_GET_STATE); |
2906 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2595 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2907 | hm.u.c.attribute = HPI_TUNER_LEVEL; | 2596 | return HPI_ERROR_INVALID_HANDLE; |
2908 | hm.u.c.param1 = HPI_TUNER_LEVEL_AVERAGE; | 2597 | hm.u.cu.attribute = HPI_TUNER_LEVEL_AVG; |
2909 | hpi_send_recv(&hm, &hr); | 2598 | hpi_send_recv(&hm, &hr); |
2910 | if (pw_level) | 2599 | if (pw_level) |
2911 | *pw_level = (short)hr.u.c.param1; | 2600 | *pw_level = hr.u.cu.tuner.s_level; |
2912 | return hr.error; | 2601 | return hr.error; |
2913 | } | 2602 | } |
2914 | 2603 | ||
2915 | u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys, | 2604 | u16 hpi_tuner_get_raw_rf_level(u32 h_control, short *pw_level) |
2916 | u32 h_control, short *pw_level) | ||
2917 | { | 2605 | { |
2918 | struct hpi_message hm; | 2606 | struct hpi_message hm; |
2919 | struct hpi_response hr; | 2607 | struct hpi_response hr; |
2920 | 2608 | ||
2921 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2609 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
2922 | HPI_CONTROL_GET_STATE); | 2610 | HPI_CONTROL_GET_STATE); |
2923 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2611 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2924 | hm.u.c.attribute = HPI_TUNER_LEVEL; | 2612 | return HPI_ERROR_INVALID_HANDLE; |
2925 | hm.u.c.param1 = HPI_TUNER_LEVEL_RAW; | 2613 | hm.u.cu.attribute = HPI_TUNER_LEVEL_RAW; |
2926 | hpi_send_recv(&hm, &hr); | 2614 | hpi_send_recv(&hm, &hr); |
2927 | if (pw_level) | 2615 | if (pw_level) |
2928 | *pw_level = (short)hr.u.c.param1; | 2616 | *pw_level = hr.u.cu.tuner.s_level; |
2929 | return hr.error; | 2617 | return hr.error; |
2930 | } | 2618 | } |
2931 | 2619 | ||
2932 | u16 hpi_tuner_query_deemphasis(const struct hpi_hsubsys *ph_subsys, | 2620 | u16 hpi_tuner_query_deemphasis(const u32 h_tuner, const u32 index, |
2933 | const u32 h_tuner, const u32 index, const u16 band, u32 *pdeemphasis) | 2621 | const u16 band, u32 *pdeemphasis) |
2934 | { | 2622 | { |
2935 | return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_DEEMPHASIS, | 2623 | return hpi_control_query(h_tuner, HPI_TUNER_DEEMPHASIS, index, band, |
2936 | index, band, pdeemphasis); | 2624 | pdeemphasis); |
2937 | } | 2625 | } |
2938 | 2626 | ||
2939 | u16 hpi_tuner_set_deemphasis(const struct hpi_hsubsys *ph_subsys, | 2627 | u16 hpi_tuner_set_deemphasis(u32 h_control, u32 deemphasis) |
2940 | u32 h_control, u32 deemphasis) | ||
2941 | { | 2628 | { |
2942 | return hpi_control_param_set(ph_subsys, h_control, | 2629 | return hpi_control_param_set(h_control, HPI_TUNER_DEEMPHASIS, |
2943 | HPI_TUNER_DEEMPHASIS, deemphasis, 0); | 2630 | deemphasis, 0); |
2944 | } | 2631 | } |
2945 | 2632 | ||
2946 | u16 hpi_tuner_get_deemphasis(const struct hpi_hsubsys *ph_subsys, | 2633 | u16 hpi_tuner_get_deemphasis(u32 h_control, u32 *pdeemphasis) |
2947 | u32 h_control, u32 *pdeemphasis) | ||
2948 | { | 2634 | { |
2949 | return hpi_control_param1_get(ph_subsys, h_control, | 2635 | return hpi_control_param1_get(h_control, HPI_TUNER_DEEMPHASIS, |
2950 | HPI_TUNER_DEEMPHASIS, pdeemphasis); | 2636 | pdeemphasis); |
2951 | } | 2637 | } |
2952 | 2638 | ||
2953 | u16 hpi_tuner_query_program(const struct hpi_hsubsys *ph_subsys, | 2639 | u16 hpi_tuner_query_program(const u32 h_tuner, u32 *pbitmap_program) |
2954 | const u32 h_tuner, u32 *pbitmap_program) | ||
2955 | { | 2640 | { |
2956 | return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_PROGRAM, 0, 0, | 2641 | return hpi_control_query(h_tuner, HPI_TUNER_PROGRAM, 0, 0, |
2957 | pbitmap_program); | 2642 | pbitmap_program); |
2958 | } | 2643 | } |
2959 | 2644 | ||
2960 | u16 hpi_tuner_set_program(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2645 | u16 hpi_tuner_set_program(u32 h_control, u32 program) |
2961 | u32 program) | ||
2962 | { | 2646 | { |
2963 | return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_PROGRAM, | 2647 | return hpi_control_param_set(h_control, HPI_TUNER_PROGRAM, program, |
2964 | program, 0); | 2648 | 0); |
2965 | } | 2649 | } |
2966 | 2650 | ||
2967 | u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2651 | u16 hpi_tuner_get_program(u32 h_control, u32 *pprogram) |
2968 | u32 *pprogram) | ||
2969 | { | 2652 | { |
2970 | return hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_PROGRAM, | 2653 | return hpi_control_param1_get(h_control, HPI_TUNER_PROGRAM, pprogram); |
2971 | pprogram); | ||
2972 | } | 2654 | } |
2973 | 2655 | ||
2974 | u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys, | 2656 | u16 hpi_tuner_get_hd_radio_dsp_version(u32 h_control, char *psz_dsp_version, |
2975 | u32 h_control, char *psz_dsp_version, const u32 string_size) | 2657 | const u32 string_size) |
2976 | { | 2658 | { |
2977 | return hpi_control_get_string(h_control, | 2659 | return hpi_control_get_string(h_control, |
2978 | HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size); | 2660 | HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size); |
2979 | } | 2661 | } |
2980 | 2662 | ||
2981 | u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys, | 2663 | u16 hpi_tuner_get_hd_radio_sdk_version(u32 h_control, char *psz_sdk_version, |
2982 | u32 h_control, char *psz_sdk_version, const u32 string_size) | 2664 | const u32 string_size) |
2983 | { | 2665 | { |
2984 | return hpi_control_get_string(h_control, | 2666 | return hpi_control_get_string(h_control, |
2985 | HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size); | 2667 | HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size); |
2986 | } | 2668 | } |
2987 | 2669 | ||
2988 | u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2670 | u16 hpi_tuner_get_status(u32 h_control, u16 *pw_status_mask, u16 *pw_status) |
2989 | u16 *pw_status_mask, u16 *pw_status) | ||
2990 | { | 2671 | { |
2991 | u32 status = 0; | 2672 | u32 status = 0; |
2992 | u16 error = 0; | 2673 | u16 error = 0; |
2993 | 2674 | ||
2994 | error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_STATUS, | 2675 | error = hpi_control_param1_get(h_control, HPI_TUNER_STATUS, &status); |
2995 | &status); | ||
2996 | if (pw_status) { | 2676 | if (pw_status) { |
2997 | if (!error) { | 2677 | if (!error) { |
2998 | *pw_status_mask = (u16)(status >> 16); | 2678 | *pw_status_mask = (u16)(status >> 16); |
@@ -3005,50 +2685,44 @@ u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
3005 | return error; | 2685 | return error; |
3006 | } | 2686 | } |
3007 | 2687 | ||
3008 | u16 hpi_tuner_set_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2688 | u16 hpi_tuner_set_mode(u32 h_control, u32 mode, u32 value) |
3009 | u32 mode, u32 value) | ||
3010 | { | 2689 | { |
3011 | return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_MODE, | 2690 | return hpi_control_param_set(h_control, HPI_TUNER_MODE, mode, value); |
3012 | mode, value); | ||
3013 | } | 2691 | } |
3014 | 2692 | ||
3015 | u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2693 | u16 hpi_tuner_get_mode(u32 h_control, u32 mode, u32 *pn_value) |
3016 | u32 mode, u32 *pn_value) | ||
3017 | { | 2694 | { |
3018 | return hpi_control_param_get(ph_subsys, h_control, HPI_TUNER_MODE, | 2695 | return hpi_control_param_get(h_control, HPI_TUNER_MODE, mode, 0, |
3019 | mode, 0, pn_value, NULL); | 2696 | pn_value, NULL); |
3020 | } | 2697 | } |
3021 | 2698 | ||
3022 | u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys, | 2699 | u16 hpi_tuner_get_hd_radio_signal_quality(u32 h_control, u32 *pquality) |
3023 | u32 h_control, u32 *pquality) | ||
3024 | { | 2700 | { |
3025 | return hpi_control_param1_get(ph_subsys, h_control, | 2701 | return hpi_control_param1_get(h_control, |
3026 | HPI_TUNER_HDRADIO_SIGNAL_QUALITY, pquality); | 2702 | HPI_TUNER_HDRADIO_SIGNAL_QUALITY, pquality); |
3027 | } | 2703 | } |
3028 | 2704 | ||
3029 | u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, | 2705 | u16 hpi_tuner_get_hd_radio_signal_blend(u32 h_control, u32 *pblend) |
3030 | u32 h_control, u32 *pblend) | ||
3031 | { | 2706 | { |
3032 | return hpi_control_param1_get(ph_subsys, h_control, | 2707 | return hpi_control_param1_get(h_control, HPI_TUNER_HDRADIO_BLEND, |
3033 | HPI_TUNER_HDRADIO_BLEND, pblend); | 2708 | pblend); |
3034 | } | 2709 | } |
3035 | 2710 | ||
3036 | u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys, | 2711 | u16 hpi_tuner_set_hd_radio_signal_blend(u32 h_control, const u32 blend) |
3037 | u32 h_control, const u32 blend) | ||
3038 | { | 2712 | { |
3039 | return hpi_control_param_set(ph_subsys, h_control, | 2713 | return hpi_control_param_set(h_control, HPI_TUNER_HDRADIO_BLEND, |
3040 | HPI_TUNER_HDRADIO_BLEND, blend, 0); | 2714 | blend, 0); |
3041 | } | 2715 | } |
3042 | 2716 | ||
3043 | u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2717 | u16 hpi_tuner_get_rds(u32 h_control, char *p_data) |
3044 | char *p_data) | ||
3045 | { | 2718 | { |
3046 | struct hpi_message hm; | 2719 | struct hpi_message hm; |
3047 | struct hpi_response hr; | 2720 | struct hpi_response hr; |
3048 | 2721 | ||
3049 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2722 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
3050 | HPI_CONTROL_GET_STATE); | 2723 | HPI_CONTROL_GET_STATE); |
3051 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2724 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2725 | return HPI_ERROR_INVALID_HANDLE; | ||
3052 | hm.u.c.attribute = HPI_TUNER_RDS; | 2726 | hm.u.c.attribute = HPI_TUNER_RDS; |
3053 | hpi_send_recv(&hm, &hr); | 2727 | hpi_send_recv(&hm, &hr); |
3054 | if (p_data) { | 2728 | if (p_data) { |
@@ -3059,80 +2733,82 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
3059 | return hr.error; | 2733 | return hr.error; |
3060 | } | 2734 | } |
3061 | 2735 | ||
3062 | u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys, | 2736 | u16 hpi_pad_get_channel_name(u32 h_control, char *psz_string, |
3063 | u32 h_control, char *psz_string, const u32 data_length) | 2737 | const u32 data_length) |
3064 | { | 2738 | { |
3065 | return hpi_control_get_string(h_control, HPI_PAD_CHANNEL_NAME, | 2739 | return hpi_control_get_string(h_control, HPI_PAD_CHANNEL_NAME, |
3066 | psz_string, data_length); | 2740 | psz_string, data_length); |
3067 | } | 2741 | } |
3068 | 2742 | ||
3069 | u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2743 | u16 hpi_pad_get_artist(u32 h_control, char *psz_string, const u32 data_length) |
3070 | char *psz_string, const u32 data_length) | ||
3071 | { | 2744 | { |
3072 | return hpi_control_get_string(h_control, HPI_PAD_ARTIST, psz_string, | 2745 | return hpi_control_get_string(h_control, HPI_PAD_ARTIST, psz_string, |
3073 | data_length); | 2746 | data_length); |
3074 | } | 2747 | } |
3075 | 2748 | ||
3076 | u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2749 | u16 hpi_pad_get_title(u32 h_control, char *psz_string, const u32 data_length) |
3077 | char *psz_string, const u32 data_length) | ||
3078 | { | 2750 | { |
3079 | return hpi_control_get_string(h_control, HPI_PAD_TITLE, psz_string, | 2751 | return hpi_control_get_string(h_control, HPI_PAD_TITLE, psz_string, |
3080 | data_length); | 2752 | data_length); |
3081 | } | 2753 | } |
3082 | 2754 | ||
3083 | u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2755 | u16 hpi_pad_get_comment(u32 h_control, char *psz_string, |
3084 | char *psz_string, const u32 data_length) | 2756 | const u32 data_length) |
3085 | { | 2757 | { |
3086 | return hpi_control_get_string(h_control, HPI_PAD_COMMENT, psz_string, | 2758 | return hpi_control_get_string(h_control, HPI_PAD_COMMENT, psz_string, |
3087 | data_length); | 2759 | data_length); |
3088 | } | 2760 | } |
3089 | 2761 | ||
3090 | u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys, | 2762 | u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY) |
3091 | u32 h_control, u32 *ppTY) | ||
3092 | { | 2763 | { |
3093 | return hpi_control_param1_get(ph_subsys, h_control, | 2764 | return hpi_control_param1_get(h_control, HPI_PAD_PROGRAM_TYPE, ppTY); |
3094 | HPI_PAD_PROGRAM_TYPE, ppTY); | ||
3095 | } | 2765 | } |
3096 | 2766 | ||
3097 | u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2767 | u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI) |
3098 | u32 *ppI) | ||
3099 | { | 2768 | { |
3100 | return hpi_control_param1_get(ph_subsys, h_control, | 2769 | return hpi_control_param1_get(h_control, HPI_PAD_PROGRAM_ID, ppI); |
3101 | HPI_PAD_PROGRAM_ID, ppI); | ||
3102 | } | 2770 | } |
3103 | 2771 | ||
3104 | u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys, | 2772 | u16 hpi_volume_query_channels(const u32 h_volume, u32 *p_channels) |
3105 | const u32 h_volume, u32 *p_channels) | ||
3106 | { | 2773 | { |
3107 | return hpi_control_query(ph_subsys, h_volume, HPI_VOLUME_NUM_CHANNELS, | 2774 | return hpi_control_query(h_volume, HPI_VOLUME_NUM_CHANNELS, 0, 0, |
3108 | 0, 0, p_channels); | 2775 | p_channels); |
3109 | } | 2776 | } |
3110 | 2777 | ||
3111 | u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2778 | u16 hpi_volume_set_gain(u32 h_control, short an_log_gain[HPI_MAX_CHANNELS] |
3112 | short an_log_gain[HPI_MAX_CHANNELS] | ||
3113 | ) | 2779 | ) |
3114 | { | 2780 | { |
3115 | return hpi_control_log_set2(h_control, HPI_VOLUME_GAIN, | 2781 | return hpi_control_log_set2(h_control, HPI_VOLUME_GAIN, |
3116 | an_log_gain[0], an_log_gain[1]); | 2782 | an_log_gain[0], an_log_gain[1]); |
3117 | } | 2783 | } |
3118 | 2784 | ||
3119 | u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2785 | u16 hpi_volume_get_gain(u32 h_control, short an_log_gain[HPI_MAX_CHANNELS] |
3120 | short an_log_gain[HPI_MAX_CHANNELS] | ||
3121 | ) | 2786 | ) |
3122 | { | 2787 | { |
3123 | return hpi_control_log_get2(ph_subsys, h_control, HPI_VOLUME_GAIN, | 2788 | return hpi_control_log_get2(h_control, HPI_VOLUME_GAIN, |
3124 | &an_log_gain[0], &an_log_gain[1]); | 2789 | &an_log_gain[0], &an_log_gain[1]); |
3125 | } | 2790 | } |
3126 | 2791 | ||
3127 | u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2792 | u16 hpi_volume_set_mute(u32 h_control, u32 mute) |
3128 | short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB) | 2793 | { |
2794 | return hpi_control_param_set(h_control, HPI_VOLUME_MUTE, mute, 0); | ||
2795 | } | ||
2796 | |||
2797 | u16 hpi_volume_get_mute(u32 h_control, u32 *mute) | ||
2798 | { | ||
2799 | return hpi_control_param1_get(h_control, HPI_VOLUME_MUTE, mute); | ||
2800 | } | ||
2801 | |||
2802 | u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB, | ||
2803 | short *max_gain_01dB, short *step_gain_01dB) | ||
3129 | { | 2804 | { |
3130 | struct hpi_message hm; | 2805 | struct hpi_message hm; |
3131 | struct hpi_response hr; | 2806 | struct hpi_response hr; |
3132 | 2807 | ||
3133 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2808 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
3134 | HPI_CONTROL_GET_STATE); | 2809 | HPI_CONTROL_GET_STATE); |
3135 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2810 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2811 | return HPI_ERROR_INVALID_HANDLE; | ||
3136 | hm.u.c.attribute = HPI_VOLUME_RANGE; | 2812 | hm.u.c.attribute = HPI_VOLUME_RANGE; |
3137 | 2813 | ||
3138 | hpi_send_recv(&hm, &hr); | 2814 | hpi_send_recv(&hm, &hr); |
@@ -3150,16 +2826,17 @@ u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
3150 | return hr.error; | 2826 | return hr.error; |
3151 | } | 2827 | } |
3152 | 2828 | ||
3153 | u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys, | 2829 | u16 hpi_volume_auto_fade_profile(u32 h_control, |
3154 | u32 h_control, short an_stop_gain0_01dB[HPI_MAX_CHANNELS], | 2830 | short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms, |
3155 | u32 duration_ms, u16 profile) | 2831 | u16 profile) |
3156 | { | 2832 | { |
3157 | struct hpi_message hm; | 2833 | struct hpi_message hm; |
3158 | struct hpi_response hr; | 2834 | struct hpi_response hr; |
3159 | 2835 | ||
3160 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2836 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
3161 | HPI_CONTROL_SET_STATE); | 2837 | HPI_CONTROL_SET_STATE); |
3162 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2838 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2839 | return HPI_ERROR_INVALID_HANDLE; | ||
3163 | 2840 | ||
3164 | memcpy(hm.u.c.an_log_value, an_stop_gain0_01dB, | 2841 | memcpy(hm.u.c.an_log_value, an_stop_gain0_01dB, |
3165 | sizeof(short) * HPI_MAX_CHANNELS); | 2842 | sizeof(short) * HPI_MAX_CHANNELS); |
@@ -3173,21 +2850,21 @@ u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys, | |||
3173 | return hr.error; | 2850 | return hr.error; |
3174 | } | 2851 | } |
3175 | 2852 | ||
3176 | u16 hpi_volume_auto_fade(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2853 | u16 hpi_volume_auto_fade(u32 h_control, |
3177 | short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms) | 2854 | short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms) |
3178 | { | 2855 | { |
3179 | return hpi_volume_auto_fade_profile(ph_subsys, h_control, | 2856 | return hpi_volume_auto_fade_profile(h_control, an_stop_gain0_01dB, |
3180 | an_stop_gain0_01dB, duration_ms, HPI_VOLUME_AUTOFADE_LOG); | 2857 | duration_ms, HPI_VOLUME_AUTOFADE_LOG); |
3181 | } | 2858 | } |
3182 | 2859 | ||
3183 | u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2860 | u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB) |
3184 | short an_gain0_01dB) | ||
3185 | { | 2861 | { |
3186 | struct hpi_message hm; | 2862 | struct hpi_message hm; |
3187 | struct hpi_response hr; | 2863 | struct hpi_response hr; |
3188 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2864 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
3189 | HPI_CONTROL_SET_STATE); | 2865 | HPI_CONTROL_SET_STATE); |
3190 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2866 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2867 | return HPI_ERROR_INVALID_HANDLE; | ||
3191 | hm.u.c.attribute = HPI_VOX_THRESHOLD; | 2868 | hm.u.c.attribute = HPI_VOX_THRESHOLD; |
3192 | 2869 | ||
3193 | hm.u.c.an_log_value[0] = an_gain0_01dB; | 2870 | hm.u.c.an_log_value[0] = an_gain0_01dB; |
@@ -3197,14 +2874,14 @@ u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
3197 | return hr.error; | 2874 | return hr.error; |
3198 | } | 2875 | } |
3199 | 2876 | ||
3200 | u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control, | 2877 | u16 hpi_vox_get_threshold(u32 h_control, short *an_gain0_01dB) |
3201 | short *an_gain0_01dB) | ||
3202 | { | 2878 | { |
3203 | struct hpi_message hm; | 2879 | struct hpi_message hm; |
3204 | struct hpi_response hr; | 2880 | struct hpi_response hr; |
3205 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, | 2881 | hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL, |
3206 | HPI_CONTROL_GET_STATE); | 2882 | HPI_CONTROL_GET_STATE); |
3207 | u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index); | 2883 | if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) |
2884 | return HPI_ERROR_INVALID_HANDLE; | ||
3208 | hm.u.c.attribute = HPI_VOX_THRESHOLD; | 2885 | hm.u.c.attribute = HPI_VOX_THRESHOLD; |
3209 | 2886 | ||
3210 | hpi_send_recv(&hm, &hr); | 2887 | hpi_send_recv(&hm, &hr); |
@@ -3213,728 +2890,3 @@ u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control, | |||
3213 | 2890 | ||
3214 | return hr.error; | 2891 | return hr.error; |
3215 | } | 2892 | } |
3216 | |||
3217 | static size_t strv_packet_size = MIN_STRV_PACKET_SIZE; | ||
3218 | |||
3219 | static size_t entity_type_to_size[LAST_ENTITY_TYPE] = { | ||
3220 | 0, | ||
3221 | sizeof(struct hpi_entity), | ||
3222 | sizeof(void *), | ||
3223 | |||
3224 | sizeof(int), | ||
3225 | sizeof(float), | ||
3226 | sizeof(double), | ||
3227 | |||
3228 | sizeof(char), | ||
3229 | sizeof(char), | ||
3230 | |||
3231 | 4 * sizeof(char), | ||
3232 | 16 * sizeof(char), | ||
3233 | 6 * sizeof(char), | ||
3234 | }; | ||
3235 | |||
3236 | static inline size_t hpi_entity_size(struct hpi_entity *entity_ptr) | ||
3237 | { | ||
3238 | return entity_ptr->header.size; | ||
3239 | } | ||
3240 | |||
3241 | static inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr) | ||
3242 | { | ||
3243 | return sizeof(entity_ptr->header); | ||
3244 | } | ||
3245 | |||
3246 | static inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr) | ||
3247 | { | ||
3248 | return hpi_entity_size(entity_ptr) - | ||
3249 | hpi_entity_header_size(entity_ptr); | ||
3250 | } | ||
3251 | |||
3252 | static inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr) | ||
3253 | { | ||
3254 | return hpi_entity_value_size(entity_ptr) / | ||
3255 | entity_type_to_size[entity_ptr->header.type]; | ||
3256 | } | ||
3257 | |||
3258 | static inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity | ||
3259 | *entity_ptr) | ||
3260 | { | ||
3261 | return (void *)(((u8 *)entity_ptr) + hpi_entity_size(entity_ptr)); | ||
3262 | } | ||
3263 | |||
3264 | static inline u16 hpi_entity_check_type(const enum e_entity_type t) | ||
3265 | { | ||
3266 | if (t >= 0 && t < STR_TYPE_FIELD_MAX) | ||
3267 | return 0; | ||
3268 | return HPI_ERROR_ENTITY_TYPE_INVALID; | ||
3269 | } | ||
3270 | |||
3271 | static inline u16 hpi_entity_check_role(const enum e_entity_role r) | ||
3272 | { | ||
3273 | if (r >= 0 && r < STR_ROLE_FIELD_MAX) | ||
3274 | return 0; | ||
3275 | return HPI_ERROR_ENTITY_ROLE_INVALID; | ||
3276 | } | ||
3277 | |||
3278 | static u16 hpi_entity_get_next(struct hpi_entity *entity, int recursive_flag, | ||
3279 | void *guard_p, struct hpi_entity **next) | ||
3280 | { | ||
3281 | HPI_DEBUG_ASSERT(entity != NULL); | ||
3282 | HPI_DEBUG_ASSERT(next != NULL); | ||
3283 | HPI_DEBUG_ASSERT(hpi_entity_size(entity) != 0); | ||
3284 | |||
3285 | if (guard_p <= (void *)entity) { | ||
3286 | *next = NULL; | ||
3287 | return 0; | ||
3288 | } | ||
3289 | |||
3290 | if (recursive_flag && entity->header.type == entity_type_sequence) | ||
3291 | *next = (struct hpi_entity *)entity->value; | ||
3292 | else | ||
3293 | *next = (struct hpi_entity *)hpi_entity_ptr_to_next(entity); | ||
3294 | |||
3295 | if (guard_p <= (void *)*next) { | ||
3296 | *next = NULL; | ||
3297 | return 0; | ||
3298 | } | ||
3299 | |||
3300 | HPI_DEBUG_ASSERT(guard_p >= (void *)hpi_entity_ptr_to_next(*next)); | ||
3301 | return 0; | ||
3302 | } | ||
3303 | |||
3304 | u16 hpi_entity_find_next(struct hpi_entity *container_entity, | ||
3305 | enum e_entity_type type, enum e_entity_role role, int recursive_flag, | ||
3306 | struct hpi_entity **current_match) | ||
3307 | { | ||
3308 | struct hpi_entity *tmp = NULL; | ||
3309 | void *guard_p = NULL; | ||
3310 | |||
3311 | HPI_DEBUG_ASSERT(container_entity != NULL); | ||
3312 | guard_p = hpi_entity_ptr_to_next(container_entity); | ||
3313 | |||
3314 | if (*current_match != NULL) | ||
3315 | hpi_entity_get_next(*current_match, recursive_flag, guard_p, | ||
3316 | &tmp); | ||
3317 | else | ||
3318 | hpi_entity_get_next(container_entity, 1, guard_p, &tmp); | ||
3319 | |||
3320 | while (tmp) { | ||
3321 | u16 err; | ||
3322 | |||
3323 | HPI_DEBUG_ASSERT((void *)tmp >= (void *)container_entity); | ||
3324 | |||
3325 | if ((!type || tmp->header.type == type) && (!role | ||
3326 | || tmp->header.role == role)) { | ||
3327 | *current_match = tmp; | ||
3328 | return 0; | ||
3329 | } | ||
3330 | |||
3331 | err = hpi_entity_get_next(tmp, recursive_flag, guard_p, | ||
3332 | current_match); | ||
3333 | if (err) | ||
3334 | return err; | ||
3335 | |||
3336 | tmp = *current_match; | ||
3337 | } | ||
3338 | |||
3339 | *current_match = NULL; | ||
3340 | return 0; | ||
3341 | } | ||
3342 | |||
3343 | void hpi_entity_free(struct hpi_entity *entity) | ||
3344 | { | ||
3345 | kfree(entity); | ||
3346 | } | ||
3347 | |||
3348 | static u16 hpi_entity_alloc_and_copy(struct hpi_entity *src, | ||
3349 | struct hpi_entity **dst) | ||
3350 | { | ||
3351 | size_t buf_size; | ||
3352 | HPI_DEBUG_ASSERT(dst != NULL); | ||
3353 | HPI_DEBUG_ASSERT(src != NULL); | ||
3354 | |||
3355 | buf_size = hpi_entity_size(src); | ||
3356 | *dst = kmalloc(buf_size, GFP_KERNEL); | ||
3357 | if (*dst == NULL) | ||
3358 | return HPI_ERROR_MEMORY_ALLOC; | ||
3359 | memcpy(*dst, src, buf_size); | ||
3360 | return 0; | ||
3361 | } | ||
3362 | |||
3363 | u16 hpi_universal_info(const struct hpi_hsubsys *ph_subsys, u32 hC, | ||
3364 | struct hpi_entity **info) | ||
3365 | { | ||
3366 | struct hpi_msg_strv hm; | ||
3367 | struct hpi_res_strv *phr; | ||
3368 | u16 hpi_err; | ||
3369 | int remaining_attempts = 2; | ||
3370 | size_t resp_packet_size = 1024; | ||
3371 | |||
3372 | *info = NULL; | ||
3373 | |||
3374 | while (remaining_attempts--) { | ||
3375 | phr = kmalloc(resp_packet_size, GFP_KERNEL); | ||
3376 | HPI_DEBUG_ASSERT(phr != NULL); | ||
3377 | |||
3378 | hpi_init_message_responseV1(&hm.h, (u16)sizeof(hm), &phr->h, | ||
3379 | (u16)resp_packet_size, HPI_OBJ_CONTROL, | ||
3380 | HPI_CONTROL_GET_INFO); | ||
3381 | u32TOINDEXES(hC, &hm.h.adapter_index, &hm.h.obj_index); | ||
3382 | |||
3383 | hm.strv.header.size = sizeof(hm.strv); | ||
3384 | phr->strv.header.size = resp_packet_size - sizeof(phr->h); | ||
3385 | |||
3386 | hpi_send_recv((struct hpi_message *)&hm.h, | ||
3387 | (struct hpi_response *)&phr->h); | ||
3388 | if (phr->h.error == HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL) { | ||
3389 | |||
3390 | HPI_DEBUG_ASSERT(phr->h.specific_error > | ||
3391 | MIN_STRV_PACKET_SIZE | ||
3392 | && phr->h.specific_error < 1500); | ||
3393 | resp_packet_size = phr->h.specific_error; | ||
3394 | } else { | ||
3395 | remaining_attempts = 0; | ||
3396 | if (!phr->h.error) | ||
3397 | hpi_entity_alloc_and_copy(&phr->strv, info); | ||
3398 | } | ||
3399 | |||
3400 | hpi_err = phr->h.error; | ||
3401 | kfree(phr); | ||
3402 | } | ||
3403 | |||
3404 | return hpi_err; | ||
3405 | } | ||
3406 | |||
3407 | u16 hpi_universal_get(const struct hpi_hsubsys *ph_subsys, u32 hC, | ||
3408 | struct hpi_entity **value) | ||
3409 | { | ||
3410 | struct hpi_msg_strv hm; | ||
3411 | struct hpi_res_strv *phr; | ||
3412 | u16 hpi_err; | ||
3413 | int remaining_attempts = 2; | ||
3414 | |||
3415 | *value = NULL; | ||
3416 | |||
3417 | while (remaining_attempts--) { | ||
3418 | phr = kmalloc(strv_packet_size, GFP_KERNEL); | ||
3419 | if (!phr) | ||
3420 | return HPI_ERROR_MEMORY_ALLOC; | ||
3421 | |||
3422 | hpi_init_message_responseV1(&hm.h, (u16)sizeof(hm), &phr->h, | ||
3423 | (u16)strv_packet_size, HPI_OBJ_CONTROL, | ||
3424 | HPI_CONTROL_GET_STATE); | ||
3425 | u32TOINDEXES(hC, &hm.h.adapter_index, &hm.h.obj_index); | ||
3426 | |||
3427 | hm.strv.header.size = sizeof(hm.strv); | ||
3428 | phr->strv.header.size = strv_packet_size - sizeof(phr->h); | ||
3429 | |||
3430 | hpi_send_recv((struct hpi_message *)&hm.h, | ||
3431 | (struct hpi_response *)&phr->h); | ||
3432 | if (phr->h.error == HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL) { | ||
3433 | |||
3434 | HPI_DEBUG_ASSERT(phr->h.specific_error > | ||
3435 | MIN_STRV_PACKET_SIZE | ||
3436 | && phr->h.specific_error < 1000); | ||
3437 | strv_packet_size = phr->h.specific_error; | ||
3438 | } else { | ||
3439 | remaining_attempts = 0; | ||
3440 | if (!phr->h.error) | ||
3441 | hpi_entity_alloc_and_copy(&phr->strv, value); | ||
3442 | } | ||
3443 | |||
3444 | hpi_err = phr->h.error; | ||
3445 | kfree(phr); | ||
3446 | } | ||
3447 | |||
3448 | return hpi_err; | ||
3449 | } | ||
3450 | |||
3451 | u16 hpi_universal_set(const struct hpi_hsubsys *ph_subsys, u32 hC, | ||
3452 | struct hpi_entity *value) | ||
3453 | { | ||
3454 | struct hpi_msg_strv *phm; | ||
3455 | struct hpi_res_strv hr; | ||
3456 | |||
3457 | phm = kmalloc(sizeof(phm->h) + value->header.size, GFP_KERNEL); | ||
3458 | HPI_DEBUG_ASSERT(phm != NULL); | ||
3459 | |||
3460 | hpi_init_message_responseV1(&phm->h, | ||
3461 | sizeof(phm->h) + value->header.size, &hr.h, sizeof(hr), | ||
3462 | HPI_OBJ_CONTROL, HPI_CONTROL_SET_STATE); | ||
3463 | u32TOINDEXES(hC, &phm->h.adapter_index, &phm->h.obj_index); | ||
3464 | hr.strv.header.size = sizeof(hr.strv); | ||
3465 | |||
3466 | memcpy(&phm->strv, value, value->header.size); | ||
3467 | hpi_send_recv((struct hpi_message *)&phm->h, | ||
3468 | (struct hpi_response *)&hr.h); | ||
3469 | |||
3470 | return hr.h.error; | ||
3471 | } | ||
3472 | |||
3473 | u16 hpi_entity_alloc_and_pack(const enum e_entity_type type, | ||
3474 | const size_t item_count, const enum e_entity_role role, void *value, | ||
3475 | struct hpi_entity **entity) | ||
3476 | { | ||
3477 | size_t bytes_to_copy, total_size; | ||
3478 | u16 hE = 0; | ||
3479 | *entity = NULL; | ||
3480 | |||
3481 | hE = hpi_entity_check_type(type); | ||
3482 | if (hE) | ||
3483 | return hE; | ||
3484 | |||
3485 | HPI_DEBUG_ASSERT(role > entity_role_null && type < LAST_ENTITY_TYPE); | ||
3486 | |||
3487 | bytes_to_copy = entity_type_to_size[type] * item_count; | ||
3488 | total_size = hpi_entity_header_size(*entity) + bytes_to_copy; | ||
3489 | |||
3490 | HPI_DEBUG_ASSERT(total_size >= hpi_entity_header_size(*entity) | ||
3491 | && total_size < STR_SIZE_FIELD_MAX); | ||
3492 | |||
3493 | *entity = kmalloc(total_size, GFP_KERNEL); | ||
3494 | if (*entity == NULL) | ||
3495 | return HPI_ERROR_MEMORY_ALLOC; | ||
3496 | memcpy((*entity)->value, value, bytes_to_copy); | ||
3497 | (*entity)->header.size = | ||
3498 | hpi_entity_header_size(*entity) + bytes_to_copy; | ||
3499 | (*entity)->header.type = type; | ||
3500 | (*entity)->header.role = role; | ||
3501 | return 0; | ||
3502 | } | ||
3503 | |||
3504 | u16 hpi_entity_copy_value_from(struct hpi_entity *entity, | ||
3505 | enum e_entity_type type, size_t item_count, void *value_dst_p) | ||
3506 | { | ||
3507 | size_t bytes_to_copy; | ||
3508 | |||
3509 | if (entity->header.type != type) | ||
3510 | return HPI_ERROR_ENTITY_TYPE_MISMATCH; | ||
3511 | |||
3512 | if (hpi_entity_item_count(entity) != item_count) | ||
3513 | return HPI_ERROR_ENTITY_ITEM_COUNT; | ||
3514 | |||
3515 | bytes_to_copy = entity_type_to_size[type] * item_count; | ||
3516 | memcpy(value_dst_p, entity->value, bytes_to_copy); | ||
3517 | return 0; | ||
3518 | } | ||
3519 | |||
3520 | u16 hpi_entity_unpack(struct hpi_entity *entity, enum e_entity_type *type, | ||
3521 | size_t *item_count, enum e_entity_role *role, void **value) | ||
3522 | { | ||
3523 | u16 err = 0; | ||
3524 | HPI_DEBUG_ASSERT(entity != NULL); | ||
3525 | |||
3526 | if (type) | ||
3527 | *type = entity->header.type; | ||
3528 | |||
3529 | if (role) | ||
3530 | *role = entity->header.role; | ||
3531 | |||
3532 | if (value) | ||
3533 | *value = entity->value; | ||
3534 | |||
3535 | if (item_count != NULL) { | ||
3536 | if (entity->header.type == entity_type_sequence) { | ||
3537 | void *guard_p = hpi_entity_ptr_to_next(entity); | ||
3538 | struct hpi_entity *next = NULL; | ||
3539 | void *contents = entity->value; | ||
3540 | |||
3541 | *item_count = 0; | ||
3542 | while (contents < guard_p) { | ||
3543 | (*item_count)++; | ||
3544 | err = hpi_entity_get_next(contents, 0, | ||
3545 | guard_p, &next); | ||
3546 | if (next == NULL || err) | ||
3547 | break; | ||
3548 | contents = next; | ||
3549 | } | ||
3550 | } else { | ||
3551 | *item_count = hpi_entity_item_count(entity); | ||
3552 | } | ||
3553 | } | ||
3554 | return err; | ||
3555 | } | ||
3556 | |||
3557 | u16 hpi_gpio_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | ||
3558 | u32 *ph_gpio, u16 *pw_number_input_bits, u16 *pw_number_output_bits) | ||
3559 | { | ||
3560 | struct hpi_message hm; | ||
3561 | struct hpi_response hr; | ||
3562 | hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_OPEN); | ||
3563 | hm.adapter_index = adapter_index; | ||
3564 | |||
3565 | hpi_send_recv(&hm, &hr); | ||
3566 | |||
3567 | if (hr.error == 0) { | ||
3568 | *ph_gpio = | ||
3569 | hpi_indexes_to_handle(HPI_OBJ_GPIO, adapter_index, 0); | ||
3570 | if (pw_number_input_bits) | ||
3571 | *pw_number_input_bits = hr.u.l.number_input_bits; | ||
3572 | if (pw_number_output_bits) | ||
3573 | *pw_number_output_bits = hr.u.l.number_output_bits; | ||
3574 | } else | ||
3575 | *ph_gpio = 0; | ||
3576 | return hr.error; | ||
3577 | } | ||
3578 | |||
3579 | u16 hpi_gpio_read_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | ||
3580 | u16 bit_index, u16 *pw_bit_data) | ||
3581 | { | ||
3582 | struct hpi_message hm; | ||
3583 | struct hpi_response hr; | ||
3584 | hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_READ_BIT); | ||
3585 | u32TOINDEX(h_gpio, &hm.adapter_index); | ||
3586 | hm.u.l.bit_index = bit_index; | ||
3587 | |||
3588 | hpi_send_recv(&hm, &hr); | ||
3589 | |||
3590 | *pw_bit_data = hr.u.l.bit_data[0]; | ||
3591 | return hr.error; | ||
3592 | } | ||
3593 | |||
3594 | u16 hpi_gpio_read_all_bits(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | ||
3595 | u16 aw_all_bit_data[4] | ||
3596 | ) | ||
3597 | { | ||
3598 | struct hpi_message hm; | ||
3599 | struct hpi_response hr; | ||
3600 | hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_READ_ALL); | ||
3601 | u32TOINDEX(h_gpio, &hm.adapter_index); | ||
3602 | |||
3603 | hpi_send_recv(&hm, &hr); | ||
3604 | |||
3605 | if (aw_all_bit_data) { | ||
3606 | aw_all_bit_data[0] = hr.u.l.bit_data[0]; | ||
3607 | aw_all_bit_data[1] = hr.u.l.bit_data[1]; | ||
3608 | aw_all_bit_data[2] = hr.u.l.bit_data[2]; | ||
3609 | aw_all_bit_data[3] = hr.u.l.bit_data[3]; | ||
3610 | } | ||
3611 | return hr.error; | ||
3612 | } | ||
3613 | |||
3614 | u16 hpi_gpio_write_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | ||
3615 | u16 bit_index, u16 bit_data) | ||
3616 | { | ||
3617 | struct hpi_message hm; | ||
3618 | struct hpi_response hr; | ||
3619 | hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_WRITE_BIT); | ||
3620 | u32TOINDEX(h_gpio, &hm.adapter_index); | ||
3621 | hm.u.l.bit_index = bit_index; | ||
3622 | hm.u.l.bit_data = bit_data; | ||
3623 | |||
3624 | hpi_send_recv(&hm, &hr); | ||
3625 | |||
3626 | return hr.error; | ||
3627 | } | ||
3628 | |||
3629 | u16 hpi_gpio_write_status(const struct hpi_hsubsys *ph_subsys, u32 h_gpio, | ||
3630 | u16 aw_all_bit_data[4] | ||
3631 | ) | ||
3632 | { | ||
3633 | struct hpi_message hm; | ||
3634 | struct hpi_response hr; | ||
3635 | hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, | ||
3636 | HPI_GPIO_WRITE_STATUS); | ||
3637 | u32TOINDEX(h_gpio, &hm.adapter_index); | ||
3638 | |||
3639 | hpi_send_recv(&hm, &hr); | ||
3640 | |||
3641 | if (aw_all_bit_data) { | ||
3642 | aw_all_bit_data[0] = hr.u.l.bit_data[0]; | ||
3643 | aw_all_bit_data[1] = hr.u.l.bit_data[1]; | ||
3644 | aw_all_bit_data[2] = hr.u.l.bit_data[2]; | ||
3645 | aw_all_bit_data[3] = hr.u.l.bit_data[3]; | ||
3646 | } | ||
3647 | return hr.error; | ||
3648 | } | ||
3649 | |||
3650 | u16 hpi_async_event_open(const struct hpi_hsubsys *ph_subsys, | ||
3651 | u16 adapter_index, u32 *ph_async) | ||
3652 | { | ||
3653 | struct hpi_message hm; | ||
3654 | struct hpi_response hr; | ||
3655 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT, | ||
3656 | HPI_ASYNCEVENT_OPEN); | ||
3657 | hm.adapter_index = adapter_index; | ||
3658 | |||
3659 | hpi_send_recv(&hm, &hr); | ||
3660 | |||
3661 | if (hr.error == 0) | ||
3662 | |||
3663 | *ph_async = | ||
3664 | hpi_indexes_to_handle(HPI_OBJ_ASYNCEVENT, | ||
3665 | adapter_index, 0); | ||
3666 | else | ||
3667 | *ph_async = 0; | ||
3668 | return hr.error; | ||
3669 | |||
3670 | } | ||
3671 | |||
3672 | u16 hpi_async_event_close(const struct hpi_hsubsys *ph_subsys, u32 h_async) | ||
3673 | { | ||
3674 | struct hpi_message hm; | ||
3675 | struct hpi_response hr; | ||
3676 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT, | ||
3677 | HPI_ASYNCEVENT_OPEN); | ||
3678 | u32TOINDEX(h_async, &hm.adapter_index); | ||
3679 | |||
3680 | hpi_send_recv(&hm, &hr); | ||
3681 | |||
3682 | return hr.error; | ||
3683 | } | ||
3684 | |||
3685 | u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async, | ||
3686 | u16 maximum_events, struct hpi_async_event *p_events, | ||
3687 | u16 *pw_number_returned) | ||
3688 | { | ||
3689 | |||
3690 | return 0; | ||
3691 | } | ||
3692 | |||
3693 | u16 hpi_async_event_get_count(const struct hpi_hsubsys *ph_subsys, | ||
3694 | u32 h_async, u16 *pw_count) | ||
3695 | { | ||
3696 | struct hpi_message hm; | ||
3697 | struct hpi_response hr; | ||
3698 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT, | ||
3699 | HPI_ASYNCEVENT_GETCOUNT); | ||
3700 | u32TOINDEX(h_async, &hm.adapter_index); | ||
3701 | |||
3702 | hpi_send_recv(&hm, &hr); | ||
3703 | |||
3704 | if (hr.error == 0) | ||
3705 | if (pw_count) | ||
3706 | *pw_count = hr.u.as.u.count.count; | ||
3707 | |||
3708 | return hr.error; | ||
3709 | } | ||
3710 | |||
3711 | u16 hpi_async_event_get(const struct hpi_hsubsys *ph_subsys, u32 h_async, | ||
3712 | u16 maximum_events, struct hpi_async_event *p_events, | ||
3713 | u16 *pw_number_returned) | ||
3714 | { | ||
3715 | struct hpi_message hm; | ||
3716 | struct hpi_response hr; | ||
3717 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT, | ||
3718 | HPI_ASYNCEVENT_GET); | ||
3719 | u32TOINDEX(h_async, &hm.adapter_index); | ||
3720 | |||
3721 | hpi_send_recv(&hm, &hr); | ||
3722 | if (!hr.error) { | ||
3723 | memcpy(p_events, &hr.u.as.u.event, | ||
3724 | sizeof(struct hpi_async_event)); | ||
3725 | *pw_number_returned = 1; | ||
3726 | } | ||
3727 | |||
3728 | return hr.error; | ||
3729 | } | ||
3730 | |||
3731 | u16 hpi_nv_memory_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | ||
3732 | u32 *ph_nv_memory, u16 *pw_size_in_bytes) | ||
3733 | { | ||
3734 | struct hpi_message hm; | ||
3735 | struct hpi_response hr; | ||
3736 | hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY, | ||
3737 | HPI_NVMEMORY_OPEN); | ||
3738 | hm.adapter_index = adapter_index; | ||
3739 | |||
3740 | hpi_send_recv(&hm, &hr); | ||
3741 | |||
3742 | if (hr.error == 0) { | ||
3743 | *ph_nv_memory = | ||
3744 | hpi_indexes_to_handle(HPI_OBJ_NVMEMORY, adapter_index, | ||
3745 | 0); | ||
3746 | if (pw_size_in_bytes) | ||
3747 | *pw_size_in_bytes = hr.u.n.size_in_bytes; | ||
3748 | } else | ||
3749 | *ph_nv_memory = 0; | ||
3750 | return hr.error; | ||
3751 | } | ||
3752 | |||
3753 | u16 hpi_nv_memory_read_byte(const struct hpi_hsubsys *ph_subsys, | ||
3754 | u32 h_nv_memory, u16 index, u16 *pw_data) | ||
3755 | { | ||
3756 | struct hpi_message hm; | ||
3757 | struct hpi_response hr; | ||
3758 | hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY, | ||
3759 | HPI_NVMEMORY_READ_BYTE); | ||
3760 | u32TOINDEX(h_nv_memory, &hm.adapter_index); | ||
3761 | hm.u.n.address = index; | ||
3762 | |||
3763 | hpi_send_recv(&hm, &hr); | ||
3764 | |||
3765 | *pw_data = hr.u.n.data; | ||
3766 | return hr.error; | ||
3767 | } | ||
3768 | |||
3769 | u16 hpi_nv_memory_write_byte(const struct hpi_hsubsys *ph_subsys, | ||
3770 | u32 h_nv_memory, u16 index, u16 data) | ||
3771 | { | ||
3772 | struct hpi_message hm; | ||
3773 | struct hpi_response hr; | ||
3774 | hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY, | ||
3775 | HPI_NVMEMORY_WRITE_BYTE); | ||
3776 | u32TOINDEX(h_nv_memory, &hm.adapter_index); | ||
3777 | hm.u.n.address = index; | ||
3778 | hm.u.n.data = data; | ||
3779 | |||
3780 | hpi_send_recv(&hm, &hr); | ||
3781 | |||
3782 | return hr.error; | ||
3783 | } | ||
3784 | |||
3785 | u16 hpi_profile_open_all(const struct hpi_hsubsys *ph_subsys, | ||
3786 | u16 adapter_index, u16 profile_index, u32 *ph_profile, | ||
3787 | u16 *pw_max_profiles) | ||
3788 | { | ||
3789 | struct hpi_message hm; | ||
3790 | struct hpi_response hr; | ||
3791 | hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, | ||
3792 | HPI_PROFILE_OPEN_ALL); | ||
3793 | hm.adapter_index = adapter_index; | ||
3794 | hm.obj_index = profile_index; | ||
3795 | hpi_send_recv(&hm, &hr); | ||
3796 | |||
3797 | *pw_max_profiles = hr.u.p.u.o.max_profiles; | ||
3798 | if (hr.error == 0) | ||
3799 | *ph_profile = | ||
3800 | hpi_indexes_to_handle(HPI_OBJ_PROFILE, adapter_index, | ||
3801 | profile_index); | ||
3802 | else | ||
3803 | *ph_profile = 0; | ||
3804 | return hr.error; | ||
3805 | } | ||
3806 | |||
3807 | u16 hpi_profile_get(const struct hpi_hsubsys *ph_subsys, u32 h_profile, | ||
3808 | u16 bin_index, u16 *pw_seconds, u32 *pmicro_seconds, u32 *pcall_count, | ||
3809 | u32 *pmax_micro_seconds, u32 *pmin_micro_seconds) | ||
3810 | { | ||
3811 | struct hpi_message hm; | ||
3812 | struct hpi_response hr; | ||
3813 | hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, HPI_PROFILE_GET); | ||
3814 | u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index); | ||
3815 | hm.u.p.bin_index = bin_index; | ||
3816 | hpi_send_recv(&hm, &hr); | ||
3817 | if (pw_seconds) | ||
3818 | *pw_seconds = hr.u.p.u.t.seconds; | ||
3819 | if (pmicro_seconds) | ||
3820 | *pmicro_seconds = hr.u.p.u.t.micro_seconds; | ||
3821 | if (pcall_count) | ||
3822 | *pcall_count = hr.u.p.u.t.call_count; | ||
3823 | if (pmax_micro_seconds) | ||
3824 | *pmax_micro_seconds = hr.u.p.u.t.max_micro_seconds; | ||
3825 | if (pmin_micro_seconds) | ||
3826 | *pmin_micro_seconds = hr.u.p.u.t.min_micro_seconds; | ||
3827 | return hr.error; | ||
3828 | } | ||
3829 | |||
3830 | u16 hpi_profile_get_utilization(const struct hpi_hsubsys *ph_subsys, | ||
3831 | u32 h_profile, u32 *putilization) | ||
3832 | { | ||
3833 | struct hpi_message hm; | ||
3834 | struct hpi_response hr; | ||
3835 | hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, | ||
3836 | HPI_PROFILE_GET_UTILIZATION); | ||
3837 | u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index); | ||
3838 | hpi_send_recv(&hm, &hr); | ||
3839 | if (hr.error) { | ||
3840 | if (putilization) | ||
3841 | *putilization = 0; | ||
3842 | } else { | ||
3843 | if (putilization) | ||
3844 | *putilization = hr.u.p.u.t.call_count; | ||
3845 | } | ||
3846 | return hr.error; | ||
3847 | } | ||
3848 | |||
3849 | u16 hpi_profile_get_name(const struct hpi_hsubsys *ph_subsys, u32 h_profile, | ||
3850 | u16 bin_index, char *sz_name, u16 name_length) | ||
3851 | { | ||
3852 | struct hpi_message hm; | ||
3853 | struct hpi_response hr; | ||
3854 | hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, | ||
3855 | HPI_PROFILE_GET_NAME); | ||
3856 | u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index); | ||
3857 | hm.u.p.bin_index = bin_index; | ||
3858 | hpi_send_recv(&hm, &hr); | ||
3859 | if (hr.error) { | ||
3860 | if (sz_name) | ||
3861 | strcpy(sz_name, "??"); | ||
3862 | } else { | ||
3863 | if (sz_name) | ||
3864 | memcpy(sz_name, (char *)hr.u.p.u.n.sz_name, | ||
3865 | name_length); | ||
3866 | } | ||
3867 | return hr.error; | ||
3868 | } | ||
3869 | |||
3870 | u16 hpi_profile_start_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile) | ||
3871 | { | ||
3872 | struct hpi_message hm; | ||
3873 | struct hpi_response hr; | ||
3874 | hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, | ||
3875 | HPI_PROFILE_START_ALL); | ||
3876 | u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index); | ||
3877 | hpi_send_recv(&hm, &hr); | ||
3878 | |||
3879 | return hr.error; | ||
3880 | } | ||
3881 | |||
3882 | u16 hpi_profile_stop_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile) | ||
3883 | { | ||
3884 | struct hpi_message hm; | ||
3885 | struct hpi_response hr; | ||
3886 | hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, | ||
3887 | HPI_PROFILE_STOP_ALL); | ||
3888 | u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index); | ||
3889 | hpi_send_recv(&hm, &hr); | ||
3890 | |||
3891 | return hr.error; | ||
3892 | } | ||
3893 | |||
3894 | u16 hpi_watchdog_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index, | ||
3895 | u32 *ph_watchdog) | ||
3896 | { | ||
3897 | struct hpi_message hm; | ||
3898 | struct hpi_response hr; | ||
3899 | hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG, | ||
3900 | HPI_WATCHDOG_OPEN); | ||
3901 | hm.adapter_index = adapter_index; | ||
3902 | |||
3903 | hpi_send_recv(&hm, &hr); | ||
3904 | |||
3905 | if (hr.error == 0) | ||
3906 | *ph_watchdog = | ||
3907 | hpi_indexes_to_handle(HPI_OBJ_WATCHDOG, adapter_index, | ||
3908 | 0); | ||
3909 | else | ||
3910 | *ph_watchdog = 0; | ||
3911 | return hr.error; | ||
3912 | } | ||
3913 | |||
3914 | u16 hpi_watchdog_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog, | ||
3915 | u32 time_millisec) | ||
3916 | { | ||
3917 | struct hpi_message hm; | ||
3918 | struct hpi_response hr; | ||
3919 | hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG, | ||
3920 | HPI_WATCHDOG_SET_TIME); | ||
3921 | u32TOINDEX(h_watchdog, &hm.adapter_index); | ||
3922 | hm.u.w.time_ms = time_millisec; | ||
3923 | |||
3924 | hpi_send_recv(&hm, &hr); | ||
3925 | |||
3926 | return hr.error; | ||
3927 | } | ||
3928 | |||
3929 | u16 hpi_watchdog_ping(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog) | ||
3930 | { | ||
3931 | struct hpi_message hm; | ||
3932 | struct hpi_response hr; | ||
3933 | hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG, | ||
3934 | HPI_WATCHDOG_PING); | ||
3935 | u32TOINDEX(h_watchdog, &hm.adapter_index); | ||
3936 | |||
3937 | hpi_send_recv(&hm, &hr); | ||
3938 | |||
3939 | return hr.error; | ||
3940 | } | ||
diff --git a/sound/pci/asihpi/hpimsginit.c b/sound/pci/asihpi/hpimsginit.c index 8e1d099ed7e4..628376ce4a49 100644 --- a/sound/pci/asihpi/hpimsginit.c +++ b/sound/pci/asihpi/hpimsginit.c | |||
@@ -32,21 +32,6 @@ static u16 res_size[HPI_OBJ_MAXINDEX + 1] = HPI_RESPONSE_SIZE_BY_OBJECT; | |||
32 | static u16 gwSSX2_bypass; | 32 | static u16 gwSSX2_bypass; |
33 | 33 | ||
34 | /** \internal | 34 | /** \internal |
35 | * Used by ASIO driver to disable SSX2 for a single process | ||
36 | * \param phSubSys Pointer to HPI subsystem handle. | ||
37 | * \param wBypass New bypass setting 0 = off, nonzero = on | ||
38 | * \return Previous bypass setting. | ||
39 | */ | ||
40 | u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass) | ||
41 | { | ||
42 | u16 old_value = gwSSX2_bypass; | ||
43 | |||
44 | gwSSX2_bypass = bypass; | ||
45 | |||
46 | return old_value; | ||
47 | } | ||
48 | |||
49 | /** \internal | ||
50 | * initialize the HPI message structure | 35 | * initialize the HPI message structure |
51 | */ | 36 | */ |
52 | static void hpi_init_message(struct hpi_message *phm, u16 object, | 37 | static void hpi_init_message(struct hpi_message *phm, u16 object, |
@@ -65,7 +50,8 @@ static void hpi_init_message(struct hpi_message *phm, u16 object, | |||
65 | phm->object = object; | 50 | phm->object = object; |
66 | phm->function = function; | 51 | phm->function = function; |
67 | phm->version = 0; | 52 | phm->version = 0; |
68 | /* Expect adapter index to be set by caller */ | 53 | phm->adapter_index = HPI_ADAPTER_INDEX_INVALID; |
54 | /* Expect actual adapter index to be set by caller */ | ||
69 | } | 55 | } |
70 | 56 | ||
71 | /** \internal | 57 | /** \internal |
diff --git a/sound/pci/asihpi/hpimsginit.h b/sound/pci/asihpi/hpimsginit.h index 864ad020c9b3..bfd330d78b58 100644 --- a/sound/pci/asihpi/hpimsginit.h +++ b/sound/pci/asihpi/hpimsginit.h | |||
@@ -21,11 +21,15 @@ | |||
21 | (C) Copyright AudioScience Inc. 2007 | 21 | (C) Copyright AudioScience Inc. 2007 |
22 | *******************************************************************************/ | 22 | *******************************************************************************/ |
23 | /* Initialise response headers, or msg/response pairs. | 23 | /* Initialise response headers, or msg/response pairs. |
24 | Note that it is valid to just init a response e.g. when a lower level is preparing | 24 | Note that it is valid to just init a response e.g. when a lower level is |
25 | a response to a message. | 25 | preparing a response to a message. |
26 | However, when sending a message, a matching response buffer always must be prepared | 26 | However, when sending a message, a matching response buffer must always be |
27 | prepared. | ||
27 | */ | 28 | */ |
28 | 29 | ||
30 | #ifndef _HPIMSGINIT_H_ | ||
31 | #define _HPIMSGINIT_H_ | ||
32 | |||
29 | void hpi_init_response(struct hpi_response *phr, u16 object, u16 function, | 33 | void hpi_init_response(struct hpi_response *phr, u16 object, u16 function, |
30 | u16 error); | 34 | u16 error); |
31 | 35 | ||
@@ -38,3 +42,5 @@ void hpi_init_responseV1(struct hpi_response_header *phr, u16 size, | |||
38 | void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size, | 42 | void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size, |
39 | struct hpi_response_header *phr, u16 res_size, u16 object, | 43 | struct hpi_response_header *phr, u16 res_size, u16 object, |
40 | u16 function); | 44 | u16 function); |
45 | |||
46 | #endif /* _HPIMSGINIT_H_ */ | ||
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index f01ab964f602..bcbdf30a6aa0 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c | |||
@@ -23,6 +23,7 @@ Extended Message Function With Response Cacheing | |||
23 | #define SOURCEFILE_NAME "hpimsgx.c" | 23 | #define SOURCEFILE_NAME "hpimsgx.c" |
24 | #include "hpi_internal.h" | 24 | #include "hpi_internal.h" |
25 | #include "hpimsginit.h" | 25 | #include "hpimsginit.h" |
26 | #include "hpicmn.h" | ||
26 | #include "hpimsgx.h" | 27 | #include "hpimsgx.h" |
27 | #include "hpidebug.h" | 28 | #include "hpidebug.h" |
28 | 29 | ||
@@ -42,22 +43,24 @@ static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci | |||
42 | 43 | ||
43 | for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) { | 44 | for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) { |
44 | if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID | 45 | if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID |
45 | && asihpi_pci_tbl[i].vendor != pci_info->vendor_id) | 46 | && asihpi_pci_tbl[i].vendor != |
47 | pci_info->pci_dev->vendor) | ||
46 | continue; | 48 | continue; |
47 | if (asihpi_pci_tbl[i].device != PCI_ANY_ID | 49 | if (asihpi_pci_tbl[i].device != PCI_ANY_ID |
48 | && asihpi_pci_tbl[i].device != pci_info->device_id) | 50 | && asihpi_pci_tbl[i].device != |
51 | pci_info->pci_dev->device) | ||
49 | continue; | 52 | continue; |
50 | if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID | 53 | if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID |
51 | && asihpi_pci_tbl[i].subvendor != | 54 | && asihpi_pci_tbl[i].subvendor != |
52 | pci_info->subsys_vendor_id) | 55 | pci_info->pci_dev->subsystem_vendor) |
53 | continue; | 56 | continue; |
54 | if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID | 57 | if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID |
55 | && asihpi_pci_tbl[i].subdevice != | 58 | && asihpi_pci_tbl[i].subdevice != |
56 | pci_info->subsys_device_id) | 59 | pci_info->pci_dev->subsystem_device) |
57 | continue; | 60 | continue; |
58 | 61 | ||
59 | HPI_DEBUG_LOG(DEBUG, " %x,%lu\n", i, | 62 | /* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i, |
60 | asihpi_pci_tbl[i].driver_data); | 63 | asihpi_pci_tbl[i].driver_data); */ |
61 | return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data; | 64 | return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data; |
62 | } | 65 | } |
63 | 66 | ||
@@ -67,21 +70,12 @@ static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci | |||
67 | static inline void hw_entry_point(struct hpi_message *phm, | 70 | static inline void hw_entry_point(struct hpi_message *phm, |
68 | struct hpi_response *phr) | 71 | struct hpi_response *phr) |
69 | { | 72 | { |
70 | 73 | if ((phm->adapter_index < HPI_MAX_ADAPTERS) | |
71 | hpi_handler_func *ep; | 74 | && hpi_entry_points[phm->adapter_index]) |
72 | 75 | hpi_entry_points[phm->adapter_index] (phm, phr); | |
73 | if (phm->adapter_index < HPI_MAX_ADAPTERS) { | 76 | else |
74 | ep = (hpi_handler_func *) hpi_entry_points[phm-> | 77 | hpi_init_response(phr, phm->object, phm->function, |
75 | adapter_index]; | 78 | HPI_ERROR_PROCESSING_MESSAGE); |
76 | if (ep) { | ||
77 | HPI_DEBUG_MESSAGE(DEBUG, phm); | ||
78 | ep(phm, phr); | ||
79 | HPI_DEBUG_RESPONSE(phr); | ||
80 | return; | ||
81 | } | ||
82 | } | ||
83 | hpi_init_response(phr, phm->object, phm->function, | ||
84 | HPI_ERROR_PROCESSING_MESSAGE); | ||
85 | } | 79 | } |
86 | 80 | ||
87 | static void adapter_open(struct hpi_message *phm, struct hpi_response *phr); | 81 | static void adapter_open(struct hpi_message *phm, struct hpi_response *phr); |
@@ -100,6 +94,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr, | |||
100 | void *h_owner); | 94 | void *h_owner); |
101 | 95 | ||
102 | static void HPIMSGX__reset(u16 adapter_index); | 96 | static void HPIMSGX__reset(u16 adapter_index); |
97 | |||
103 | static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr); | 98 | static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr); |
104 | static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); | 99 | static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); |
105 | 100 | ||
@@ -153,8 +148,6 @@ static struct hpi_stream_response | |||
153 | 148 | ||
154 | static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS]; | 149 | static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS]; |
155 | 150 | ||
156 | static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS; | ||
157 | |||
158 | static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS]; | 151 | static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS]; |
159 | 152 | ||
160 | /* use these to keep track of opens from user mode apps/DLLs */ | 153 | /* use these to keep track of opens from user mode apps/DLLs */ |
@@ -167,6 +160,11 @@ static struct asi_open_state | |||
167 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, | 160 | static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, |
168 | void *h_owner) | 161 | void *h_owner) |
169 | { | 162 | { |
163 | if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID) | ||
164 | HPI_DEBUG_LOG(WARNING, | ||
165 | "suspicious adapter index %d in subsys message 0x%x.\n", | ||
166 | phm->adapter_index, phm->function); | ||
167 | |||
170 | switch (phm->function) { | 168 | switch (phm->function) { |
171 | case HPI_SUBSYS_GET_VERSION: | 169 | case HPI_SUBSYS_GET_VERSION: |
172 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, | 170 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, |
@@ -204,85 +202,37 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr, | |||
204 | HPI_SUBSYS_DRIVER_UNLOAD, 0); | 202 | HPI_SUBSYS_DRIVER_UNLOAD, 0); |
205 | return; | 203 | return; |
206 | 204 | ||
207 | case HPI_SUBSYS_GET_INFO: | ||
208 | HPI_COMMON(phm, phr); | ||
209 | break; | ||
210 | |||
211 | case HPI_SUBSYS_FIND_ADAPTERS: | ||
212 | memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS, | ||
213 | sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS)); | ||
214 | break; | ||
215 | case HPI_SUBSYS_GET_NUM_ADAPTERS: | 205 | case HPI_SUBSYS_GET_NUM_ADAPTERS: |
216 | memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS, | ||
217 | sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS)); | ||
218 | phr->function = HPI_SUBSYS_GET_NUM_ADAPTERS; | ||
219 | break; | ||
220 | case HPI_SUBSYS_GET_ADAPTER: | 206 | case HPI_SUBSYS_GET_ADAPTER: |
221 | { | 207 | HPI_COMMON(phm, phr); |
222 | int count = phm->adapter_index; | 208 | break; |
223 | int index = 0; | ||
224 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, | ||
225 | HPI_SUBSYS_GET_ADAPTER, 0); | ||
226 | |||
227 | /* This is complicated by the fact that we want to | ||
228 | * "skip" 0's in the adapter list. | ||
229 | * First, make sure we are pointing to a | ||
230 | * non-zero adapter type. | ||
231 | */ | ||
232 | while (gRESP_HPI_SUBSYS_FIND_ADAPTERS. | ||
233 | s.aw_adapter_list[index] == 0) { | ||
234 | index++; | ||
235 | if (index >= HPI_MAX_ADAPTERS) | ||
236 | break; | ||
237 | } | ||
238 | while (count) { | ||
239 | /* move on to the next adapter */ | ||
240 | index++; | ||
241 | if (index >= HPI_MAX_ADAPTERS) | ||
242 | break; | ||
243 | while (gRESP_HPI_SUBSYS_FIND_ADAPTERS. | ||
244 | s.aw_adapter_list[index] == 0) { | ||
245 | index++; | ||
246 | if (index >= HPI_MAX_ADAPTERS) | ||
247 | break; | ||
248 | } | ||
249 | count--; | ||
250 | } | ||
251 | 209 | ||
252 | if (index < HPI_MAX_ADAPTERS) { | ||
253 | phr->u.s.adapter_index = (u16)index; | ||
254 | phr->u.s.aw_adapter_list[0] = | ||
255 | gRESP_HPI_SUBSYS_FIND_ADAPTERS. | ||
256 | s.aw_adapter_list[index]; | ||
257 | } else { | ||
258 | phr->u.s.adapter_index = 0; | ||
259 | phr->u.s.aw_adapter_list[0] = 0; | ||
260 | phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER; | ||
261 | } | ||
262 | break; | ||
263 | } | ||
264 | case HPI_SUBSYS_CREATE_ADAPTER: | 210 | case HPI_SUBSYS_CREATE_ADAPTER: |
265 | HPIMSGX__init(phm, phr); | 211 | HPIMSGX__init(phm, phr); |
266 | break; | 212 | break; |
213 | |||
267 | case HPI_SUBSYS_DELETE_ADAPTER: | 214 | case HPI_SUBSYS_DELETE_ADAPTER: |
268 | HPIMSGX__cleanup(phm->adapter_index, h_owner); | 215 | HPIMSGX__cleanup(phm->obj_index, h_owner); |
269 | { | 216 | { |
270 | struct hpi_message hm; | 217 | struct hpi_message hm; |
271 | struct hpi_response hr; | 218 | struct hpi_response hr; |
272 | /* call to HPI_ADAPTER_CLOSE */ | ||
273 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, | 219 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER, |
274 | HPI_ADAPTER_CLOSE); | 220 | HPI_ADAPTER_CLOSE); |
275 | hm.adapter_index = phm->adapter_index; | 221 | hm.adapter_index = phm->obj_index; |
276 | hw_entry_point(&hm, &hr); | 222 | hw_entry_point(&hm, &hr); |
277 | } | 223 | } |
278 | hw_entry_point(phm, phr); | 224 | if ((phm->obj_index < HPI_MAX_ADAPTERS) |
279 | gRESP_HPI_SUBSYS_FIND_ADAPTERS.s. | 225 | && hpi_entry_points[phm->obj_index]) { |
280 | aw_adapter_list[phm->adapter_index] | 226 | hpi_entry_points[phm->obj_index] (phm, phr); |
281 | = 0; | 227 | hpi_entry_points[phm->obj_index] = NULL; |
282 | hpi_entry_points[phm->adapter_index] = NULL; | 228 | } else |
229 | phr->error = HPI_ERROR_INVALID_OBJ_INDEX; | ||
230 | |||
283 | break; | 231 | break; |
284 | default: | 232 | default: |
285 | hw_entry_point(phm, phr); | 233 | /* Must explicitly handle every subsys message in this switch */ |
234 | hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, | ||
235 | HPI_ERROR_INVALID_FUNC); | ||
286 | break; | 236 | break; |
287 | } | 237 | } |
288 | } | 238 | } |
@@ -409,33 +359,7 @@ void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr, | |||
409 | break; | 359 | break; |
410 | } | 360 | } |
411 | HPI_DEBUG_RESPONSE(phr); | 361 | HPI_DEBUG_RESPONSE(phr); |
412 | #if 1 | 362 | |
413 | if (phr->error >= HPI_ERROR_BACKEND_BASE) { | ||
414 | void *ep = NULL; | ||
415 | char *ep_name; | ||
416 | |||
417 | HPI_DEBUG_MESSAGE(ERROR, phm); | ||
418 | |||
419 | if (phm->adapter_index < HPI_MAX_ADAPTERS) | ||
420 | ep = hpi_entry_points[phm->adapter_index]; | ||
421 | |||
422 | /* Don't need this? Have adapter index in debug info | ||
423 | Know at driver load time index->backend mapping */ | ||
424 | if (ep == HPI_6000) | ||
425 | ep_name = "HPI_6000"; | ||
426 | else if (ep == HPI_6205) | ||
427 | ep_name = "HPI_6205"; | ||
428 | else | ||
429 | ep_name = "unknown"; | ||
430 | |||
431 | HPI_DEBUG_LOG(ERROR, "HPI %s response - error# %d\n", ep_name, | ||
432 | phr->error); | ||
433 | |||
434 | if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) | ||
435 | hpi_debug_data((u16 *)phm, | ||
436 | sizeof(*phm) / sizeof(u16)); | ||
437 | } | ||
438 | #endif | ||
439 | } | 363 | } |
440 | 364 | ||
441 | static void adapter_open(struct hpi_message *phm, struct hpi_response *phr) | 365 | static void adapter_open(struct hpi_message *phm, struct hpi_response *phr) |
@@ -484,7 +408,7 @@ static void instream_open(struct hpi_message *phm, struct hpi_response *phr, | |||
484 | else { | 408 | else { |
485 | instream_user_open[phm->adapter_index][phm-> | 409 | instream_user_open[phm->adapter_index][phm-> |
486 | obj_index].open_flag = 1; | 410 | obj_index].open_flag = 1; |
487 | hpios_msgxlock_un_lock(&msgx_lock); | 411 | hpios_msgxlock_unlock(&msgx_lock); |
488 | 412 | ||
489 | /* issue a reset */ | 413 | /* issue a reset */ |
490 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 414 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
@@ -509,7 +433,7 @@ static void instream_open(struct hpi_message *phm, struct hpi_response *phr, | |||
509 | sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); | 433 | sizeof(rESP_HPI_ISTREAM_OPEN[0][0])); |
510 | } | 434 | } |
511 | } | 435 | } |
512 | hpios_msgxlock_un_lock(&msgx_lock); | 436 | hpios_msgxlock_unlock(&msgx_lock); |
513 | } | 437 | } |
514 | 438 | ||
515 | static void instream_close(struct hpi_message *phm, struct hpi_response *phr, | 439 | static void instream_close(struct hpi_message *phm, struct hpi_response *phr, |
@@ -530,7 +454,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr, | |||
530 | phm->wAdapterIndex, phm->wObjIndex, hOwner); */ | 454 | phm->wAdapterIndex, phm->wObjIndex, hOwner); */ |
531 | instream_user_open[phm->adapter_index][phm-> | 455 | instream_user_open[phm->adapter_index][phm-> |
532 | obj_index].h_owner = NULL; | 456 | obj_index].h_owner = NULL; |
533 | hpios_msgxlock_un_lock(&msgx_lock); | 457 | hpios_msgxlock_unlock(&msgx_lock); |
534 | /* issue a reset */ | 458 | /* issue a reset */ |
535 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, | 459 | hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM, |
536 | HPI_ISTREAM_RESET); | 460 | HPI_ISTREAM_RESET); |
@@ -556,7 +480,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr, | |||
556 | obj_index].h_owner); | 480 | obj_index].h_owner); |
557 | phr->error = HPI_ERROR_OBJ_NOT_OPEN; | 481 | phr->error = HPI_ERROR_OBJ_NOT_OPEN; |
558 | } | 482 | } |
559 | hpios_msgxlock_un_lock(&msgx_lock); | 483 | hpios_msgxlock_unlock(&msgx_lock); |
560 | } | 484 | } |
561 | 485 | ||
562 | static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, | 486 | static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, |
@@ -581,7 +505,7 @@ static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, | |||
581 | else { | 505 | else { |
582 | outstream_user_open[phm->adapter_index][phm-> | 506 | outstream_user_open[phm->adapter_index][phm-> |
583 | obj_index].open_flag = 1; | 507 | obj_index].open_flag = 1; |
584 | hpios_msgxlock_un_lock(&msgx_lock); | 508 | hpios_msgxlock_unlock(&msgx_lock); |
585 | 509 | ||
586 | /* issue a reset */ | 510 | /* issue a reset */ |
587 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 511 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
@@ -606,7 +530,7 @@ static void outstream_open(struct hpi_message *phm, struct hpi_response *phr, | |||
606 | sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); | 530 | sizeof(rESP_HPI_OSTREAM_OPEN[0][0])); |
607 | } | 531 | } |
608 | } | 532 | } |
609 | hpios_msgxlock_un_lock(&msgx_lock); | 533 | hpios_msgxlock_unlock(&msgx_lock); |
610 | } | 534 | } |
611 | 535 | ||
612 | static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, | 536 | static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, |
@@ -628,7 +552,7 @@ static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, | |||
628 | phm->wAdapterIndex, phm->wObjIndex, hOwner); */ | 552 | phm->wAdapterIndex, phm->wObjIndex, hOwner); */ |
629 | outstream_user_open[phm->adapter_index][phm-> | 553 | outstream_user_open[phm->adapter_index][phm-> |
630 | obj_index].h_owner = NULL; | 554 | obj_index].h_owner = NULL; |
631 | hpios_msgxlock_un_lock(&msgx_lock); | 555 | hpios_msgxlock_unlock(&msgx_lock); |
632 | /* issue a reset */ | 556 | /* issue a reset */ |
633 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, | 557 | hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM, |
634 | HPI_OSTREAM_RESET); | 558 | HPI_OSTREAM_RESET); |
@@ -654,7 +578,7 @@ static void outstream_close(struct hpi_message *phm, struct hpi_response *phr, | |||
654 | obj_index].h_owner); | 578 | obj_index].h_owner); |
655 | phr->error = HPI_ERROR_OBJ_NOT_OPEN; | 579 | phr->error = HPI_ERROR_OBJ_NOT_OPEN; |
656 | } | 580 | } |
657 | hpios_msgxlock_un_lock(&msgx_lock); | 581 | hpios_msgxlock_unlock(&msgx_lock); |
658 | } | 582 | } |
659 | 583 | ||
660 | static u16 adapter_prepare(u16 adapter) | 584 | static u16 adapter_prepare(u16 adapter) |
@@ -683,16 +607,9 @@ static u16 adapter_prepare(u16 adapter) | |||
683 | if (hr.error) | 607 | if (hr.error) |
684 | return hr.error; | 608 | return hr.error; |
685 | 609 | ||
686 | aDAPTER_INFO[adapter].num_outstreams = hr.u.a.num_outstreams; | 610 | aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams; |
687 | aDAPTER_INFO[adapter].num_instreams = hr.u.a.num_instreams; | 611 | aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams; |
688 | aDAPTER_INFO[adapter].type = hr.u.a.adapter_type; | 612 | aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type; |
689 | |||
690 | gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list[adapter] = | ||
691 | hr.u.a.adapter_type; | ||
692 | gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters++; | ||
693 | if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters > HPI_MAX_ADAPTERS) | ||
694 | gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters = | ||
695 | HPI_MAX_ADAPTERS; | ||
696 | 613 | ||
697 | /* call to HPI_OSTREAM_OPEN */ | 614 | /* call to HPI_OSTREAM_OPEN */ |
698 | for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) { | 615 | for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) { |
@@ -727,7 +644,7 @@ static u16 adapter_prepare(u16 adapter) | |||
727 | memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, | 644 | memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr, |
728 | sizeof(rESP_HPI_MIXER_OPEN[0])); | 645 | sizeof(rESP_HPI_MIXER_OPEN[0])); |
729 | 646 | ||
730 | return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.error; | 647 | return 0; |
731 | } | 648 | } |
732 | 649 | ||
733 | static void HPIMSGX__reset(u16 adapter_index) | 650 | static void HPIMSGX__reset(u16 adapter_index) |
@@ -737,12 +654,6 @@ static void HPIMSGX__reset(u16 adapter_index) | |||
737 | struct hpi_response hr; | 654 | struct hpi_response hr; |
738 | 655 | ||
739 | if (adapter_index == HPIMSGX_ALLADAPTERS) { | 656 | if (adapter_index == HPIMSGX_ALLADAPTERS) { |
740 | /* reset all responses to contain errors */ | ||
741 | hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, | ||
742 | HPI_SUBSYS_FIND_ADAPTERS, 0); | ||
743 | memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr, | ||
744 | sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS)); | ||
745 | |||
746 | for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) { | 657 | for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) { |
747 | 658 | ||
748 | hpi_init_response(&hr, HPI_OBJ_ADAPTER, | 659 | hpi_init_response(&hr, HPI_OBJ_ADAPTER, |
@@ -783,12 +694,6 @@ static void HPIMSGX__reset(u16 adapter_index) | |||
783 | rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error = | 694 | rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error = |
784 | HPI_ERROR_INVALID_OBJ; | 695 | HPI_ERROR_INVALID_OBJ; |
785 | } | 696 | } |
786 | if (gRESP_HPI_SUBSYS_FIND_ADAPTERS. | ||
787 | s.aw_adapter_list[adapter_index]) { | ||
788 | gRESP_HPI_SUBSYS_FIND_ADAPTERS. | ||
789 | s.aw_adapter_list[adapter_index] = 0; | ||
790 | gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters--; | ||
791 | } | ||
792 | } | 697 | } |
793 | } | 698 | } |
794 | 699 | ||
@@ -802,15 +707,9 @@ static u16 HPIMSGX__init(struct hpi_message *phm, | |||
802 | hpi_handler_func *entry_point_func; | 707 | hpi_handler_func *entry_point_func; |
803 | struct hpi_response hr; | 708 | struct hpi_response hr; |
804 | 709 | ||
805 | if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters >= HPI_MAX_ADAPTERS) | ||
806 | return HPI_ERROR_BAD_ADAPTER_NUMBER; | ||
807 | |||
808 | /* Init response here so we can pass in previous adapter list */ | 710 | /* Init response here so we can pass in previous adapter list */ |
809 | hpi_init_response(&hr, phm->object, phm->function, | 711 | hpi_init_response(&hr, phm->object, phm->function, |
810 | HPI_ERROR_INVALID_OBJ); | 712 | HPI_ERROR_INVALID_OBJ); |
811 | memcpy(hr.u.s.aw_adapter_list, | ||
812 | gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list, | ||
813 | sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list)); | ||
814 | 713 | ||
815 | entry_point_func = | 714 | entry_point_func = |
816 | hpi_lookup_entry_point_function(phm->u.s.resource.r.pci); | 715 | hpi_lookup_entry_point_function(phm->u.s.resource.r.pci); |
@@ -860,7 +759,7 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner) | |||
860 | struct hpi_response hr; | 759 | struct hpi_response hr; |
861 | 760 | ||
862 | HPI_DEBUG_LOG(DEBUG, | 761 | HPI_DEBUG_LOG(DEBUG, |
863 | "close adapter %d ostream %d\n", | 762 | "Close adapter %d ostream %d\n", |
864 | adapter, i); | 763 | adapter, i); |
865 | 764 | ||
866 | hpi_init_message_response(&hm, &hr, | 765 | hpi_init_message_response(&hm, &hr, |
@@ -884,7 +783,7 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner) | |||
884 | struct hpi_response hr; | 783 | struct hpi_response hr; |
885 | 784 | ||
886 | HPI_DEBUG_LOG(DEBUG, | 785 | HPI_DEBUG_LOG(DEBUG, |
887 | "close adapter %d istream %d\n", | 786 | "Close adapter %d istream %d\n", |
888 | adapter, i); | 787 | adapter, i); |
889 | 788 | ||
890 | hpi_init_message_response(&hm, &hr, | 789 | hpi_init_message_response(&hm, &hr, |
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c index 22dbd91811a4..cd624f13ff8e 100644 --- a/sound/pci/asihpi/hpioctl.c +++ b/sound/pci/asihpi/hpioctl.c | |||
@@ -30,6 +30,7 @@ Common Linux HPI ioctl and module probe/remove functions | |||
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
33 | #include <linux/pci.h> | ||
33 | #include <linux/stringify.h> | 34 | #include <linux/stringify.h> |
34 | 35 | ||
35 | #ifdef MODULE_FIRMWARE | 36 | #ifdef MODULE_FIRMWARE |
@@ -45,7 +46,7 @@ MODULE_FIRMWARE("asihpi/dsp8900.bin"); | |||
45 | static int prealloc_stream_buf; | 46 | static int prealloc_stream_buf; |
46 | module_param(prealloc_stream_buf, int, S_IRUGO); | 47 | module_param(prealloc_stream_buf, int, S_IRUGO); |
47 | MODULE_PARM_DESC(prealloc_stream_buf, | 48 | MODULE_PARM_DESC(prealloc_stream_buf, |
48 | "preallocate size for per-adapter stream buffer"); | 49 | "Preallocate size for per-adapter stream buffer"); |
49 | 50 | ||
50 | /* Allow the debug level to be changed after module load. | 51 | /* Allow the debug level to be changed after module load. |
51 | E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel | 52 | E.g. echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel |
@@ -121,8 +122,8 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
121 | phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg; | 122 | phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg; |
122 | 123 | ||
123 | /* Read the message and response pointers from user space. */ | 124 | /* Read the message and response pointers from user space. */ |
124 | if (get_user(puhm, &phpi_ioctl_data->phm) || | 125 | if (get_user(puhm, &phpi_ioctl_data->phm) |
125 | get_user(puhr, &phpi_ioctl_data->phr)) { | 126 | || get_user(puhr, &phpi_ioctl_data->phr)) { |
126 | err = -EFAULT; | 127 | err = -EFAULT; |
127 | goto out; | 128 | goto out; |
128 | } | 129 | } |
@@ -135,7 +136,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
135 | if (hm->h.size > sizeof(*hm)) | 136 | if (hm->h.size > sizeof(*hm)) |
136 | hm->h.size = sizeof(*hm); | 137 | hm->h.size = sizeof(*hm); |
137 | 138 | ||
138 | /*printk(KERN_INFO "message size %d\n", hm->h.wSize); */ | 139 | /* printk(KERN_INFO "message size %d\n", hm->h.wSize); */ |
139 | 140 | ||
140 | uncopied_bytes = copy_from_user(hm, puhm, hm->h.size); | 141 | uncopied_bytes = copy_from_user(hm, puhm, hm->h.size); |
141 | if (uncopied_bytes) { | 142 | if (uncopied_bytes) { |
@@ -155,8 +156,13 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
155 | goto out; | 156 | goto out; |
156 | } | 157 | } |
157 | 158 | ||
159 | if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) { | ||
160 | err = -EINVAL; | ||
161 | goto out; | ||
162 | } | ||
163 | |||
158 | pa = &adapters[hm->h.adapter_index]; | 164 | pa = &adapters[hm->h.adapter_index]; |
159 | hr->h.size = 0; | 165 | hr->h.size = res_max_size; |
160 | if (hm->h.object == HPI_OBJ_SUBSYSTEM) { | 166 | if (hm->h.object == HPI_OBJ_SUBSYSTEM) { |
161 | switch (hm->h.function) { | 167 | switch (hm->h.function) { |
162 | case HPI_SUBSYS_CREATE_ADAPTER: | 168 | case HPI_SUBSYS_CREATE_ADAPTER: |
@@ -216,7 +222,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
216 | */ | 222 | */ |
217 | if (pa->buffer_size < size) { | 223 | if (pa->buffer_size < size) { |
218 | HPI_DEBUG_LOG(DEBUG, | 224 | HPI_DEBUG_LOG(DEBUG, |
219 | "realloc adapter %d stream " | 225 | "Realloc adapter %d stream " |
220 | "buffer from %zd to %d\n", | 226 | "buffer from %zd to %d\n", |
221 | hm->h.adapter_index, | 227 | hm->h.adapter_index, |
222 | pa->buffer_size, size); | 228 | pa->buffer_size, size); |
@@ -259,7 +265,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
259 | copy_from_user(pa->p_buffer, ptr, size); | 265 | copy_from_user(pa->p_buffer, ptr, size); |
260 | if (uncopied_bytes) | 266 | if (uncopied_bytes) |
261 | HPI_DEBUG_LOG(WARNING, | 267 | HPI_DEBUG_LOG(WARNING, |
262 | "missed %d of %d " | 268 | "Missed %d of %d " |
263 | "bytes from user\n", uncopied_bytes, | 269 | "bytes from user\n", uncopied_bytes, |
264 | size); | 270 | size); |
265 | } | 271 | } |
@@ -271,7 +277,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
271 | copy_to_user(ptr, pa->p_buffer, size); | 277 | copy_to_user(ptr, pa->p_buffer, size); |
272 | if (uncopied_bytes) | 278 | if (uncopied_bytes) |
273 | HPI_DEBUG_LOG(WARNING, | 279 | HPI_DEBUG_LOG(WARNING, |
274 | "missed %d of %d " "bytes to user\n", | 280 | "Missed %d of %d " "bytes to user\n", |
275 | uncopied_bytes, size); | 281 | uncopied_bytes, size); |
276 | } | 282 | } |
277 | 283 | ||
@@ -290,9 +296,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
290 | if (hr->h.size > res_max_size) { | 296 | if (hr->h.size > res_max_size) { |
291 | HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size, | 297 | HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size, |
292 | res_max_size); | 298 | res_max_size); |
293 | /*HPI_DEBUG_MESSAGE(ERROR, hm); */ | 299 | hr->h.error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL; |
294 | err = -EFAULT; | 300 | hr->h.specific_error = hr->h.size; |
295 | goto out; | 301 | hr->h.size = sizeof(hr->h); |
296 | } | 302 | } |
297 | 303 | ||
298 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); | 304 | uncopied_bytes = copy_to_user(puhr, hr, hr->h.size); |
@@ -320,18 +326,26 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
320 | 326 | ||
321 | memset(&adapter, 0, sizeof(adapter)); | 327 | memset(&adapter, 0, sizeof(adapter)); |
322 | 328 | ||
323 | printk(KERN_DEBUG "probe PCI device (%04x:%04x,%04x:%04x,%04x)\n", | 329 | dev_printk(KERN_DEBUG, &pci_dev->dev, |
324 | pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor, | 330 | "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor, |
331 | pci_dev->device, pci_dev->subsystem_vendor, | ||
325 | pci_dev->subsystem_device, pci_dev->devfn); | 332 | pci_dev->subsystem_device, pci_dev->devfn); |
326 | 333 | ||
334 | if (pci_enable_device(pci_dev) < 0) { | ||
335 | dev_printk(KERN_ERR, &pci_dev->dev, | ||
336 | "pci_enable_device failed, disabling device\n"); | ||
337 | return -EIO; | ||
338 | } | ||
339 | |||
340 | pci_set_master(pci_dev); /* also sets latency timer if < 16 */ | ||
341 | |||
327 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | 342 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, |
328 | HPI_SUBSYS_CREATE_ADAPTER); | 343 | HPI_SUBSYS_CREATE_ADAPTER); |
329 | hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, | 344 | hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER, |
330 | HPI_ERROR_PROCESSING_MESSAGE); | 345 | HPI_ERROR_PROCESSING_MESSAGE); |
331 | 346 | ||
332 | hm.adapter_index = -1; /* an invalid index */ | 347 | hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; |
333 | 348 | ||
334 | /* fill in HPI_PCI information from kernel provided information */ | ||
335 | adapter.pci = pci_dev; | 349 | adapter.pci = pci_dev; |
336 | 350 | ||
337 | nm = HPI_MAX_ADAPTER_MEM_SPACES; | 351 | nm = HPI_MAX_ADAPTER_MEM_SPACES; |
@@ -359,19 +373,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
359 | pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx]; | 373 | pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx]; |
360 | } | 374 | } |
361 | 375 | ||
362 | /* could replace Pci with direct pointer to pci_dev for linux | 376 | pci.pci_dev = pci_dev; |
363 | Instead wrap accessor functions for IDs etc. | ||
364 | Would it work for windows? | ||
365 | */ | ||
366 | pci.bus_number = pci_dev->bus->number; | ||
367 | pci.vendor_id = (u16)pci_dev->vendor; | ||
368 | pci.device_id = (u16)pci_dev->device; | ||
369 | pci.subsys_vendor_id = (u16)(pci_dev->subsystem_vendor & 0xffff); | ||
370 | pci.subsys_device_id = (u16)(pci_dev->subsystem_device & 0xffff); | ||
371 | pci.device_number = pci_dev->devfn; | ||
372 | pci.interrupt = pci_dev->irq; | ||
373 | pci.p_os_data = pci_dev; | ||
374 | |||
375 | hm.u.s.resource.bus_type = HPI_BUS_PCI; | 377 | hm.u.s.resource.bus_type = HPI_BUS_PCI; |
376 | hm.u.s.resource.r.pci = &pci; | 378 | hm.u.s.resource.r.pci = &pci; |
377 | 379 | ||
@@ -392,10 +394,10 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
392 | } | 394 | } |
393 | 395 | ||
394 | adapter.index = hr.u.s.adapter_index; | 396 | adapter.index = hr.u.s.adapter_index; |
395 | adapter.type = hr.u.s.aw_adapter_list[adapter.index]; | 397 | adapter.type = hr.u.s.adapter_type; |
396 | hm.adapter_index = adapter.index; | 398 | hm.adapter_index = adapter.index; |
397 | 399 | ||
398 | err = hpi_adapter_open(NULL, adapter.index); | 400 | err = hpi_adapter_open(adapter.index); |
399 | if (err) | 401 | if (err) |
400 | goto err; | 402 | goto err; |
401 | 403 | ||
@@ -407,8 +409,9 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev, | |||
407 | mutex_init(&adapters[adapter.index].mutex); | 409 | mutex_init(&adapters[adapter.index].mutex); |
408 | pci_set_drvdata(pci_dev, &adapters[adapter.index]); | 410 | pci_set_drvdata(pci_dev, &adapters[adapter.index]); |
409 | 411 | ||
410 | printk(KERN_INFO "probe found adapter ASI%04X HPI index #%d.\n", | 412 | dev_printk(KERN_INFO, &pci_dev->dev, |
411 | adapter.type, adapter.index); | 413 | "probe succeeded for ASI%04X HPI index %d\n", adapter.type, |
414 | adapter.index); | ||
412 | 415 | ||
413 | return 0; | 416 | return 0; |
414 | 417 | ||
@@ -439,7 +442,8 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) | |||
439 | 442 | ||
440 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, | 443 | hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM, |
441 | HPI_SUBSYS_DELETE_ADAPTER); | 444 | HPI_SUBSYS_DELETE_ADAPTER); |
442 | hm.adapter_index = pa->index; | 445 | hm.obj_index = pa->index; |
446 | hm.adapter_index = HPI_ADAPTER_INDEX_INVALID; | ||
443 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); | 447 | hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL); |
444 | 448 | ||
445 | /* unmap PCI memory space, mapped during device init. */ | 449 | /* unmap PCI memory space, mapped during device init. */ |
@@ -450,20 +454,18 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev) | |||
450 | } | 454 | } |
451 | } | 455 | } |
452 | 456 | ||
453 | if (pa->p_buffer) { | 457 | if (pa->p_buffer) |
454 | pa->buffer_size = 0; | ||
455 | vfree(pa->p_buffer); | 458 | vfree(pa->p_buffer); |
456 | } | ||
457 | 459 | ||
458 | pci_set_drvdata(pci_dev, NULL); | 460 | pci_set_drvdata(pci_dev, NULL); |
459 | /* | 461 | if (1) |
460 | printk(KERN_INFO "PCI device (%04x:%04x,%04x:%04x,%04x)," | 462 | dev_printk(KERN_INFO, &pci_dev->dev, |
461 | " HPI index # %d, removed.\n", | 463 | "remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n", |
462 | pci_dev->vendor, pci_dev->device, | 464 | pci_dev->vendor, pci_dev->device, |
463 | pci_dev->subsystem_vendor, | 465 | pci_dev->subsystem_vendor, pci_dev->subsystem_device, |
464 | pci_dev->subsystem_device, pci_dev->devfn, | 466 | pci_dev->devfn, pa->index); |
465 | pa->index); | 467 | |
466 | */ | 468 | memset(pa, 0, sizeof(*pa)); |
467 | } | 469 | } |
468 | 470 | ||
469 | void __init asihpi_init(void) | 471 | void __init asihpi_init(void) |
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h index 370f39b43f85..03273e729f99 100644 --- a/sound/pci/asihpi/hpios.h +++ b/sound/pci/asihpi/hpios.h | |||
@@ -27,9 +27,7 @@ HPI Operating System Specific macros for Linux Kernel driver | |||
27 | #define HPI_OS_LINUX_KERNEL | 27 | #define HPI_OS_LINUX_KERNEL |
28 | 28 | ||
29 | #define HPI_OS_DEFINED | 29 | #define HPI_OS_DEFINED |
30 | #define HPI_KERNEL_MODE | 30 | #define HPI_BUILD_KERNEL_MODE |
31 | |||
32 | #define HPI_REASSIGN_DUPLICATE_ADAPTER_IDX | ||
33 | 31 | ||
34 | #include <linux/io.h> | 32 | #include <linux/io.h> |
35 | #include <asm/system.h> | 33 | #include <asm/system.h> |
@@ -135,20 +133,20 @@ static inline void cond_unlock(struct hpios_spinlock *l) | |||
135 | 133 | ||
136 | #define hpios_msgxlock_init(obj) spin_lock_init(&(obj)->lock) | 134 | #define hpios_msgxlock_init(obj) spin_lock_init(&(obj)->lock) |
137 | #define hpios_msgxlock_lock(obj) cond_lock(obj) | 135 | #define hpios_msgxlock_lock(obj) cond_lock(obj) |
138 | #define hpios_msgxlock_un_lock(obj) cond_unlock(obj) | 136 | #define hpios_msgxlock_unlock(obj) cond_unlock(obj) |
139 | 137 | ||
140 | #define hpios_dsplock_init(obj) spin_lock_init(&(obj)->dsp_lock.lock) | 138 | #define hpios_dsplock_init(obj) spin_lock_init(&(obj)->dsp_lock.lock) |
141 | #define hpios_dsplock_lock(obj) cond_lock(&(obj)->dsp_lock) | 139 | #define hpios_dsplock_lock(obj) cond_lock(&(obj)->dsp_lock) |
142 | #define hpios_dsplock_unlock(obj) cond_unlock(&(obj)->dsp_lock) | 140 | #define hpios_dsplock_unlock(obj) cond_unlock(&(obj)->dsp_lock) |
143 | 141 | ||
144 | #ifdef CONFIG_SND_DEBUG | 142 | #ifdef CONFIG_SND_DEBUG |
145 | #define HPI_DEBUG | 143 | #define HPI_BUILD_DEBUG |
146 | #endif | 144 | #endif |
147 | 145 | ||
148 | #define HPI_ALIST_LOCKING | 146 | #define HPI_ALIST_LOCKING |
149 | #define hpios_alistlock_init(obj) spin_lock_init(&((obj)->list_lock.lock)) | 147 | #define hpios_alistlock_init(obj) spin_lock_init(&((obj)->list_lock.lock)) |
150 | #define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock)) | 148 | #define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock)) |
151 | #define hpios_alistlock_un_lock(obj) spin_unlock(&((obj)->list_lock.lock)) | 149 | #define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock)) |
152 | 150 | ||
153 | struct hpi_adapter { | 151 | struct hpi_adapter { |
154 | /* mutex prevents contention for one card | 152 | /* mutex prevents contention for one card |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 49d572a7b235..3119cd97a217 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
@@ -522,7 +522,7 @@ static int snd_atiixp_aclink_reset(struct atiixp *chip) | |||
522 | atiixp_read(chip, CMD); | 522 | atiixp_read(chip, CMD); |
523 | mdelay(1); | 523 | mdelay(1); |
524 | atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); | 524 | atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); |
525 | if (--timeout) { | 525 | if (!--timeout) { |
526 | snd_printk(KERN_ERR "atiixp: codec reset timeout\n"); | 526 | snd_printk(KERN_ERR "atiixp: codec reset timeout\n"); |
527 | break; | 527 | break; |
528 | } | 528 | } |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 91d7036b6411..2f74c2fdf1ea 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
@@ -498,7 +498,7 @@ static int snd_atiixp_aclink_reset(struct atiixp_modem *chip) | |||
498 | atiixp_read(chip, CMD); | 498 | atiixp_read(chip, CMD); |
499 | msleep(1); | 499 | msleep(1); |
500 | atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); | 500 | atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET); |
501 | if (--timeout) { | 501 | if (!--timeout) { |
502 | snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n"); | 502 | snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n"); |
503 | break; | 503 | break; |
504 | } | 504 | } |
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c index 38602b85874d..278ed8189fca 100644 --- a/sound/pci/au88x0/au88x0_eq.c +++ b/sound/pci/au88x0/au88x0_eq.c | |||
@@ -896,7 +896,8 @@ static int __devinit vortex_eq_init(vortex_t * vortex) | |||
896 | if ((kcontrol = | 896 | if ((kcontrol = |
897 | snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL) | 897 | snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL) |
898 | return -ENOMEM; | 898 | return -ENOMEM; |
899 | strcpy(kcontrol->id.name, EqBandLabels[i]); | 899 | snprintf(kcontrol->id.name, sizeof(kcontrol->id.name), |
900 | "%s Playback Volume", EqBandLabels[i]); | ||
900 | kcontrol->private_value = i; | 901 | kcontrol->private_value = i; |
901 | if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) | 902 | if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0) |
902 | return err; | 903 | return err; |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 573594bf3225..5715c4d05573 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). |
2 | * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). | 2 | * Copyright (C) 2002, 2005 - 2011 by Andreas Mohr <andi AT lisas.de> |
3 | * Copyright (C) 2002, 2005 - 2010 by Andreas Mohr <andi AT lisas.de> | ||
4 | * | 3 | * |
5 | * Framework borrowed from Bart Hartgers's als4000.c. | 4 | * Framework borrowed from Bart Hartgers's als4000.c. |
6 | * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), | 5 | * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), |
@@ -66,6 +65,13 @@ | |||
66 | * addresses illegally. So far unfortunately it looks like the very flexible | 65 | * addresses illegally. So far unfortunately it looks like the very flexible |
67 | * ALSA AC97 support is still not enough to easily compensate for such a | 66 | * ALSA AC97 support is still not enough to easily compensate for such a |
68 | * grave layout violation despite all tweaks and quirks mechanisms it offers. | 67 | * grave layout violation despite all tweaks and quirks mechanisms it offers. |
68 | * Well, not quite: now ac97 layer is much improved (bus-specific ops!), | ||
69 | * thus I was able to implement support - it's actually working quite well. | ||
70 | * An interesting item might be Aztech AMR 2800-W, since it's an AC97 | ||
71 | * modem card which might reveal the Aztech-specific codec ID which | ||
72 | * we might want to pretend, too. Dito PCI168's brother, PCI368, | ||
73 | * where the advertising datasheet says it's AC97-based and has a | ||
74 | * Digital Enhanced Game Port. | ||
69 | * - builtin genuine OPL3 - verified to work fine, 20080506 | 75 | * - builtin genuine OPL3 - verified to work fine, 20080506 |
70 | * - full duplex 16bit playback/record at independent sampling rate | 76 | * - full duplex 16bit playback/record at independent sampling rate |
71 | * - MPU401 (+ legacy address support, claimed by one official spec sheet) | 77 | * - MPU401 (+ legacy address support, claimed by one official spec sheet) |
@@ -189,6 +195,16 @@ | |||
189 | #include <sound/mpu401.h> | 195 | #include <sound/mpu401.h> |
190 | #include <sound/opl3.h> | 196 | #include <sound/opl3.h> |
191 | #include <sound/initval.h> | 197 | #include <sound/initval.h> |
198 | /* | ||
199 | * Config switch, to use ALSA's AC97 layer instead of old custom mixer crap. | ||
200 | * If the AC97 compatibility parts we needed to implement locally turn out | ||
201 | * to work nicely, then remove the old implementation eventually. | ||
202 | */ | ||
203 | #define AZF_USE_AC97_LAYER 1 | ||
204 | |||
205 | #ifdef AZF_USE_AC97_LAYER | ||
206 | #include <sound/ac97_codec.h> | ||
207 | #endif | ||
192 | #include "azt3328.h" | 208 | #include "azt3328.h" |
193 | 209 | ||
194 | MODULE_AUTHOR("Andreas Mohr <andi AT lisas.de>"); | 210 | MODULE_AUTHOR("Andreas Mohr <andi AT lisas.de>"); |
@@ -328,6 +344,10 @@ struct snd_azf3328 { | |||
328 | /* playback, recording and I2S out codecs */ | 344 | /* playback, recording and I2S out codecs */ |
329 | struct snd_azf3328_codec_data codecs[3]; | 345 | struct snd_azf3328_codec_data codecs[3]; |
330 | 346 | ||
347 | #ifdef AZF_USE_AC97_LAYER | ||
348 | struct snd_ac97 *ac97; | ||
349 | #endif | ||
350 | |||
331 | struct snd_card *card; | 351 | struct snd_card *card; |
332 | struct snd_rawmidi *rmidi; | 352 | struct snd_rawmidi *rmidi; |
333 | 353 | ||
@@ -506,7 +526,7 @@ snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg) | |||
506 | #define AZF_MUTE_BIT 0x80 | 526 | #define AZF_MUTE_BIT 0x80 |
507 | 527 | ||
508 | static bool | 528 | static bool |
509 | snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip, | 529 | snd_azf3328_mixer_mute_control(const struct snd_azf3328 *chip, |
510 | unsigned reg, bool do_mute | 530 | unsigned reg, bool do_mute |
511 | ) | 531 | ) |
512 | { | 532 | { |
@@ -521,6 +541,323 @@ snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip, | |||
521 | return (do_mute) ? !updated : updated; | 541 | return (do_mute) ? !updated : updated; |
522 | } | 542 | } |
523 | 543 | ||
544 | static inline bool | ||
545 | snd_azf3328_mixer_mute_control_master(const struct snd_azf3328 *chip, | ||
546 | bool do_mute | ||
547 | ) | ||
548 | { | ||
549 | return snd_azf3328_mixer_mute_control( | ||
550 | chip, | ||
551 | IDX_MIXER_PLAY_MASTER, | ||
552 | do_mute | ||
553 | ); | ||
554 | } | ||
555 | |||
556 | static inline bool | ||
557 | snd_azf3328_mixer_mute_control_pcm(const struct snd_azf3328 *chip, | ||
558 | bool do_mute | ||
559 | ) | ||
560 | { | ||
561 | return snd_azf3328_mixer_mute_control( | ||
562 | chip, | ||
563 | IDX_MIXER_WAVEOUT, | ||
564 | do_mute | ||
565 | ); | ||
566 | } | ||
567 | |||
568 | static inline void | ||
569 | snd_azf3328_mixer_reset(const struct snd_azf3328 *chip) | ||
570 | { | ||
571 | /* reset (close) mixer: | ||
572 | * first mute master volume, then reset | ||
573 | */ | ||
574 | snd_azf3328_mixer_mute_control_master(chip, 1); | ||
575 | snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); | ||
576 | } | ||
577 | |||
578 | #ifdef AZF_USE_AC97_LAYER | ||
579 | |||
580 | static inline void | ||
581 | snd_azf3328_mixer_ac97_map_unsupported(unsigned short reg, const char *mode) | ||
582 | { | ||
583 | /* need to add some more or less clever emulation? */ | ||
584 | printk(KERN_WARNING | ||
585 | "azt3328: missing %s emulation for AC97 register 0x%02x!\n", | ||
586 | mode, reg); | ||
587 | } | ||
588 | |||
589 | /* | ||
590 | * Need to have _special_ AC97 mixer hardware register index mapper, | ||
591 | * to compensate for the issue of a rather AC97-incompatible hardware layout. | ||
592 | */ | ||
593 | #define AZF_REG_MASK 0x3f | ||
594 | #define AZF_AC97_REG_UNSUPPORTED 0x8000 | ||
595 | #define AZF_AC97_REG_REAL_IO_READ 0x4000 | ||
596 | #define AZF_AC97_REG_REAL_IO_WRITE 0x2000 | ||
597 | #define AZF_AC97_REG_REAL_IO_RW \ | ||
598 | (AZF_AC97_REG_REAL_IO_READ | AZF_AC97_REG_REAL_IO_WRITE) | ||
599 | #define AZF_AC97_REG_EMU_IO_READ 0x0400 | ||
600 | #define AZF_AC97_REG_EMU_IO_WRITE 0x0200 | ||
601 | #define AZF_AC97_REG_EMU_IO_RW \ | ||
602 | (AZF_AC97_REG_EMU_IO_READ | AZF_AC97_REG_EMU_IO_WRITE) | ||
603 | static unsigned short | ||
604 | snd_azf3328_mixer_ac97_map_reg_idx(unsigned short reg) | ||
605 | { | ||
606 | static const struct { | ||
607 | unsigned short azf_reg; | ||
608 | } azf_reg_mapper[] = { | ||
609 | /* Especially when taking into consideration | ||
610 | * mono/stereo-based sequence of azf vs. AC97 control series, | ||
611 | * it's quite obvious that azf simply got rid | ||
612 | * of the AC97_HEADPHONE control at its intended offset, | ||
613 | * thus shifted _all_ controls by one, | ||
614 | * and _then_ simply added it as an FMSYNTH control at the end, | ||
615 | * to make up for the offset. | ||
616 | * This means we'll have to translate indices here as | ||
617 | * needed and then do some tiny AC97 patch action | ||
618 | * (snd_ac97_rename_vol_ctl() etc.) - that's it. | ||
619 | */ | ||
620 | { /* AC97_RESET */ IDX_MIXER_RESET | ||
621 | | AZF_AC97_REG_REAL_IO_WRITE | ||
622 | | AZF_AC97_REG_EMU_IO_READ }, | ||
623 | { /* AC97_MASTER */ IDX_MIXER_PLAY_MASTER }, | ||
624 | /* note large shift: AC97_HEADPHONE to IDX_MIXER_FMSYNTH! */ | ||
625 | { /* AC97_HEADPHONE */ IDX_MIXER_FMSYNTH }, | ||
626 | { /* AC97_MASTER_MONO */ IDX_MIXER_MODEMOUT }, | ||
627 | { /* AC97_MASTER_TONE */ IDX_MIXER_BASSTREBLE }, | ||
628 | { /* AC97_PC_BEEP */ IDX_MIXER_PCBEEP }, | ||
629 | { /* AC97_PHONE */ IDX_MIXER_MODEMIN }, | ||
630 | { /* AC97_MIC */ IDX_MIXER_MIC }, | ||
631 | { /* AC97_LINE */ IDX_MIXER_LINEIN }, | ||
632 | { /* AC97_CD */ IDX_MIXER_CDAUDIO }, | ||
633 | { /* AC97_VIDEO */ IDX_MIXER_VIDEO }, | ||
634 | { /* AC97_AUX */ IDX_MIXER_AUX }, | ||
635 | { /* AC97_PCM */ IDX_MIXER_WAVEOUT }, | ||
636 | { /* AC97_REC_SEL */ IDX_MIXER_REC_SELECT }, | ||
637 | { /* AC97_REC_GAIN */ IDX_MIXER_REC_VOLUME }, | ||
638 | { /* AC97_REC_GAIN_MIC */ AZF_AC97_REG_EMU_IO_RW }, | ||
639 | { /* AC97_GENERAL_PURPOSE */ IDX_MIXER_ADVCTL2 }, | ||
640 | { /* AC97_3D_CONTROL */ IDX_MIXER_ADVCTL1 }, | ||
641 | }; | ||
642 | |||
643 | unsigned short reg_azf = AZF_AC97_REG_UNSUPPORTED; | ||
644 | |||
645 | /* azf3328 supports the low-numbered and low-spec:ed range | ||
646 | of AC97 regs only */ | ||
647 | if (reg <= AC97_3D_CONTROL) { | ||
648 | unsigned short reg_idx = reg / 2; | ||
649 | reg_azf = azf_reg_mapper[reg_idx].azf_reg; | ||
650 | /* a translation-only entry means it's real read/write: */ | ||
651 | if (!(reg_azf & ~AZF_REG_MASK)) | ||
652 | reg_azf |= AZF_AC97_REG_REAL_IO_RW; | ||
653 | } else { | ||
654 | switch (reg) { | ||
655 | case AC97_POWERDOWN: | ||
656 | reg_azf = AZF_AC97_REG_EMU_IO_RW; | ||
657 | break; | ||
658 | case AC97_EXTENDED_ID: | ||
659 | reg_azf = AZF_AC97_REG_EMU_IO_READ; | ||
660 | break; | ||
661 | case AC97_EXTENDED_STATUS: | ||
662 | /* I don't know what the h*ll AC97 layer | ||
663 | * would consult this _extended_ register for | ||
664 | * given a base-AC97-advertised card, | ||
665 | * but let's just emulate it anyway :-P | ||
666 | */ | ||
667 | reg_azf = AZF_AC97_REG_EMU_IO_RW; | ||
668 | break; | ||
669 | case AC97_VENDOR_ID1: | ||
670 | case AC97_VENDOR_ID2: | ||
671 | reg_azf = AZF_AC97_REG_EMU_IO_READ; | ||
672 | break; | ||
673 | } | ||
674 | } | ||
675 | return reg_azf; | ||
676 | } | ||
677 | |||
678 | static const unsigned short | ||
679 | azf_emulated_ac97_caps = | ||
680 | AC97_BC_DEDICATED_MIC | | ||
681 | AC97_BC_BASS_TREBLE | | ||
682 | /* Headphone is an FM Synth control here */ | ||
683 | AC97_BC_HEADPHONE | | ||
684 | /* no AC97_BC_LOUDNESS! */ | ||
685 | /* mask 0x7c00 is | ||
686 | vendor-specific 3D enhancement | ||
687 | vendor indicator. | ||
688 | Since there actually _is_ an | ||
689 | entry for Aztech Labs | ||
690 | (13), make damn sure | ||
691 | to indicate it. */ | ||
692 | (13 << 10); | ||
693 | |||
694 | static const unsigned short | ||
695 | azf_emulated_ac97_powerdown = | ||
696 | /* pretend everything to be active */ | ||
697 | AC97_PD_ADC_STATUS | | ||
698 | AC97_PD_DAC_STATUS | | ||
699 | AC97_PD_MIXER_STATUS | | ||
700 | AC97_PD_VREF_STATUS; | ||
701 | |||
702 | /* | ||
703 | * Emulated, _inofficial_ vendor ID | ||
704 | * (there might be some devices such as the MR 2800-W | ||
705 | * which could reveal the real Aztech AC97 ID). | ||
706 | * We choose to use "AZT" prefix, and then use 1 to indicate PCI168 | ||
707 | * (better don't use 0x68 since there's a PCI368 as well). | ||
708 | */ | ||
709 | static const unsigned int | ||
710 | azf_emulated_ac97_vendor_id = 0x415a5401; | ||
711 | |||
712 | static unsigned short | ||
713 | snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97) | ||
714 | { | ||
715 | const struct snd_azf3328 *chip = ac97->private_data; | ||
716 | unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97); | ||
717 | unsigned short reg_val = 0; | ||
718 | bool unsupported = 0; | ||
719 | |||
720 | snd_azf3328_dbgmixer( | ||
721 | "snd_azf3328_mixer_ac97_read reg_ac97 %u\n", | ||
722 | reg_ac97 | ||
723 | ); | ||
724 | if (reg_azf & AZF_AC97_REG_UNSUPPORTED) | ||
725 | unsupported = 1; | ||
726 | else { | ||
727 | if (reg_azf & AZF_AC97_REG_REAL_IO_READ) | ||
728 | reg_val = snd_azf3328_mixer_inw(chip, | ||
729 | reg_azf & AZF_REG_MASK); | ||
730 | else { | ||
731 | /* | ||
732 | * Proceed with dummy I/O read, | ||
733 | * to ensure compatible timing where this may matter. | ||
734 | * (ALSA AC97 layer usually doesn't call I/O functions | ||
735 | * due to intelligent I/O caching anyway) | ||
736 | * Choose a mixer register that's thoroughly unrelated | ||
737 | * to common audio (try to minimize distortion). | ||
738 | */ | ||
739 | snd_azf3328_mixer_inw(chip, IDX_MIXER_SOMETHING30H); | ||
740 | } | ||
741 | |||
742 | if (reg_azf & AZF_AC97_REG_EMU_IO_READ) { | ||
743 | switch (reg_ac97) { | ||
744 | case AC97_RESET: | ||
745 | reg_val |= azf_emulated_ac97_caps; | ||
746 | break; | ||
747 | case AC97_POWERDOWN: | ||
748 | reg_val |= azf_emulated_ac97_powerdown; | ||
749 | break; | ||
750 | case AC97_EXTENDED_ID: | ||
751 | case AC97_EXTENDED_STATUS: | ||
752 | /* AFAICS we simply can't support anything: */ | ||
753 | reg_val |= 0; | ||
754 | break; | ||
755 | case AC97_VENDOR_ID1: | ||
756 | reg_val = azf_emulated_ac97_vendor_id >> 16; | ||
757 | break; | ||
758 | case AC97_VENDOR_ID2: | ||
759 | reg_val = azf_emulated_ac97_vendor_id & 0xffff; | ||
760 | break; | ||
761 | default: | ||
762 | unsupported = 1; | ||
763 | break; | ||
764 | } | ||
765 | } | ||
766 | } | ||
767 | if (unsupported) | ||
768 | snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "read"); | ||
769 | |||
770 | return reg_val; | ||
771 | } | ||
772 | |||
773 | static void | ||
774 | snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97, | ||
775 | unsigned short reg_ac97, unsigned short val) | ||
776 | { | ||
777 | const struct snd_azf3328 *chip = ac97->private_data; | ||
778 | unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97); | ||
779 | bool unsupported = 0; | ||
780 | |||
781 | snd_azf3328_dbgmixer( | ||
782 | "snd_azf3328_mixer_ac97_write reg_ac97 %u val %u\n", | ||
783 | reg_ac97, val | ||
784 | ); | ||
785 | if (reg_azf & AZF_AC97_REG_UNSUPPORTED) | ||
786 | unsupported = 1; | ||
787 | else { | ||
788 | if (reg_azf & AZF_AC97_REG_REAL_IO_WRITE) | ||
789 | snd_azf3328_mixer_outw( | ||
790 | chip, | ||
791 | reg_azf & AZF_REG_MASK, | ||
792 | val | ||
793 | ); | ||
794 | else | ||
795 | if (reg_azf & AZF_AC97_REG_EMU_IO_WRITE) { | ||
796 | switch (reg_ac97) { | ||
797 | case AC97_REC_GAIN_MIC: | ||
798 | case AC97_POWERDOWN: | ||
799 | case AC97_EXTENDED_STATUS: | ||
800 | /* | ||
801 | * Silently swallow these writes. | ||
802 | * Since for most registers our card doesn't | ||
803 | * actually support a comparable feature, | ||
804 | * this is exactly what we should do here. | ||
805 | * The AC97 layer's I/O caching probably | ||
806 | * automatically takes care of all the rest... | ||
807 | * (remembers written values etc.) | ||
808 | */ | ||
809 | break; | ||
810 | default: | ||
811 | unsupported = 1; | ||
812 | break; | ||
813 | } | ||
814 | } | ||
815 | } | ||
816 | if (unsupported) | ||
817 | snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write"); | ||
818 | } | ||
819 | |||
820 | static int __devinit | ||
821 | snd_azf3328_mixer_new(struct snd_azf3328 *chip) | ||
822 | { | ||
823 | struct snd_ac97_bus *bus; | ||
824 | struct snd_ac97_template ac97; | ||
825 | static struct snd_ac97_bus_ops ops = { | ||
826 | .write = snd_azf3328_mixer_ac97_write, | ||
827 | .read = snd_azf3328_mixer_ac97_read, | ||
828 | }; | ||
829 | int rc; | ||
830 | |||
831 | memset(&ac97, 0, sizeof(ac97)); | ||
832 | ac97.scaps = AC97_SCAP_SKIP_MODEM | ||
833 | | AC97_SCAP_AUDIO /* we support audio! */ | ||
834 | | AC97_SCAP_NO_SPDIF; | ||
835 | ac97.private_data = chip; | ||
836 | ac97.pci = chip->pci; | ||
837 | |||
838 | /* | ||
839 | * ALSA's AC97 layer has terrible init crackling issues, | ||
840 | * unfortunately, and since it makes use of AC97_RESET, | ||
841 | * there's no use trying to mute Master Playback proactively. | ||
842 | */ | ||
843 | |||
844 | rc = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus); | ||
845 | if (!rc) | ||
846 | rc = snd_ac97_mixer(bus, &ac97, &chip->ac97); | ||
847 | /* | ||
848 | * Make sure to complain loudly in case of AC97 init failure, | ||
849 | * since failure may happen quite often, | ||
850 | * due to this card being a very quirky AC97 "lookalike". | ||
851 | */ | ||
852 | if (rc) | ||
853 | printk(KERN_ERR "azt3328: AC97 init failed, err %d!\n", rc); | ||
854 | |||
855 | /* If we return an error here, then snd_card_free() should | ||
856 | * free up any ac97 codecs that got created, as well as the bus. | ||
857 | */ | ||
858 | return rc; | ||
859 | } | ||
860 | #else /* AZF_USE_AC97_LAYER */ | ||
524 | static void | 861 | static void |
525 | snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, | 862 | snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip, |
526 | unsigned reg, | 863 | unsigned reg, |
@@ -945,6 +1282,7 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip) | |||
945 | snd_azf3328_dbgcallleave(); | 1282 | snd_azf3328_dbgcallleave(); |
946 | return 0; | 1283 | return 0; |
947 | } | 1284 | } |
1285 | #endif /* AZF_USE_AC97_LAYER */ | ||
948 | 1286 | ||
949 | static int | 1287 | static int |
950 | snd_azf3328_hw_params(struct snd_pcm_substream *substream, | 1288 | snd_azf3328_hw_params(struct snd_pcm_substream *substream, |
@@ -1233,8 +1571,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1233 | if (is_main_mixer_playback_codec) { | 1571 | if (is_main_mixer_playback_codec) { |
1234 | /* mute WaveOut (avoid clicking during setup) */ | 1572 | /* mute WaveOut (avoid clicking during setup) */ |
1235 | previously_muted = | 1573 | previously_muted = |
1236 | snd_azf3328_mixer_set_mute( | 1574 | snd_azf3328_mixer_mute_control_pcm( |
1237 | chip, IDX_MIXER_WAVEOUT, 1 | 1575 | chip, 1 |
1238 | ); | 1576 | ); |
1239 | } | 1577 | } |
1240 | 1578 | ||
@@ -1290,8 +1628,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1290 | if (is_main_mixer_playback_codec) { | 1628 | if (is_main_mixer_playback_codec) { |
1291 | /* now unmute WaveOut */ | 1629 | /* now unmute WaveOut */ |
1292 | if (!previously_muted) | 1630 | if (!previously_muted) |
1293 | snd_azf3328_mixer_set_mute( | 1631 | snd_azf3328_mixer_mute_control_pcm( |
1294 | chip, IDX_MIXER_WAVEOUT, 0 | 1632 | chip, 0 |
1295 | ); | 1633 | ); |
1296 | } | 1634 | } |
1297 | 1635 | ||
@@ -1315,8 +1653,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1315 | if (is_main_mixer_playback_codec) { | 1653 | if (is_main_mixer_playback_codec) { |
1316 | /* mute WaveOut (avoid clicking during setup) */ | 1654 | /* mute WaveOut (avoid clicking during setup) */ |
1317 | previously_muted = | 1655 | previously_muted = |
1318 | snd_azf3328_mixer_set_mute( | 1656 | snd_azf3328_mixer_mute_control_pcm( |
1319 | chip, IDX_MIXER_WAVEOUT, 1 | 1657 | chip, 1 |
1320 | ); | 1658 | ); |
1321 | } | 1659 | } |
1322 | 1660 | ||
@@ -1341,8 +1679,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
1341 | if (is_main_mixer_playback_codec) { | 1679 | if (is_main_mixer_playback_codec) { |
1342 | /* now unmute WaveOut */ | 1680 | /* now unmute WaveOut */ |
1343 | if (!previously_muted) | 1681 | if (!previously_muted) |
1344 | snd_azf3328_mixer_set_mute( | 1682 | snd_azf3328_mixer_mute_control_pcm( |
1345 | chip, IDX_MIXER_WAVEOUT, 0 | 1683 | chip, 0 |
1346 | ); | 1684 | ); |
1347 | } | 1685 | } |
1348 | 1686 | ||
@@ -2050,11 +2388,7 @@ snd_azf3328_free(struct snd_azf3328 *chip) | |||
2050 | if (chip->irq < 0) | 2388 | if (chip->irq < 0) |
2051 | goto __end_hw; | 2389 | goto __end_hw; |
2052 | 2390 | ||
2053 | /* reset (close) mixer: | 2391 | snd_azf3328_mixer_reset(chip); |
2054 | * first mute master volume, then reset | ||
2055 | */ | ||
2056 | snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); | ||
2057 | snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000); | ||
2058 | 2392 | ||
2059 | snd_azf3328_timer_stop(chip->timer); | 2393 | snd_azf3328_timer_stop(chip->timer); |
2060 | snd_azf3328_gameport_free(chip); | 2394 | snd_azf3328_gameport_free(chip); |
@@ -2407,6 +2741,55 @@ snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) | |||
2407 | } | 2741 | } |
2408 | } | 2742 | } |
2409 | 2743 | ||
2744 | static inline void | ||
2745 | snd_azf3328_resume_regs(const u32 *saved_regs, | ||
2746 | unsigned long io_addr, | ||
2747 | unsigned count | ||
2748 | ) | ||
2749 | { | ||
2750 | unsigned reg; | ||
2751 | |||
2752 | for (reg = 0; reg < count; ++reg) { | ||
2753 | outl(*saved_regs, io_addr); | ||
2754 | snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n", | ||
2755 | io_addr, *saved_regs, inl(io_addr)); | ||
2756 | ++saved_regs; | ||
2757 | io_addr += sizeof(*saved_regs); | ||
2758 | } | ||
2759 | } | ||
2760 | |||
2761 | static inline void | ||
2762 | snd_azf3328_suspend_ac97(struct snd_azf3328 *chip) | ||
2763 | { | ||
2764 | #ifdef AZF_USE_AC97_LAYER | ||
2765 | snd_ac97_suspend(chip->ac97); | ||
2766 | #else | ||
2767 | snd_azf3328_suspend_regs(chip->mixer_io, | ||
2768 | ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer); | ||
2769 | |||
2770 | /* make sure to disable master volume etc. to prevent looping sound */ | ||
2771 | snd_azf3328_mixer_mute_control_master(chip, 1); | ||
2772 | snd_azf3328_mixer_mute_control_pcm(chip, 1); | ||
2773 | #endif /* AZF_USE_AC97_LAYER */ | ||
2774 | } | ||
2775 | |||
2776 | static inline void | ||
2777 | snd_azf3328_resume_ac97(const struct snd_azf3328 *chip) | ||
2778 | { | ||
2779 | #ifdef AZF_USE_AC97_LAYER | ||
2780 | snd_ac97_resume(chip->ac97); | ||
2781 | #else | ||
2782 | snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io, | ||
2783 | ARRAY_SIZE(chip->saved_regs_mixer)); | ||
2784 | |||
2785 | /* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02) | ||
2786 | and IDX_MIXER_RESET (offset 0x00) get touched at the same time, | ||
2787 | resulting in a mixer reset condition persisting until _after_ | ||
2788 | master vol was restored. Thus master vol needs an extra restore. */ | ||
2789 | outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2); | ||
2790 | #endif /* AZF_USE_AC97_LAYER */ | ||
2791 | } | ||
2792 | |||
2410 | static int | 2793 | static int |
2411 | snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | 2794 | snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) |
2412 | { | 2795 | { |
@@ -2420,12 +2803,7 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | |||
2420 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); | 2803 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); |
2421 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); | 2804 | snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); |
2422 | 2805 | ||
2423 | snd_azf3328_suspend_regs(chip->mixer_io, | 2806 | snd_azf3328_suspend_ac97(chip); |
2424 | ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer); | ||
2425 | |||
2426 | /* make sure to disable master volume etc. to prevent looping sound */ | ||
2427 | snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); | ||
2428 | snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); | ||
2429 | 2807 | ||
2430 | snd_azf3328_suspend_regs(chip->ctrl_io, | 2808 | snd_azf3328_suspend_regs(chip->ctrl_io, |
2431 | ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl); | 2809 | ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl); |
@@ -2447,23 +2825,6 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) | |||
2447 | return 0; | 2825 | return 0; |
2448 | } | 2826 | } |
2449 | 2827 | ||
2450 | static inline void | ||
2451 | snd_azf3328_resume_regs(const u32 *saved_regs, | ||
2452 | unsigned long io_addr, | ||
2453 | unsigned count | ||
2454 | ) | ||
2455 | { | ||
2456 | unsigned reg; | ||
2457 | |||
2458 | for (reg = 0; reg < count; ++reg) { | ||
2459 | outl(*saved_regs, io_addr); | ||
2460 | snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n", | ||
2461 | io_addr, *saved_regs, inl(io_addr)); | ||
2462 | ++saved_regs; | ||
2463 | io_addr += sizeof(*saved_regs); | ||
2464 | } | ||
2465 | } | ||
2466 | |||
2467 | static int | 2828 | static int |
2468 | snd_azf3328_resume(struct pci_dev *pci) | 2829 | snd_azf3328_resume(struct pci_dev *pci) |
2469 | { | 2830 | { |
@@ -2487,14 +2848,7 @@ snd_azf3328_resume(struct pci_dev *pci) | |||
2487 | snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io, | 2848 | snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io, |
2488 | ARRAY_SIZE(chip->saved_regs_opl3)); | 2849 | ARRAY_SIZE(chip->saved_regs_opl3)); |
2489 | 2850 | ||
2490 | snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io, | 2851 | snd_azf3328_resume_ac97(chip); |
2491 | ARRAY_SIZE(chip->saved_regs_mixer)); | ||
2492 | |||
2493 | /* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02) | ||
2494 | and IDX_MIXER_RESET (offset 0x00) get touched at the same time, | ||
2495 | resulting in a mixer reset condition persisting until _after_ | ||
2496 | master vol was restored. Thus master vol needs an extra restore. */ | ||
2497 | outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2); | ||
2498 | 2852 | ||
2499 | snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io, | 2853 | snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io, |
2500 | ARRAY_SIZE(chip->saved_regs_ctrl)); | 2854 | ARRAY_SIZE(chip->saved_regs_ctrl)); |
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 1bff80cde0a2..b9321544c31c 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
@@ -869,7 +869,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm) | |||
869 | mutex_lock(&atc->atc_mutex); | 869 | mutex_lock(&atc->atc_mutex); |
870 | dao->ops->get_spos(dao, &status); | 870 | dao->ops->get_spos(dao, &status); |
871 | if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { | 871 | if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) { |
872 | status &= ((~IEC958_AES3_CON_FS) << 24); | 872 | status &= ~(IEC958_AES3_CON_FS << 24); |
873 | status |= (iec958_con_fs << 24); | 873 | status |= (iec958_con_fs << 24); |
874 | dao->ops->set_spos(dao, status); | 874 | dao->ops->set_spos(dao, status); |
875 | dao->ops->commit_write(dao); | 875 | dao->ops->commit_write(dao); |
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c index af56eb949bde..47d9ea97de02 100644 --- a/sound/pci/ctxfi/ctdaio.c +++ b/sound/pci/ctxfi/ctdaio.c | |||
@@ -176,6 +176,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input) | |||
176 | if (!entry) | 176 | if (!entry) |
177 | return -ENOMEM; | 177 | return -ENOMEM; |
178 | 178 | ||
179 | dao->ops->clear_left_input(dao); | ||
179 | /* Program master and conjugate resources */ | 180 | /* Program master and conjugate resources */ |
180 | input->ops->master(input); | 181 | input->ops->master(input); |
181 | daio->rscl.ops->master(&daio->rscl); | 182 | daio->rscl.ops->master(&daio->rscl); |
@@ -204,6 +205,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input) | |||
204 | if (!entry) | 205 | if (!entry) |
205 | return -ENOMEM; | 206 | return -ENOMEM; |
206 | 207 | ||
208 | dao->ops->clear_right_input(dao); | ||
207 | /* Program master and conjugate resources */ | 209 | /* Program master and conjugate resources */ |
208 | input->ops->master(input); | 210 | input->ops->master(input); |
209 | daio->rscr.ops->master(&daio->rscr); | 211 | daio->rscr.ops->master(&daio->rscr); |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index b6b11bfe7574..5364164674e4 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
@@ -1307,10 +1307,10 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr) | |||
1307 | set_field(&pllctl, PLLCTL_B, 0); | 1307 | set_field(&pllctl, PLLCTL_B, 0); |
1308 | if (48000 == rsr) { | 1308 | if (48000 == rsr) { |
1309 | set_field(&pllctl, PLLCTL_FD, 16 - 2); | 1309 | set_field(&pllctl, PLLCTL_FD, 16 - 2); |
1310 | set_field(&pllctl, PLLCTL_RD, 1 - 1); | 1310 | set_field(&pllctl, PLLCTL_RD, 1 - 1); /* 3000*16/1 = 48000 */ |
1311 | } else { /* 44100 */ | 1311 | } else { /* 44100 */ |
1312 | set_field(&pllctl, PLLCTL_FD, 147 - 2); | 1312 | set_field(&pllctl, PLLCTL_FD, 147 - 2); |
1313 | set_field(&pllctl, PLLCTL_RD, 10 - 1); | 1313 | set_field(&pllctl, PLLCTL_RD, 10 - 1); /* 3000*147/10 = 44100 */ |
1314 | } | 1314 | } |
1315 | hw_write_20kx(hw, PLL_CTL, pllctl); | 1315 | hw_write_20kx(hw, PLL_CTL, pllctl); |
1316 | mdelay(40); | 1316 | mdelay(40); |
@@ -1740,6 +1740,10 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type) | |||
1740 | return data; | 1740 | return data; |
1741 | } | 1741 | } |
1742 | 1742 | ||
1743 | #define MIC_BOOST_0DB 0xCF | ||
1744 | #define MIC_BOOST_STEPS_PER_DB 2 | ||
1745 | #define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB) | ||
1746 | |||
1743 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | 1747 | static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) |
1744 | { | 1748 | { |
1745 | u32 data; | 1749 | u32 data; |
@@ -1751,10 +1755,12 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type) | |||
1751 | hw_write_20kx(hw, GPIO_DATA, data); | 1755 | hw_write_20kx(hw, GPIO_DATA, data); |
1752 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | 1756 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), |
1753 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | 1757 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ |
1754 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7), | 1758 | hw20k2_i2c_write(hw, |
1755 | MAKE_WM8775_DATA(0xE7)); /* +12dB boost */ | 1759 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), |
1756 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7), | 1760 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ |
1757 | MAKE_WM8775_DATA(0xE7)); /* +12dB boost */ | 1761 | hw20k2_i2c_write(hw, |
1762 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1763 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1758 | break; | 1764 | break; |
1759 | case ADC_LINEIN: | 1765 | case ADC_LINEIN: |
1760 | data &= ~(0x1 << 14); | 1766 | data &= ~(0x1 << 14); |
@@ -1827,10 +1833,12 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info) | |||
1827 | 1833 | ||
1828 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), | 1834 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101), |
1829 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ | 1835 | MAKE_WM8775_DATA(0x101)); /* Mic-in */ |
1830 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7), | 1836 | hw20k2_i2c_write(hw, |
1831 | MAKE_WM8775_DATA(0xE7)); /* +12dB boost */ | 1837 | MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB), |
1832 | hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7), | 1838 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ |
1833 | MAKE_WM8775_DATA(0xE7)); /* +12dB boost */ | 1839 | hw20k2_i2c_write(hw, |
1840 | MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB), | ||
1841 | MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */ | ||
1834 | } else if (mux == 2) { | 1842 | } else if (mux == 2) { |
1835 | /* Configures GPIO data to select Line-in */ | 1843 | /* Configures GPIO data to select Line-in */ |
1836 | data &= ~(0x1 << 14); | 1844 | data &= ~(0x1 << 14); |
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 15c1e7271ea8..c3519ff42fbb 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c | |||
@@ -566,19 +566,6 @@ static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol, | |||
566 | return 0; | 566 | return 0; |
567 | } | 567 | } |
568 | 568 | ||
569 | static int ct_spdif_default_get(struct snd_kcontrol *kcontrol, | ||
570 | struct snd_ctl_elem_value *ucontrol) | ||
571 | { | ||
572 | unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF; | ||
573 | |||
574 | ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; | ||
575 | ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; | ||
576 | ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; | ||
577 | ucontrol->value.iec958.status[3] = (status >> 24) & 0xff; | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int ct_spdif_get(struct snd_kcontrol *kcontrol, | 569 | static int ct_spdif_get(struct snd_kcontrol *kcontrol, |
583 | struct snd_ctl_elem_value *ucontrol) | 570 | struct snd_ctl_elem_value *ucontrol) |
584 | { | 571 | { |
@@ -586,6 +573,10 @@ static int ct_spdif_get(struct snd_kcontrol *kcontrol, | |||
586 | unsigned int status; | 573 | unsigned int status; |
587 | 574 | ||
588 | atc->spdif_out_get_status(atc, &status); | 575 | atc->spdif_out_get_status(atc, &status); |
576 | |||
577 | if (status == 0) | ||
578 | status = SNDRV_PCM_DEFAULT_CON_SPDIF; | ||
579 | |||
589 | ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; | 580 | ucontrol->value.iec958.status[0] = (status >> 0) & 0xff; |
590 | ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; | 581 | ucontrol->value.iec958.status[1] = (status >> 8) & 0xff; |
591 | ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; | 582 | ucontrol->value.iec958.status[2] = (status >> 16) & 0xff; |
@@ -629,7 +620,7 @@ static struct snd_kcontrol_new iec958_default_ctl = { | |||
629 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), | 620 | .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), |
630 | .count = 1, | 621 | .count = 1, |
631 | .info = ct_spdif_info, | 622 | .info = ct_spdif_info, |
632 | .get = ct_spdif_default_get, | 623 | .get = ct_spdif_get, |
633 | .put = ct_spdif_put, | 624 | .put = ct_spdif_put, |
634 | .private_value = MIXER_IEC958_DEFAULT | 625 | .private_value = MIXER_IEC958_DEFAULT |
635 | }; | 626 | }; |
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c index 65da6e466f80..b78f3fc3c33c 100644 --- a/sound/pci/ctxfi/ctvmem.c +++ b/sound/pci/ctxfi/ctvmem.c | |||
@@ -52,8 +52,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size) | |||
52 | 52 | ||
53 | if (entry->size == size) { | 53 | if (entry->size == size) { |
54 | /* Move the vm node from unused list to used list directly */ | 54 | /* Move the vm node from unused list to used list directly */ |
55 | list_del(&entry->list); | 55 | list_move(&entry->list, &vm->used); |
56 | list_add(&entry->list, &vm->used); | ||
57 | vm->size -= size; | 56 | vm->size -= size; |
58 | block = entry; | 57 | block = entry; |
59 | goto out; | 58 | goto out; |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 66c7fb3ced3e..5e619a84da06 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -926,7 +926,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) | |||
926 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); | 926 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); |
927 | /* Unknown. */ | 927 | /* Unknown. */ |
928 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); | 928 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); |
929 | /* IRQ Enable: Alll on */ | 929 | /* IRQ Enable: All on */ |
930 | /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */ | 930 | /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */ |
931 | /* IRQ Enable: All off */ | 931 | /* IRQ Enable: All off */ |
932 | snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); | 932 | snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index ae5c5d5e4b7c..2c79e96d0324 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sound/asoundef.h> | 29 | #include <sound/asoundef.h> |
30 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
31 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
32 | #include <sound/jack.h> | ||
32 | #include "hda_local.h" | 33 | #include "hda_local.h" |
33 | #include "hda_beep.h" | 34 | #include "hda_beep.h" |
34 | #include <sound/hda_hwdep.h> | 35 | #include <sound/hda_hwdep.h> |
@@ -4959,5 +4960,109 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen) | |||
4959 | } | 4960 | } |
4960 | EXPORT_SYMBOL_HDA(snd_print_pcm_bits); | 4961 | EXPORT_SYMBOL_HDA(snd_print_pcm_bits); |
4961 | 4962 | ||
4963 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
4964 | /* | ||
4965 | * Input-jack notification support | ||
4966 | */ | ||
4967 | struct hda_jack_item { | ||
4968 | hda_nid_t nid; | ||
4969 | int type; | ||
4970 | struct snd_jack *jack; | ||
4971 | }; | ||
4972 | |||
4973 | static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid, | ||
4974 | int type) | ||
4975 | { | ||
4976 | switch (type) { | ||
4977 | case SND_JACK_HEADPHONE: | ||
4978 | return "Headphone"; | ||
4979 | case SND_JACK_MICROPHONE: | ||
4980 | return "Mic"; | ||
4981 | case SND_JACK_LINEOUT: | ||
4982 | return "Line-out"; | ||
4983 | case SND_JACK_HEADSET: | ||
4984 | return "Headset"; | ||
4985 | default: | ||
4986 | return "Misc"; | ||
4987 | } | ||
4988 | } | ||
4989 | |||
4990 | static void hda_free_jack_priv(struct snd_jack *jack) | ||
4991 | { | ||
4992 | struct hda_jack_item *jacks = jack->private_data; | ||
4993 | jacks->nid = 0; | ||
4994 | jacks->jack = NULL; | ||
4995 | } | ||
4996 | |||
4997 | int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, | ||
4998 | const char *name) | ||
4999 | { | ||
5000 | struct hda_jack_item *jack; | ||
5001 | int err; | ||
5002 | |||
5003 | snd_array_init(&codec->jacks, sizeof(*jack), 32); | ||
5004 | jack = snd_array_new(&codec->jacks); | ||
5005 | if (!jack) | ||
5006 | return -ENOMEM; | ||
5007 | |||
5008 | jack->nid = nid; | ||
5009 | jack->type = type; | ||
5010 | if (!name) | ||
5011 | name = get_jack_default_name(codec, nid, type); | ||
5012 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
5013 | if (err < 0) { | ||
5014 | jack->nid = 0; | ||
5015 | return err; | ||
5016 | } | ||
5017 | jack->jack->private_data = jack; | ||
5018 | jack->jack->private_free = hda_free_jack_priv; | ||
5019 | return 0; | ||
5020 | } | ||
5021 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_add); | ||
5022 | |||
5023 | void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid) | ||
5024 | { | ||
5025 | struct hda_jack_item *jacks = codec->jacks.list; | ||
5026 | int i; | ||
5027 | |||
5028 | if (!jacks) | ||
5029 | return; | ||
5030 | |||
5031 | for (i = 0; i < codec->jacks.used; i++, jacks++) { | ||
5032 | unsigned int pin_ctl; | ||
5033 | unsigned int present; | ||
5034 | int type; | ||
5035 | |||
5036 | if (jacks->nid != nid) | ||
5037 | continue; | ||
5038 | present = snd_hda_jack_detect(codec, nid); | ||
5039 | type = jacks->type; | ||
5040 | if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) { | ||
5041 | pin_ctl = snd_hda_codec_read(codec, nid, 0, | ||
5042 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
5043 | type = (pin_ctl & AC_PINCTL_HP_EN) ? | ||
5044 | SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
5045 | } | ||
5046 | snd_jack_report(jacks->jack, present ? type : 0); | ||
5047 | } | ||
5048 | } | ||
5049 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_report); | ||
5050 | |||
5051 | /* free jack instances manually when clearing/reconfiguring */ | ||
5052 | void snd_hda_input_jack_free(struct hda_codec *codec) | ||
5053 | { | ||
5054 | if (!codec->bus->shutdown && codec->jacks.list) { | ||
5055 | struct hda_jack_item *jacks = codec->jacks.list; | ||
5056 | int i; | ||
5057 | for (i = 0; i < codec->jacks.used; i++, jacks++) { | ||
5058 | if (jacks->jack) | ||
5059 | snd_device_free(codec->bus->card, jacks->jack); | ||
5060 | } | ||
5061 | } | ||
5062 | snd_array_free(&codec->jacks); | ||
5063 | } | ||
5064 | EXPORT_SYMBOL_HDA(snd_hda_input_jack_free); | ||
5065 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | ||
5066 | |||
4962 | MODULE_DESCRIPTION("HDA codec core"); | 5067 | MODULE_DESCRIPTION("HDA codec core"); |
4963 | MODULE_LICENSE("GPL"); | 5068 | MODULE_LICENSE("GPL"); |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index fdf8d44f8b6b..e46d5420a9f2 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -866,6 +866,11 @@ struct hda_codec { | |||
866 | /* codec-specific additional proc output */ | 866 | /* codec-specific additional proc output */ |
867 | void (*proc_widget_hook)(struct snd_info_buffer *buffer, | 867 | void (*proc_widget_hook)(struct snd_info_buffer *buffer, |
868 | struct hda_codec *codec, hda_nid_t nid); | 868 | struct hda_codec *codec, hda_nid_t nid); |
869 | |||
870 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
871 | /* jack detection */ | ||
872 | struct snd_array jacks; | ||
873 | #endif | ||
869 | }; | 874 | }; |
870 | 875 | ||
871 | /* direction */ | 876 | /* direction */ |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fcedad9a5fef..70a9d32f0e96 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -1052,9 +1052,12 @@ static void azx_init_pci(struct azx *chip) | |||
1052 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) | 1052 | /* Clear bits 0-2 of PCI register TCSEL (at offset 0x44) |
1053 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS | 1053 | * TCSEL == Traffic Class Select Register, which sets PCI express QOS |
1054 | * Ensuring these bits are 0 clears playback static on some HD Audio | 1054 | * Ensuring these bits are 0 clears playback static on some HD Audio |
1055 | * codecs | 1055 | * codecs. |
1056 | * The PCI register TCSEL is defined in the Intel manuals. | ||
1056 | */ | 1057 | */ |
1057 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | 1058 | if (chip->driver_type != AZX_DRIVER_ATI && |
1059 | chip->driver_type != AZX_DRIVER_ATIHDMI) | ||
1060 | update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0); | ||
1058 | 1061 | ||
1059 | switch (chip->driver_type) { | 1062 | switch (chip->driver_type) { |
1060 | case AZX_DRIVER_ATI: | 1063 | case AZX_DRIVER_ATI: |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 3ab5e7a303db..ff5e2ac2239a 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -656,4 +656,28 @@ static inline void snd_hda_eld_proc_free(struct hda_codec *codec, | |||
656 | #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 | 656 | #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80 |
657 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); | 657 | void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen); |
658 | 658 | ||
659 | /* | ||
660 | * Input-jack notification support | ||
661 | */ | ||
662 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
663 | int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type, | ||
664 | const char *name); | ||
665 | void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid); | ||
666 | void snd_hda_input_jack_free(struct hda_codec *codec); | ||
667 | #else /* CONFIG_SND_HDA_INPUT_JACK */ | ||
668 | static inline int snd_hda_input_jack_add(struct hda_codec *codec, | ||
669 | hda_nid_t nid, int type, | ||
670 | const char *name) | ||
671 | { | ||
672 | return 0; | ||
673 | } | ||
674 | static inline void snd_hda_input_jack_report(struct hda_codec *codec, | ||
675 | hda_nid_t nid) | ||
676 | { | ||
677 | } | ||
678 | static inline void snd_hda_input_jack_free(struct hda_codec *codec) | ||
679 | { | ||
680 | } | ||
681 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | ||
682 | |||
659 | #endif /* __SOUND_HDA_LOCAL_H */ | 683 | #endif /* __SOUND_HDA_LOCAL_H */ |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 8dabab798689..734c6ee55d8a 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -30,10 +30,10 @@ | |||
30 | #include "hda_beep.h" | 30 | #include "hda_beep.h" |
31 | 31 | ||
32 | struct ad198x_spec { | 32 | struct ad198x_spec { |
33 | struct snd_kcontrol_new *mixers[5]; | 33 | struct snd_kcontrol_new *mixers[6]; |
34 | int num_mixers; | 34 | int num_mixers; |
35 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ | 35 | unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ |
36 | const struct hda_verb *init_verbs[5]; /* initialization verbs | 36 | const struct hda_verb *init_verbs[6]; /* initialization verbs |
37 | * don't forget NULL termination! | 37 | * don't forget NULL termination! |
38 | */ | 38 | */ |
39 | unsigned int num_init_verbs; | 39 | unsigned int num_init_verbs; |
@@ -331,36 +331,11 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
331 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); | 331 | return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout); |
332 | } | 332 | } |
333 | 333 | ||
334 | static int ad198x_alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
335 | struct hda_codec *codec, | ||
336 | unsigned int stream_tag, | ||
337 | unsigned int format, | ||
338 | struct snd_pcm_substream *substream) | ||
339 | { | ||
340 | struct ad198x_spec *spec = codec->spec; | ||
341 | snd_hda_codec_setup_stream(codec, spec->alt_dac_nid[0], stream_tag, | ||
342 | 0, format); | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | static int ad198x_alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
347 | struct hda_codec *codec, | ||
348 | struct snd_pcm_substream *substream) | ||
349 | { | ||
350 | struct ad198x_spec *spec = codec->spec; | ||
351 | snd_hda_codec_cleanup_stream(codec, spec->alt_dac_nid[0]); | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static struct hda_pcm_stream ad198x_pcm_analog_alt_playback = { | 334 | static struct hda_pcm_stream ad198x_pcm_analog_alt_playback = { |
356 | .substreams = 1, | 335 | .substreams = 1, |
357 | .channels_min = 2, | 336 | .channels_min = 2, |
358 | .channels_max = 2, | 337 | .channels_max = 2, |
359 | /* NID is set in ad198x_build_pcms */ | 338 | /* NID is set in ad198x_build_pcms */ |
360 | .ops = { | ||
361 | .prepare = ad198x_alt_playback_pcm_prepare, | ||
362 | .cleanup = ad198x_alt_playback_pcm_cleanup | ||
363 | }, | ||
364 | }; | 339 | }; |
365 | 340 | ||
366 | /* | 341 | /* |
@@ -2239,29 +2214,6 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = { | |||
2239 | static struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = { | 2214 | static struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = { |
2240 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), | 2215 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT), |
2241 | 2216 | ||
2242 | HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT), | ||
2243 | HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT), | ||
2244 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT), | ||
2245 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT), | ||
2246 | HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT), | ||
2247 | HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT), | ||
2248 | HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT), | ||
2249 | |||
2250 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT), | ||
2251 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT), | ||
2252 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT), | ||
2253 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT), | ||
2254 | HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT), | ||
2255 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT), | ||
2256 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT), | ||
2257 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT), | ||
2258 | |||
2259 | HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT), | ||
2260 | HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT), | ||
2261 | |||
2262 | HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT), | ||
2263 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT), | ||
2264 | |||
2265 | { } /* end */ | 2217 | { } /* end */ |
2266 | }; | 2218 | }; |
2267 | 2219 | ||
@@ -2545,11 +2497,6 @@ static struct hda_verb ad1988_6stack_init_verbs[] = { | |||
2545 | }; | 2497 | }; |
2546 | 2498 | ||
2547 | static struct hda_verb ad1988_6stack_fp_init_verbs[] = { | 2499 | static struct hda_verb ad1988_6stack_fp_init_verbs[] = { |
2548 | /* Front, Surround, CLFE, side DAC; unmute as default */ | ||
2549 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2550 | {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2551 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2552 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2553 | /* Headphone; unmute as default */ | 2500 | /* Headphone; unmute as default */ |
2554 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 2501 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
2555 | /* Port-A front headphon path */ | 2502 | /* Port-A front headphon path */ |
@@ -2558,50 +2505,6 @@ static struct hda_verb ad1988_6stack_fp_init_verbs[] = { | |||
2558 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | 2505 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, |
2559 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 2506 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
2560 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 2507 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
2561 | /* Port-D line-out path */ | ||
2562 | {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2563 | {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2564 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2565 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2566 | /* Port-F surround path */ | ||
2567 | {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2568 | {0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2569 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2570 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2571 | /* Port-G CLFE path */ | ||
2572 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2573 | {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2574 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2575 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2576 | /* Port-H side path */ | ||
2577 | {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2578 | {0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2579 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
2580 | {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2581 | /* Mono out path */ | ||
2582 | {0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */ | ||
2583 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2584 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2585 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
2586 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */ | ||
2587 | /* Port-B front mic-in path */ | ||
2588 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2589 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2590 | {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
2591 | /* Port-C line-in path */ | ||
2592 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2593 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2594 | {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
2595 | {0x33, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2596 | /* Port-E mic-in path */ | ||
2597 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2598 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2599 | {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
2600 | {0x34, AC_VERB_SET_CONNECT_SEL, 0x0}, | ||
2601 | /* Analog CD Input */ | ||
2602 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
2603 | /* Analog Mix output amp */ | ||
2604 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ | ||
2605 | 2508 | ||
2606 | { } | 2509 | { } |
2607 | }; | 2510 | }; |
@@ -3316,20 +3219,20 @@ static int patch_ad1988(struct hda_codec *codec) | |||
3316 | spec->mixers[0] = ad1988_6stack_mixers1_rev2; | 3219 | spec->mixers[0] = ad1988_6stack_mixers1_rev2; |
3317 | else | 3220 | else |
3318 | spec->mixers[0] = ad1988_6stack_mixers1; | 3221 | spec->mixers[0] = ad1988_6stack_mixers1; |
3222 | spec->mixers[1] = ad1988_6stack_mixers2; | ||
3223 | spec->num_init_verbs = 1; | ||
3224 | spec->init_verbs[0] = ad1988_6stack_init_verbs; | ||
3319 | if (board_config == AD1988_6STACK_DIG_FP) { | 3225 | if (board_config == AD1988_6STACK_DIG_FP) { |
3320 | spec->mixers[1] = ad1988_6stack_fp_mixers; | 3226 | spec->num_mixers++; |
3227 | spec->mixers[2] = ad1988_6stack_fp_mixers; | ||
3228 | spec->num_init_verbs++; | ||
3229 | spec->init_verbs[1] = ad1988_6stack_fp_init_verbs; | ||
3321 | spec->slave_vols = ad1988_6stack_fp_slave_vols; | 3230 | spec->slave_vols = ad1988_6stack_fp_slave_vols; |
3322 | spec->slave_sws = ad1988_6stack_fp_slave_sws; | 3231 | spec->slave_sws = ad1988_6stack_fp_slave_sws; |
3323 | spec->alt_dac_nid = ad1988_alt_dac_nid; | 3232 | spec->alt_dac_nid = ad1988_alt_dac_nid; |
3324 | spec->stream_analog_alt_playback = | 3233 | spec->stream_analog_alt_playback = |
3325 | &ad198x_pcm_analog_alt_playback; | 3234 | &ad198x_pcm_analog_alt_playback; |
3326 | } else | 3235 | } |
3327 | spec->mixers[1] = ad1988_6stack_mixers2; | ||
3328 | spec->num_init_verbs = 1; | ||
3329 | if (board_config == AD1988_6STACK_DIG_FP) | ||
3330 | spec->init_verbs[0] = ad1988_6stack_fp_init_verbs; | ||
3331 | else | ||
3332 | spec->init_verbs[0] = ad1988_6stack_init_verbs; | ||
3333 | if ((board_config == AD1988_6STACK_DIG) || | 3236 | if ((board_config == AD1988_6STACK_DIG) || |
3334 | (board_config == AD1988_6STACK_DIG_FP)) { | 3237 | (board_config == AD1988_6STACK_DIG_FP)) { |
3335 | spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; | 3238 | spec->multiout.dig_out_nid = AD1988_SPDIF_OUT; |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 4d5004e693f0..d08cf31596f3 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -49,14 +49,6 @@ | |||
49 | #define AUTO_MIC_PORTB (1 << 1) | 49 | #define AUTO_MIC_PORTB (1 << 1) |
50 | #define AUTO_MIC_PORTC (1 << 2) | 50 | #define AUTO_MIC_PORTC (1 << 2) |
51 | 51 | ||
52 | struct conexant_jack { | ||
53 | |||
54 | hda_nid_t nid; | ||
55 | int type; | ||
56 | struct snd_jack *jack; | ||
57 | |||
58 | }; | ||
59 | |||
60 | struct pin_dac_pair { | 52 | struct pin_dac_pair { |
61 | hda_nid_t pin; | 53 | hda_nid_t pin; |
62 | hda_nid_t dac; | 54 | hda_nid_t dac; |
@@ -111,9 +103,6 @@ struct conexant_spec { | |||
111 | 103 | ||
112 | unsigned int spdif_route; | 104 | unsigned int spdif_route; |
113 | 105 | ||
114 | /* jack detection */ | ||
115 | struct snd_array jacks; | ||
116 | |||
117 | /* dynamic controls, init_verbs and input_mux */ | 106 | /* dynamic controls, init_verbs and input_mux */ |
118 | struct auto_pin_cfg autocfg; | 107 | struct auto_pin_cfg autocfg; |
119 | struct hda_input_mux private_imux; | 108 | struct hda_input_mux private_imux; |
@@ -393,71 +382,9 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol, | |||
393 | &spec->cur_mux[adc_idx]); | 382 | &spec->cur_mux[adc_idx]); |
394 | } | 383 | } |
395 | 384 | ||
396 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
397 | static void conexant_free_jack_priv(struct snd_jack *jack) | ||
398 | { | ||
399 | struct conexant_jack *jacks = jack->private_data; | ||
400 | jacks->nid = 0; | ||
401 | jacks->jack = NULL; | ||
402 | } | ||
403 | |||
404 | static int conexant_add_jack(struct hda_codec *codec, | ||
405 | hda_nid_t nid, int type) | ||
406 | { | ||
407 | struct conexant_spec *spec; | ||
408 | struct conexant_jack *jack; | ||
409 | const char *name; | ||
410 | int i, err; | ||
411 | |||
412 | spec = codec->spec; | ||
413 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
414 | |||
415 | jack = spec->jacks.list; | ||
416 | for (i = 0; i < spec->jacks.used; i++, jack++) | ||
417 | if (jack->nid == nid) | ||
418 | return 0 ; /* already present */ | ||
419 | |||
420 | jack = snd_array_new(&spec->jacks); | ||
421 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
422 | |||
423 | if (!jack) | ||
424 | return -ENOMEM; | ||
425 | |||
426 | jack->nid = nid; | ||
427 | jack->type = type; | ||
428 | |||
429 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
430 | if (err < 0) | ||
431 | return err; | ||
432 | jack->jack->private_data = jack; | ||
433 | jack->jack->private_free = conexant_free_jack_priv; | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
438 | { | ||
439 | struct conexant_spec *spec = codec->spec; | ||
440 | struct conexant_jack *jacks = spec->jacks.list; | ||
441 | |||
442 | if (jacks) { | ||
443 | int i; | ||
444 | for (i = 0; i < spec->jacks.used; i++) { | ||
445 | if (jacks->nid == nid) { | ||
446 | unsigned int present; | ||
447 | present = snd_hda_jack_detect(codec, nid); | ||
448 | |||
449 | present = (present) ? jacks->type : 0 ; | ||
450 | |||
451 | snd_jack_report(jacks->jack, | ||
452 | present); | ||
453 | } | ||
454 | jacks++; | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | |||
459 | static int conexant_init_jacks(struct hda_codec *codec) | 385 | static int conexant_init_jacks(struct hda_codec *codec) |
460 | { | 386 | { |
387 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
461 | struct conexant_spec *spec = codec->spec; | 388 | struct conexant_spec *spec = codec->spec; |
462 | int i; | 389 | int i; |
463 | 390 | ||
@@ -469,15 +396,15 @@ static int conexant_init_jacks(struct hda_codec *codec) | |||
469 | int err = 0; | 396 | int err = 0; |
470 | switch (hv->param ^ AC_USRSP_EN) { | 397 | switch (hv->param ^ AC_USRSP_EN) { |
471 | case CONEXANT_HP_EVENT: | 398 | case CONEXANT_HP_EVENT: |
472 | err = conexant_add_jack(codec, hv->nid, | 399 | err = snd_hda_input_jack_add(codec, hv->nid, |
473 | SND_JACK_HEADPHONE); | 400 | SND_JACK_HEADPHONE, NULL); |
474 | conexant_report_jack(codec, hv->nid); | 401 | snd_hda_input_jack_report(codec, hv->nid); |
475 | break; | 402 | break; |
476 | case CXT5051_PORTC_EVENT: | 403 | case CXT5051_PORTC_EVENT: |
477 | case CONEXANT_MIC_EVENT: | 404 | case CONEXANT_MIC_EVENT: |
478 | err = conexant_add_jack(codec, hv->nid, | 405 | err = snd_hda_input_jack_add(codec, hv->nid, |
479 | SND_JACK_MICROPHONE); | 406 | SND_JACK_MICROPHONE, NULL); |
480 | conexant_report_jack(codec, hv->nid); | 407 | snd_hda_input_jack_report(codec, hv->nid); |
481 | break; | 408 | break; |
482 | } | 409 | } |
483 | if (err < 0) | 410 | if (err < 0) |
@@ -485,19 +412,9 @@ static int conexant_init_jacks(struct hda_codec *codec) | |||
485 | ++hv; | 412 | ++hv; |
486 | } | 413 | } |
487 | } | 414 | } |
488 | return 0; | 415 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ |
489 | |||
490 | } | ||
491 | #else | ||
492 | static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
493 | { | ||
494 | } | ||
495 | |||
496 | static inline int conexant_init_jacks(struct hda_codec *codec) | ||
497 | { | ||
498 | return 0; | 416 | return 0; |
499 | } | 417 | } |
500 | #endif | ||
501 | 418 | ||
502 | static int conexant_init(struct hda_codec *codec) | 419 | static int conexant_init(struct hda_codec *codec) |
503 | { | 420 | { |
@@ -511,18 +428,7 @@ static int conexant_init(struct hda_codec *codec) | |||
511 | 428 | ||
512 | static void conexant_free(struct hda_codec *codec) | 429 | static void conexant_free(struct hda_codec *codec) |
513 | { | 430 | { |
514 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 431 | snd_hda_input_jack_free(codec); |
515 | struct conexant_spec *spec = codec->spec; | ||
516 | if (spec->jacks.list) { | ||
517 | struct conexant_jack *jacks = spec->jacks.list; | ||
518 | int i; | ||
519 | for (i = 0; i < spec->jacks.used; i++, jacks++) { | ||
520 | if (jacks->jack) | ||
521 | snd_device_free(codec->bus->card, jacks->jack); | ||
522 | } | ||
523 | snd_array_free(&spec->jacks); | ||
524 | } | ||
525 | #endif | ||
526 | snd_hda_detach_beep_device(codec); | 432 | snd_hda_detach_beep_device(codec); |
527 | kfree(codec->spec); | 433 | kfree(codec->spec); |
528 | } | 434 | } |
@@ -1787,7 +1693,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec, | |||
1787 | cxt5051_portc_automic(codec); | 1693 | cxt5051_portc_automic(codec); |
1788 | break; | 1694 | break; |
1789 | } | 1695 | } |
1790 | conexant_report_jack(codec, nid); | 1696 | snd_hda_input_jack_report(codec, nid); |
1791 | } | 1697 | } |
1792 | 1698 | ||
1793 | static struct snd_kcontrol_new cxt5051_playback_mixers[] = { | 1699 | static struct snd_kcontrol_new cxt5051_playback_mixers[] = { |
@@ -1959,10 +1865,8 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid, | |||
1959 | snd_hda_codec_write(codec, nid, 0, | 1865 | snd_hda_codec_write(codec, nid, 0, |
1960 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1866 | AC_VERB_SET_UNSOLICITED_ENABLE, |
1961 | AC_USRSP_EN | event); | 1867 | AC_USRSP_EN | event); |
1962 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 1868 | snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL); |
1963 | conexant_add_jack(codec, nid, SND_JACK_MICROPHONE); | 1869 | snd_hda_input_jack_report(codec, nid); |
1964 | conexant_report_jack(codec, nid); | ||
1965 | #endif | ||
1966 | } | 1870 | } |
1967 | 1871 | ||
1968 | static struct hda_verb cxt5051_ideapad_init_verbs[] = { | 1872 | static struct hda_verb cxt5051_ideapad_init_verbs[] = { |
@@ -3477,11 +3381,11 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) | |||
3477 | switch (res >> 26) { | 3381 | switch (res >> 26) { |
3478 | case CONEXANT_HP_EVENT: | 3382 | case CONEXANT_HP_EVENT: |
3479 | cx_auto_hp_automute(codec); | 3383 | cx_auto_hp_automute(codec); |
3480 | conexant_report_jack(codec, nid); | 3384 | snd_hda_input_jack_report(codec, nid); |
3481 | break; | 3385 | break; |
3482 | case CONEXANT_MIC_EVENT: | 3386 | case CONEXANT_MIC_EVENT: |
3483 | cx_auto_automic(codec); | 3387 | cx_auto_automic(codec); |
3484 | conexant_report_jack(codec, nid); | 3388 | snd_hda_input_jack_report(codec, nid); |
3485 | break; | 3389 | break; |
3486 | } | 3390 | } |
3487 | } | 3391 | } |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index ec0fa2dd0a27..251773e45f61 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -110,6 +110,12 @@ struct dp_audio_infoframe { | |||
110 | u8 LFEPBL01_LSV36_DM_INH7; | 110 | u8 LFEPBL01_LSV36_DM_INH7; |
111 | }; | 111 | }; |
112 | 112 | ||
113 | union audio_infoframe { | ||
114 | struct hdmi_audio_infoframe hdmi; | ||
115 | struct dp_audio_infoframe dp; | ||
116 | u8 bytes[0]; | ||
117 | }; | ||
118 | |||
113 | /* | 119 | /* |
114 | * CEA speaker placement: | 120 | * CEA speaker placement: |
115 | * | 121 | * |
@@ -620,8 +626,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
620 | int channels = substream->runtime->channels; | 626 | int channels = substream->runtime->channels; |
621 | int ca; | 627 | int ca; |
622 | int i; | 628 | int i; |
623 | u8 ai[max(sizeof(struct hdmi_audio_infoframe), | 629 | union audio_infoframe ai; |
624 | sizeof(struct dp_audio_infoframe))]; | ||
625 | 630 | ||
626 | ca = hdmi_channel_allocation(codec, nid, channels); | 631 | ca = hdmi_channel_allocation(codec, nid, channels); |
627 | 632 | ||
@@ -633,11 +638,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
633 | 638 | ||
634 | pin_nid = spec->pin[i]; | 639 | pin_nid = spec->pin[i]; |
635 | 640 | ||
636 | memset(ai, 0, sizeof(ai)); | 641 | memset(&ai, 0, sizeof(ai)); |
637 | if (spec->sink_eld[i].conn_type == 0) { /* HDMI */ | 642 | if (spec->sink_eld[i].conn_type == 0) { /* HDMI */ |
638 | struct hdmi_audio_infoframe *hdmi_ai; | 643 | struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; |
639 | 644 | ||
640 | hdmi_ai = (struct hdmi_audio_infoframe *)ai; | ||
641 | hdmi_ai->type = 0x84; | 645 | hdmi_ai->type = 0x84; |
642 | hdmi_ai->ver = 0x01; | 646 | hdmi_ai->ver = 0x01; |
643 | hdmi_ai->len = 0x0a; | 647 | hdmi_ai->len = 0x0a; |
@@ -645,9 +649,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
645 | hdmi_ai->CA = ca; | 649 | hdmi_ai->CA = ca; |
646 | hdmi_checksum_audio_infoframe(hdmi_ai); | 650 | hdmi_checksum_audio_infoframe(hdmi_ai); |
647 | } else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */ | 651 | } else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */ |
648 | struct dp_audio_infoframe *dp_ai; | 652 | struct dp_audio_infoframe *dp_ai = &ai.dp; |
649 | 653 | ||
650 | dp_ai = (struct dp_audio_infoframe *)ai; | ||
651 | dp_ai->type = 0x84; | 654 | dp_ai->type = 0x84; |
652 | dp_ai->len = 0x1b; | 655 | dp_ai->len = 0x1b; |
653 | dp_ai->ver = 0x11 << 2; | 656 | dp_ai->ver = 0x11 << 2; |
@@ -664,7 +667,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
664 | * sizeof(*dp_ai) to avoid partial match/update problems when | 667 | * sizeof(*dp_ai) to avoid partial match/update problems when |
665 | * the user switches between HDMI/DP monitors. | 668 | * the user switches between HDMI/DP monitors. |
666 | */ | 669 | */ |
667 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai, sizeof(ai))) { | 670 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes, |
671 | sizeof(ai))) { | ||
668 | snd_printdd("hdmi_setup_audio_infoframe: " | 672 | snd_printdd("hdmi_setup_audio_infoframe: " |
669 | "cvt=%d pin=%d channels=%d\n", | 673 | "cvt=%d pin=%d channels=%d\n", |
670 | nid, pin_nid, | 674 | nid, pin_nid, |
@@ -672,7 +676,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
672 | hdmi_setup_channel_mapping(codec, pin_nid, ca); | 676 | hdmi_setup_channel_mapping(codec, pin_nid, ca); |
673 | hdmi_stop_infoframe_trans(codec, pin_nid); | 677 | hdmi_stop_infoframe_trans(codec, pin_nid); |
674 | hdmi_fill_audio_infoframe(codec, pin_nid, | 678 | hdmi_fill_audio_infoframe(codec, pin_nid, |
675 | ai, sizeof(ai)); | 679 | ai.bytes, sizeof(ai)); |
676 | hdmi_start_infoframe_trans(codec, pin_nid); | 680 | hdmi_start_infoframe_trans(codec, pin_nid); |
677 | } | 681 | } |
678 | } | 682 | } |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4261bb8eec1d..f1a03f223495 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -282,12 +282,6 @@ struct alc_mic_route { | |||
282 | unsigned char amix_idx; | 282 | unsigned char amix_idx; |
283 | }; | 283 | }; |
284 | 284 | ||
285 | struct alc_jack { | ||
286 | hda_nid_t nid; | ||
287 | int type; | ||
288 | struct snd_jack *jack; | ||
289 | }; | ||
290 | |||
291 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 285 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
292 | 286 | ||
293 | struct alc_customize_define { | 287 | struct alc_customize_define { |
@@ -366,9 +360,6 @@ struct alc_spec { | |||
366 | /* PCM information */ | 360 | /* PCM information */ |
367 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 361 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
368 | 362 | ||
369 | /* jack detection */ | ||
370 | struct snd_array jacks; | ||
371 | |||
372 | /* dynamic controls, init_verbs and input_mux */ | 363 | /* dynamic controls, init_verbs and input_mux */ |
373 | struct auto_pin_cfg autocfg; | 364 | struct auto_pin_cfg autocfg; |
374 | struct alc_customize_define cdefine; | 365 | struct alc_customize_define cdefine; |
@@ -394,6 +385,7 @@ struct alc_spec { | |||
394 | /* other flags */ | 385 | /* other flags */ |
395 | unsigned int no_analog :1; /* digital I/O only */ | 386 | unsigned int no_analog :1; /* digital I/O only */ |
396 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ | 387 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ |
388 | unsigned int single_input_src:1; | ||
397 | int init_amp; | 389 | int init_amp; |
398 | int codec_variant; /* flag for other variants */ | 390 | int codec_variant; /* flag for other variants */ |
399 | 391 | ||
@@ -1032,94 +1024,32 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
1032 | alc_fix_pll(codec); | 1024 | alc_fix_pll(codec); |
1033 | } | 1025 | } |
1034 | 1026 | ||
1035 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
1036 | static void alc_free_jack_priv(struct snd_jack *jack) | ||
1037 | { | ||
1038 | struct alc_jack *jacks = jack->private_data; | ||
1039 | jacks->nid = 0; | ||
1040 | jacks->jack = NULL; | ||
1041 | } | ||
1042 | |||
1043 | static int alc_add_jack(struct hda_codec *codec, | ||
1044 | hda_nid_t nid, int type) | ||
1045 | { | ||
1046 | struct alc_spec *spec; | ||
1047 | struct alc_jack *jack; | ||
1048 | const char *name; | ||
1049 | int err; | ||
1050 | |||
1051 | spec = codec->spec; | ||
1052 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
1053 | jack = snd_array_new(&spec->jacks); | ||
1054 | if (!jack) | ||
1055 | return -ENOMEM; | ||
1056 | |||
1057 | jack->nid = nid; | ||
1058 | jack->type = type; | ||
1059 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
1060 | |||
1061 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
1062 | if (err < 0) | ||
1063 | return err; | ||
1064 | jack->jack->private_data = jack; | ||
1065 | jack->jack->private_free = alc_free_jack_priv; | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1070 | { | ||
1071 | struct alc_spec *spec = codec->spec; | ||
1072 | struct alc_jack *jacks = spec->jacks.list; | ||
1073 | |||
1074 | if (jacks) { | ||
1075 | int i; | ||
1076 | for (i = 0; i < spec->jacks.used; i++) { | ||
1077 | if (jacks->nid == nid) { | ||
1078 | unsigned int present; | ||
1079 | present = snd_hda_jack_detect(codec, nid); | ||
1080 | |||
1081 | present = (present) ? jacks->type : 0; | ||
1082 | |||
1083 | snd_jack_report(jacks->jack, present); | ||
1084 | } | ||
1085 | jacks++; | ||
1086 | } | ||
1087 | } | ||
1088 | } | ||
1089 | |||
1090 | static int alc_init_jacks(struct hda_codec *codec) | 1027 | static int alc_init_jacks(struct hda_codec *codec) |
1091 | { | 1028 | { |
1029 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
1092 | struct alc_spec *spec = codec->spec; | 1030 | struct alc_spec *spec = codec->spec; |
1093 | int err; | 1031 | int err; |
1094 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | 1032 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; |
1095 | unsigned int mic_nid = spec->ext_mic.pin; | 1033 | unsigned int mic_nid = spec->ext_mic.pin; |
1096 | 1034 | ||
1097 | if (hp_nid) { | 1035 | if (hp_nid) { |
1098 | err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE); | 1036 | err = snd_hda_input_jack_add(codec, hp_nid, |
1037 | SND_JACK_HEADPHONE, NULL); | ||
1099 | if (err < 0) | 1038 | if (err < 0) |
1100 | return err; | 1039 | return err; |
1101 | alc_report_jack(codec, hp_nid); | 1040 | snd_hda_input_jack_report(codec, hp_nid); |
1102 | } | 1041 | } |
1103 | 1042 | ||
1104 | if (mic_nid) { | 1043 | if (mic_nid) { |
1105 | err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE); | 1044 | err = snd_hda_input_jack_add(codec, mic_nid, |
1045 | SND_JACK_MICROPHONE, NULL); | ||
1106 | if (err < 0) | 1046 | if (err < 0) |
1107 | return err; | 1047 | return err; |
1108 | alc_report_jack(codec, mic_nid); | 1048 | snd_hda_input_jack_report(codec, mic_nid); |
1109 | } | 1049 | } |
1110 | 1050 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ | |
1111 | return 0; | ||
1112 | } | ||
1113 | #else | ||
1114 | static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1115 | { | ||
1116 | } | ||
1117 | |||
1118 | static inline int alc_init_jacks(struct hda_codec *codec) | ||
1119 | { | ||
1120 | return 0; | 1051 | return 0; |
1121 | } | 1052 | } |
1122 | #endif | ||
1123 | 1053 | ||
1124 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | 1054 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) |
1125 | { | 1055 | { |
@@ -1133,7 +1063,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | |||
1133 | nid = spec->autocfg.hp_pins[i]; | 1063 | nid = spec->autocfg.hp_pins[i]; |
1134 | if (!nid) | 1064 | if (!nid) |
1135 | break; | 1065 | break; |
1136 | alc_report_jack(codec, nid); | 1066 | snd_hda_input_jack_report(codec, nid); |
1137 | spec->jack_present |= snd_hda_jack_detect(codec, nid); | 1067 | spec->jack_present |= snd_hda_jack_detect(codec, nid); |
1138 | } | 1068 | } |
1139 | 1069 | ||
@@ -1240,7 +1170,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
1240 | AC_VERB_SET_CONNECT_SEL, | 1170 | AC_VERB_SET_CONNECT_SEL, |
1241 | alive->mux_idx); | 1171 | alive->mux_idx); |
1242 | } | 1172 | } |
1243 | alc_report_jack(codec, spec->ext_mic.pin); | 1173 | snd_hda_input_jack_report(codec, spec->ext_mic.pin); |
1244 | 1174 | ||
1245 | /* FIXME: analog mixer */ | 1175 | /* FIXME: analog mixer */ |
1246 | } | 1176 | } |
@@ -2292,13 +2222,13 @@ static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = { | |||
2292 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | 2222 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
2293 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), | 2223 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), |
2294 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), | 2224 | HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), |
2295 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0f, 2, 0x0, | 2225 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, |
2296 | HDA_OUTPUT), | 2226 | HDA_OUTPUT), |
2297 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0f, 2, 2, HDA_INPUT), | 2227 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), |
2298 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT), | 2228 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), |
2299 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT), | 2229 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), |
2300 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | 2230 | HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT), |
2301 | HDA_BIND_MUTE("Side Playback Switch", 0x0e, 2, HDA_INPUT), | 2231 | HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT), |
2302 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | 2232 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), |
2303 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | 2233 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), |
2304 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | 2234 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), |
@@ -2309,7 +2239,6 @@ static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = { | |||
2309 | { } /* end */ | 2239 | { } /* end */ |
2310 | }; | 2240 | }; |
2311 | 2241 | ||
2312 | |||
2313 | static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = { | 2242 | static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = { |
2314 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 2243 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
2315 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | 2244 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
@@ -3919,6 +3848,8 @@ static struct hda_amp_list alc880_lg_loopbacks[] = { | |||
3919 | * Common callbacks | 3848 | * Common callbacks |
3920 | */ | 3849 | */ |
3921 | 3850 | ||
3851 | static void alc_init_special_input_src(struct hda_codec *codec); | ||
3852 | |||
3922 | static int alc_init(struct hda_codec *codec) | 3853 | static int alc_init(struct hda_codec *codec) |
3923 | { | 3854 | { |
3924 | struct alc_spec *spec = codec->spec; | 3855 | struct alc_spec *spec = codec->spec; |
@@ -3929,6 +3860,7 @@ static int alc_init(struct hda_codec *codec) | |||
3929 | 3860 | ||
3930 | for (i = 0; i < spec->num_init_verbs; i++) | 3861 | for (i = 0; i < spec->num_init_verbs; i++) |
3931 | snd_hda_sequence_write(codec, spec->init_verbs[i]); | 3862 | snd_hda_sequence_write(codec, spec->init_verbs[i]); |
3863 | alc_init_special_input_src(codec); | ||
3932 | 3864 | ||
3933 | if (spec->init_hook) | 3865 | if (spec->init_hook) |
3934 | spec->init_hook(codec); | 3866 | spec->init_hook(codec); |
@@ -4284,6 +4216,7 @@ static void alc_free(struct hda_codec *codec) | |||
4284 | return; | 4216 | return; |
4285 | 4217 | ||
4286 | alc_shutup(codec); | 4218 | alc_shutup(codec); |
4219 | snd_hda_input_jack_free(codec); | ||
4287 | alc_free_kctls(codec); | 4220 | alc_free_kctls(codec); |
4288 | kfree(spec); | 4221 | kfree(spec); |
4289 | snd_hda_detach_beep_device(codec); | 4222 | snd_hda_detach_beep_device(codec); |
@@ -4702,7 +4635,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = { | |||
4702 | SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), | 4635 | SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2), |
4703 | SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), | 4636 | SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG), |
4704 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), | 4637 | SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG), |
4705 | SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734), | 4638 | SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734), |
4706 | SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), | 4639 | SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL), |
4707 | SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), | 4640 | SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53), |
4708 | SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), | 4641 | SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810), |
@@ -5151,7 +5084,9 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg, | |||
5151 | 5084 | ||
5152 | switch (cfg->line_out_type) { | 5085 | switch (cfg->line_out_type) { |
5153 | case AUTO_PIN_SPEAKER_OUT: | 5086 | case AUTO_PIN_SPEAKER_OUT: |
5154 | return "Speaker"; | 5087 | if (cfg->line_outs == 1) |
5088 | return "Speaker"; | ||
5089 | break; | ||
5155 | case AUTO_PIN_HP_OUT: | 5090 | case AUTO_PIN_HP_OUT: |
5156 | return "Headphone"; | 5091 | return "Headphone"; |
5157 | default: | 5092 | default: |
@@ -5205,16 +5140,19 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
5205 | return err; | 5140 | return err; |
5206 | } else { | 5141 | } else { |
5207 | const char *name = pfx; | 5142 | const char *name = pfx; |
5208 | if (!name) | 5143 | int index = i; |
5144 | if (!name) { | ||
5209 | name = chname[i]; | 5145 | name = chname[i]; |
5146 | index = 0; | ||
5147 | } | ||
5210 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, | 5148 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, |
5211 | name, i, | 5149 | name, index, |
5212 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, | 5150 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, |
5213 | HDA_OUTPUT)); | 5151 | HDA_OUTPUT)); |
5214 | if (err < 0) | 5152 | if (err < 0) |
5215 | return err; | 5153 | return err; |
5216 | err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, | 5154 | err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE, |
5217 | name, i, | 5155 | name, index, |
5218 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, | 5156 | HDA_COMPOSE_AMP_VAL(nid, 3, 2, |
5219 | HDA_INPUT)); | 5157 | HDA_INPUT)); |
5220 | if (err < 0) | 5158 | if (err < 0) |
@@ -5585,6 +5523,7 @@ static void fixup_single_adc(struct hda_codec *codec) | |||
5585 | spec->capsrc_nids += i; | 5523 | spec->capsrc_nids += i; |
5586 | spec->adc_nids += i; | 5524 | spec->adc_nids += i; |
5587 | spec->num_adc_nids = 1; | 5525 | spec->num_adc_nids = 1; |
5526 | spec->single_input_src = 1; | ||
5588 | } | 5527 | } |
5589 | } | 5528 | } |
5590 | 5529 | ||
@@ -5596,6 +5535,16 @@ static void fixup_dual_adc_switch(struct hda_codec *codec) | |||
5596 | init_capsrc_for_pin(codec, spec->int_mic.pin); | 5535 | init_capsrc_for_pin(codec, spec->int_mic.pin); |
5597 | } | 5536 | } |
5598 | 5537 | ||
5538 | /* initialize some special cases for input sources */ | ||
5539 | static void alc_init_special_input_src(struct hda_codec *codec) | ||
5540 | { | ||
5541 | struct alc_spec *spec = codec->spec; | ||
5542 | if (spec->dual_adc_switch) | ||
5543 | fixup_dual_adc_switch(codec); | ||
5544 | else if (spec->single_input_src) | ||
5545 | init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin); | ||
5546 | } | ||
5547 | |||
5599 | static void set_capture_mixer(struct hda_codec *codec) | 5548 | static void set_capture_mixer(struct hda_codec *codec) |
5600 | { | 5549 | { |
5601 | struct alc_spec *spec = codec->spec; | 5550 | struct alc_spec *spec = codec->spec; |
@@ -5611,7 +5560,7 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
5611 | int mux = 0; | 5560 | int mux = 0; |
5612 | int num_adcs = spec->num_adc_nids; | 5561 | int num_adcs = spec->num_adc_nids; |
5613 | if (spec->dual_adc_switch) | 5562 | if (spec->dual_adc_switch) |
5614 | fixup_dual_adc_switch(codec); | 5563 | num_adcs = 1; |
5615 | else if (spec->auto_mic) | 5564 | else if (spec->auto_mic) |
5616 | fixup_automic_adc(codec); | 5565 | fixup_automic_adc(codec); |
5617 | else if (spec->input_mux) { | 5566 | else if (spec->input_mux) { |
@@ -5620,8 +5569,6 @@ static void set_capture_mixer(struct hda_codec *codec) | |||
5620 | else if (spec->input_mux->num_items == 1) | 5569 | else if (spec->input_mux->num_items == 1) |
5621 | fixup_single_adc(codec); | 5570 | fixup_single_adc(codec); |
5622 | } | 5571 | } |
5623 | if (spec->dual_adc_switch) | ||
5624 | num_adcs = 1; | ||
5625 | spec->cap_mixer = caps[mux][num_adcs - 1]; | 5572 | spec->cap_mixer = caps[mux][num_adcs - 1]; |
5626 | } | 5573 | } |
5627 | } | 5574 | } |
@@ -10748,6 +10695,7 @@ static struct alc_config_preset alc882_presets[] = { | |||
10748 | */ | 10695 | */ |
10749 | enum { | 10696 | enum { |
10750 | PINFIX_ABIT_AW9D_MAX, | 10697 | PINFIX_ABIT_AW9D_MAX, |
10698 | PINFIX_LENOVO_Y530, | ||
10751 | PINFIX_PB_M5210, | 10699 | PINFIX_PB_M5210, |
10752 | PINFIX_ACER_ASPIRE_7736, | 10700 | PINFIX_ACER_ASPIRE_7736, |
10753 | }; | 10701 | }; |
@@ -10762,6 +10710,14 @@ static const struct alc_fixup alc882_fixups[] = { | |||
10762 | { } | 10710 | { } |
10763 | } | 10711 | } |
10764 | }, | 10712 | }, |
10713 | [PINFIX_LENOVO_Y530] = { | ||
10714 | .type = ALC_FIXUP_PINS, | ||
10715 | .v.pins = (const struct alc_pincfg[]) { | ||
10716 | { 0x15, 0x99130112 }, /* rear int speakers */ | ||
10717 | { 0x16, 0x99130111 }, /* subwoofer */ | ||
10718 | { } | ||
10719 | } | ||
10720 | }, | ||
10765 | [PINFIX_PB_M5210] = { | 10721 | [PINFIX_PB_M5210] = { |
10766 | .type = ALC_FIXUP_VERBS, | 10722 | .type = ALC_FIXUP_VERBS, |
10767 | .v.verbs = (const struct hda_verb[]) { | 10723 | .v.verbs = (const struct hda_verb[]) { |
@@ -10777,6 +10733,7 @@ static const struct alc_fixup alc882_fixups[] = { | |||
10777 | 10733 | ||
10778 | static struct snd_pci_quirk alc882_fixup_tbl[] = { | 10734 | static struct snd_pci_quirk alc882_fixup_tbl[] = { |
10779 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), | 10735 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), |
10736 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530), | ||
10780 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), | 10737 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), |
10781 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736), | 10738 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736), |
10782 | {} | 10739 | {} |
@@ -10829,23 +10786,28 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
10829 | hda_nid_t pin, dac; | 10786 | hda_nid_t pin, dac; |
10830 | int i; | 10787 | int i; |
10831 | 10788 | ||
10832 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { | 10789 | if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) { |
10833 | pin = spec->autocfg.hp_pins[i]; | 10790 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
10834 | if (!pin) | 10791 | pin = spec->autocfg.hp_pins[i]; |
10835 | break; | 10792 | if (!pin) |
10836 | dac = spec->multiout.hp_nid; | 10793 | break; |
10837 | if (!dac) | 10794 | dac = spec->multiout.hp_nid; |
10838 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10795 | if (!dac) |
10839 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); | 10796 | dac = spec->multiout.dac_nids[0]; /* to front */ |
10797 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); | ||
10798 | } | ||
10840 | } | 10799 | } |
10841 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | 10800 | |
10842 | pin = spec->autocfg.speaker_pins[i]; | 10801 | if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) { |
10843 | if (!pin) | 10802 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
10844 | break; | 10803 | pin = spec->autocfg.speaker_pins[i]; |
10845 | dac = spec->multiout.extra_out_nid[0]; | 10804 | if (!pin) |
10846 | if (!dac) | 10805 | break; |
10847 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10806 | dac = spec->multiout.extra_out_nid[0]; |
10848 | alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); | 10807 | if (!dac) |
10808 | dac = spec->multiout.dac_nids[0]; /* to front */ | ||
10809 | alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac); | ||
10810 | } | ||
10849 | } | 10811 | } |
10850 | } | 10812 | } |
10851 | 10813 | ||
@@ -13796,6 +13758,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) | |||
13796 | } | 13758 | } |
13797 | 13759 | ||
13798 | #define alc268_auto_init_analog_input alc882_auto_init_analog_input | 13760 | #define alc268_auto_init_analog_input alc882_auto_init_analog_input |
13761 | #define alc268_auto_init_input_src alc882_auto_init_input_src | ||
13799 | 13762 | ||
13800 | /* init callback for auto-configuration model -- overriding the default init */ | 13763 | /* init callback for auto-configuration model -- overriding the default init */ |
13801 | static void alc268_auto_init(struct hda_codec *codec) | 13764 | static void alc268_auto_init(struct hda_codec *codec) |
@@ -13805,6 +13768,7 @@ static void alc268_auto_init(struct hda_codec *codec) | |||
13805 | alc268_auto_init_hp_out(codec); | 13768 | alc268_auto_init_hp_out(codec); |
13806 | alc268_auto_init_mono_speaker_out(codec); | 13769 | alc268_auto_init_mono_speaker_out(codec); |
13807 | alc268_auto_init_analog_input(codec); | 13770 | alc268_auto_init_analog_input(codec); |
13771 | alc268_auto_init_input_src(codec); | ||
13808 | alc_auto_init_digital(codec); | 13772 | alc_auto_init_digital(codec); |
13809 | if (spec->unsol_event) | 13773 | if (spec->unsol_event) |
13810 | alc_inithook(codec); | 13774 | alc_inithook(codec); |
@@ -14092,7 +14056,6 @@ static int patch_alc268(struct hda_codec *codec) | |||
14092 | if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { | 14056 | if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { |
14093 | /* check whether NID 0x07 is valid */ | 14057 | /* check whether NID 0x07 is valid */ |
14094 | unsigned int wcap = get_wcaps(codec, 0x07); | 14058 | unsigned int wcap = get_wcaps(codec, 0x07); |
14095 | int i; | ||
14096 | 14059 | ||
14097 | spec->capsrc_nids = alc268_capsrc_nids; | 14060 | spec->capsrc_nids = alc268_capsrc_nids; |
14098 | /* get type */ | 14061 | /* get type */ |
@@ -14112,13 +14075,6 @@ static int patch_alc268(struct hda_codec *codec) | |||
14112 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids); | 14075 | spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids); |
14113 | add_mixer(spec, alc268_capture_mixer); | 14076 | add_mixer(spec, alc268_capture_mixer); |
14114 | } | 14077 | } |
14115 | /* set default input source */ | ||
14116 | for (i = 0; i < spec->num_adc_nids; i++) | ||
14117 | snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i], | ||
14118 | 0, AC_VERB_SET_CONNECT_SEL, | ||
14119 | i < spec->num_mux_defs ? | ||
14120 | spec->input_mux[i].items[0].index : | ||
14121 | spec->input_mux->items[0].index); | ||
14122 | } | 14078 | } |
14123 | 14079 | ||
14124 | spec->vmaster_nid = 0x02; | 14080 | spec->vmaster_nid = 0x02; |
@@ -14495,7 +14451,7 @@ static void alc269_speaker_automute(struct hda_codec *codec) | |||
14495 | HDA_AMP_MUTE, bits); | 14451 | HDA_AMP_MUTE, bits); |
14496 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 14452 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
14497 | HDA_AMP_MUTE, bits); | 14453 | HDA_AMP_MUTE, bits); |
14498 | alc_report_jack(codec, nid); | 14454 | snd_hda_input_jack_report(codec, nid); |
14499 | } | 14455 | } |
14500 | 14456 | ||
14501 | /* unsolicited event for HP jack sensing */ | 14457 | /* unsolicited event for HP jack sensing */ |
@@ -14807,11 +14763,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14807 | fillup_priv_adc_nids(codec, alc269_adc_candidates, | 14763 | fillup_priv_adc_nids(codec, alc269_adc_candidates, |
14808 | sizeof(alc269_adc_candidates)); | 14764 | sizeof(alc269_adc_candidates)); |
14809 | 14765 | ||
14810 | /* set default input source */ | ||
14811 | if (!spec->dual_adc_switch) | ||
14812 | select_or_unmute_capsrc(codec, spec->capsrc_nids[0], | ||
14813 | spec->input_mux->items[0].index); | ||
14814 | |||
14815 | err = alc_auto_add_mic_boost(codec); | 14766 | err = alc_auto_add_mic_boost(codec); |
14816 | if (err < 0) | 14767 | if (err < 0) |
14817 | return err; | 14768 | return err; |
@@ -14825,6 +14776,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14825 | #define alc269_auto_init_multi_out alc268_auto_init_multi_out | 14776 | #define alc269_auto_init_multi_out alc268_auto_init_multi_out |
14826 | #define alc269_auto_init_hp_out alc268_auto_init_hp_out | 14777 | #define alc269_auto_init_hp_out alc268_auto_init_hp_out |
14827 | #define alc269_auto_init_analog_input alc882_auto_init_analog_input | 14778 | #define alc269_auto_init_analog_input alc882_auto_init_analog_input |
14779 | #define alc269_auto_init_input_src alc882_auto_init_input_src | ||
14828 | 14780 | ||
14829 | 14781 | ||
14830 | /* init callback for auto-configuration model -- overriding the default init */ | 14782 | /* init callback for auto-configuration model -- overriding the default init */ |
@@ -14834,6 +14786,8 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
14834 | alc269_auto_init_multi_out(codec); | 14786 | alc269_auto_init_multi_out(codec); |
14835 | alc269_auto_init_hp_out(codec); | 14787 | alc269_auto_init_hp_out(codec); |
14836 | alc269_auto_init_analog_input(codec); | 14788 | alc269_auto_init_analog_input(codec); |
14789 | if (!spec->dual_adc_switch) | ||
14790 | alc269_auto_init_input_src(codec); | ||
14837 | alc_auto_init_digital(codec); | 14791 | alc_auto_init_digital(codec); |
14838 | if (spec->unsol_event) | 14792 | if (spec->unsol_event) |
14839 | alc_inithook(codec); | 14793 | alc_inithook(codec); |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index bd7b123f6440..05fcd60cc46f 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -180,18 +180,16 @@ struct sigmatel_event { | |||
180 | int data; | 180 | int data; |
181 | }; | 181 | }; |
182 | 182 | ||
183 | struct sigmatel_jack { | ||
184 | hda_nid_t nid; | ||
185 | int type; | ||
186 | struct snd_jack *jack; | ||
187 | }; | ||
188 | |||
189 | struct sigmatel_mic_route { | 183 | struct sigmatel_mic_route { |
190 | hda_nid_t pin; | 184 | hda_nid_t pin; |
191 | signed char mux_idx; | 185 | signed char mux_idx; |
192 | signed char dmux_idx; | 186 | signed char dmux_idx; |
193 | }; | 187 | }; |
194 | 188 | ||
189 | #define MAX_PINS_NUM 16 | ||
190 | #define MAX_ADCS_NUM 4 | ||
191 | #define MAX_DMICS_NUM 4 | ||
192 | |||
195 | struct sigmatel_spec { | 193 | struct sigmatel_spec { |
196 | struct snd_kcontrol_new *mixers[4]; | 194 | struct snd_kcontrol_new *mixers[4]; |
197 | unsigned int num_mixers; | 195 | unsigned int num_mixers; |
@@ -229,9 +227,6 @@ struct sigmatel_spec { | |||
229 | hda_nid_t *pwr_nids; | 227 | hda_nid_t *pwr_nids; |
230 | hda_nid_t *dac_list; | 228 | hda_nid_t *dac_list; |
231 | 229 | ||
232 | /* jack detection */ | ||
233 | struct snd_array jacks; | ||
234 | |||
235 | /* events */ | 230 | /* events */ |
236 | struct snd_array events; | 231 | struct snd_array events; |
237 | 232 | ||
@@ -309,6 +304,17 @@ struct sigmatel_spec { | |||
309 | struct hda_input_mux private_imux; | 304 | struct hda_input_mux private_imux; |
310 | struct hda_input_mux private_smux; | 305 | struct hda_input_mux private_smux; |
311 | struct hda_input_mux private_mono_mux; | 306 | struct hda_input_mux private_mono_mux; |
307 | |||
308 | /* auto spec */ | ||
309 | unsigned auto_pin_cnt; | ||
310 | hda_nid_t auto_pin_nids[MAX_PINS_NUM]; | ||
311 | unsigned auto_adc_cnt; | ||
312 | hda_nid_t auto_adc_nids[MAX_ADCS_NUM]; | ||
313 | hda_nid_t auto_mux_nids[MAX_ADCS_NUM]; | ||
314 | hda_nid_t auto_dmux_nids[MAX_ADCS_NUM]; | ||
315 | unsigned long auto_capvols[MAX_ADCS_NUM]; | ||
316 | unsigned auto_dmic_cnt; | ||
317 | hda_nid_t auto_dmic_nids[MAX_DMICS_NUM]; | ||
312 | }; | 318 | }; |
313 | 319 | ||
314 | static hda_nid_t stac9200_adc_nids[1] = { | 320 | static hda_nid_t stac9200_adc_nids[1] = { |
@@ -364,14 +370,6 @@ static unsigned long stac92hd73xx_capvols[] = { | |||
364 | 370 | ||
365 | #define STAC92HD83_DAC_COUNT 3 | 371 | #define STAC92HD83_DAC_COUNT 3 |
366 | 372 | ||
367 | static hda_nid_t stac92hd83xxx_mux_nids[2] = { | ||
368 | 0x17, 0x18, | ||
369 | }; | ||
370 | |||
371 | static hda_nid_t stac92hd83xxx_adc_nids[2] = { | ||
372 | 0x15, 0x16, | ||
373 | }; | ||
374 | |||
375 | static hda_nid_t stac92hd83xxx_pwr_nids[4] = { | 373 | static hda_nid_t stac92hd83xxx_pwr_nids[4] = { |
376 | 0xa, 0xb, 0xd, 0xe, | 374 | 0xa, 0xb, 0xd, 0xe, |
377 | }; | 375 | }; |
@@ -384,25 +382,9 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = { | |||
384 | 0x03, 0x0c, 0x20, 0x40, | 382 | 0x03, 0x0c, 0x20, 0x40, |
385 | }; | 383 | }; |
386 | 384 | ||
387 | #define STAC92HD83XXX_NUM_DMICS 2 | 385 | static hda_nid_t stac92hd83xxx_dmic_nids[] = { |
388 | static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | 386 | 0x11, 0x20, |
389 | 0x11, 0x20, 0 | ||
390 | }; | ||
391 | |||
392 | #define STAC92HD88XXX_NUM_DMICS STAC92HD83XXX_NUM_DMICS | ||
393 | #define stac92hd88xxx_dmic_nids stac92hd83xxx_dmic_nids | ||
394 | |||
395 | #define STAC92HD87B_NUM_DMICS 1 | ||
396 | static hda_nid_t stac92hd87b_dmic_nids[STAC92HD87B_NUM_DMICS + 1] = { | ||
397 | 0x11, 0 | ||
398 | }; | ||
399 | |||
400 | #define STAC92HD83XXX_NUM_CAPS 2 | ||
401 | static unsigned long stac92hd83xxx_capvols[] = { | ||
402 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), | ||
403 | HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_OUTPUT), | ||
404 | }; | 387 | }; |
405 | #define stac92hd83xxx_capsws stac92hd83xxx_capvols | ||
406 | 388 | ||
407 | static hda_nid_t stac92hd71bxx_pwr_nids[3] = { | 389 | static hda_nid_t stac92hd71bxx_pwr_nids[3] = { |
408 | 0x0a, 0x0d, 0x0f | 390 | 0x0a, 0x0d, 0x0f |
@@ -581,21 +563,6 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = { | |||
581 | 0x14, 0x22, 0x23 | 563 | 0x14, 0x22, 0x23 |
582 | }; | 564 | }; |
583 | 565 | ||
584 | static hda_nid_t stac92hd83xxx_pin_nids[10] = { | ||
585 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | ||
586 | 0x0f, 0x10, 0x11, 0x1f, 0x20, | ||
587 | }; | ||
588 | |||
589 | static hda_nid_t stac92hd87xxx_pin_nids[6] = { | ||
590 | 0x0a, 0x0b, 0x0c, 0x0d, | ||
591 | 0x0f, 0x11, | ||
592 | }; | ||
593 | |||
594 | static hda_nid_t stac92hd88xxx_pin_nids[8] = { | ||
595 | 0x0a, 0x0b, 0x0c, 0x0d, | ||
596 | 0x0f, 0x11, 0x1f, 0x20, | ||
597 | }; | ||
598 | |||
599 | #define STAC92HD71BXX_NUM_PINS 13 | 566 | #define STAC92HD71BXX_NUM_PINS 13 |
600 | static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { | 567 | static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = { |
601 | 0x0a, 0x0b, 0x0c, 0x0d, 0x00, | 568 | 0x0a, 0x0b, 0x0c, 0x0d, 0x00, |
@@ -757,7 +724,7 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
757 | struct sigmatel_spec *spec = codec->spec; | 724 | struct sigmatel_spec *spec = codec->spec; |
758 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 725 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
759 | const struct hda_input_mux *imux = spec->input_mux; | 726 | const struct hda_input_mux *imux = spec->input_mux; |
760 | unsigned int idx, prev_idx; | 727 | unsigned int idx, prev_idx, didx; |
761 | 728 | ||
762 | idx = ucontrol->value.enumerated.item[0]; | 729 | idx = ucontrol->value.enumerated.item[0]; |
763 | if (idx >= imux->num_items) | 730 | if (idx >= imux->num_items) |
@@ -769,7 +736,8 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
769 | snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, | 736 | snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0, |
770 | AC_VERB_SET_CONNECT_SEL, | 737 | AC_VERB_SET_CONNECT_SEL, |
771 | imux->items[idx].index); | 738 | imux->items[idx].index); |
772 | if (prev_idx >= spec->num_analog_muxes) { | 739 | if (prev_idx >= spec->num_analog_muxes && |
740 | spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) { | ||
773 | imux = spec->dinput_mux; | 741 | imux = spec->dinput_mux; |
774 | /* 0 = analog */ | 742 | /* 0 = analog */ |
775 | snd_hda_codec_write_cache(codec, | 743 | snd_hda_codec_write_cache(codec, |
@@ -779,9 +747,13 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
779 | } | 747 | } |
780 | } else { | 748 | } else { |
781 | imux = spec->dinput_mux; | 749 | imux = spec->dinput_mux; |
750 | /* first dimux item is hardcoded to select analog imux, | ||
751 | * so lets skip it | ||
752 | */ | ||
753 | didx = idx - spec->num_analog_muxes + 1; | ||
782 | snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, | 754 | snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0, |
783 | AC_VERB_SET_CONNECT_SEL, | 755 | AC_VERB_SET_CONNECT_SEL, |
784 | imux->items[idx - 1].index); | 756 | imux->items[didx].index); |
785 | } | 757 | } |
786 | spec->cur_mux[adc_idx] = idx; | 758 | spec->cur_mux[adc_idx] = idx; |
787 | return 1; | 759 | return 1; |
@@ -3419,6 +3391,17 @@ static const char * const stac92xx_dmic_labels[5] = { | |||
3419 | "Digital Mic 3", "Digital Mic 4" | 3391 | "Digital Mic 3", "Digital Mic 4" |
3420 | }; | 3392 | }; |
3421 | 3393 | ||
3394 | static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux, | ||
3395 | int idx) | ||
3396 | { | ||
3397 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
3398 | int nums; | ||
3399 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | ||
3400 | if (idx >= 0 && idx < nums) | ||
3401 | return conn[idx]; | ||
3402 | return 0; | ||
3403 | } | ||
3404 | |||
3422 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | 3405 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, |
3423 | hda_nid_t nid) | 3406 | hda_nid_t nid) |
3424 | { | 3407 | { |
@@ -3429,6 +3412,15 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | |||
3429 | for (i = 0; i < nums; i++) | 3412 | for (i = 0; i < nums; i++) |
3430 | if (conn[i] == nid) | 3413 | if (conn[i] == nid) |
3431 | return i; | 3414 | return i; |
3415 | |||
3416 | for (i = 0; i < nums; i++) { | ||
3417 | unsigned int wid_caps = get_wcaps(codec, conn[i]); | ||
3418 | unsigned int wid_type = get_wcaps_type(wid_caps); | ||
3419 | |||
3420 | if (wid_type != AC_WID_PIN && wid_type != AC_WID_AUD_MIX) | ||
3421 | if (get_connection_index(codec, conn[i], nid) >= 0) | ||
3422 | return i; | ||
3423 | } | ||
3432 | return -1; | 3424 | return -1; |
3433 | } | 3425 | } |
3434 | 3426 | ||
@@ -3501,6 +3493,16 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3501 | type_idx, HDA_OUTPUT); | 3493 | type_idx, HDA_OUTPUT); |
3502 | if (err < 0) | 3494 | if (err < 0) |
3503 | return err; | 3495 | return err; |
3496 | if (!err) { | ||
3497 | nid = get_connected_node(codec, | ||
3498 | spec->dmux_nids[0], index); | ||
3499 | if (nid) | ||
3500 | err = create_elem_capture_vol(codec, | ||
3501 | nid, label, | ||
3502 | type_idx, HDA_INPUT); | ||
3503 | if (err < 0) | ||
3504 | return err; | ||
3505 | } | ||
3504 | } | 3506 | } |
3505 | } | 3507 | } |
3506 | 3508 | ||
@@ -4054,21 +4056,10 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | |||
4054 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ | 4056 | AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */ |
4055 | } | 4057 | } |
4056 | 4058 | ||
4057 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
4058 | static void stac92xx_free_jack_priv(struct snd_jack *jack) | ||
4059 | { | ||
4060 | struct sigmatel_jack *jacks = jack->private_data; | ||
4061 | jacks->nid = 0; | ||
4062 | jacks->jack = NULL; | ||
4063 | } | ||
4064 | #endif | ||
4065 | |||
4066 | static int stac92xx_add_jack(struct hda_codec *codec, | 4059 | static int stac92xx_add_jack(struct hda_codec *codec, |
4067 | hda_nid_t nid, int type) | 4060 | hda_nid_t nid, int type) |
4068 | { | 4061 | { |
4069 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 4062 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
4070 | struct sigmatel_spec *spec = codec->spec; | ||
4071 | struct sigmatel_jack *jack; | ||
4072 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); | 4063 | int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
4073 | int connectivity = get_defcfg_connect(def_conf); | 4064 | int connectivity = get_defcfg_connect(def_conf); |
4074 | char name[32]; | 4065 | char name[32]; |
@@ -4077,26 +4068,15 @@ static int stac92xx_add_jack(struct hda_codec *codec, | |||
4077 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) | 4068 | if (connectivity && connectivity != AC_JACK_PORT_FIXED) |
4078 | return 0; | 4069 | return 0; |
4079 | 4070 | ||
4080 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
4081 | jack = snd_array_new(&spec->jacks); | ||
4082 | if (!jack) | ||
4083 | return -ENOMEM; | ||
4084 | jack->nid = nid; | ||
4085 | jack->type = type; | ||
4086 | |||
4087 | snprintf(name, sizeof(name), "%s at %s %s Jack", | 4071 | snprintf(name, sizeof(name), "%s at %s %s Jack", |
4088 | snd_hda_get_jack_type(def_conf), | 4072 | snd_hda_get_jack_type(def_conf), |
4089 | snd_hda_get_jack_connectivity(def_conf), | 4073 | snd_hda_get_jack_connectivity(def_conf), |
4090 | snd_hda_get_jack_location(def_conf)); | 4074 | snd_hda_get_jack_location(def_conf)); |
4091 | 4075 | ||
4092 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | 4076 | err = snd_hda_input_jack_add(codec, nid, type, name); |
4093 | if (err < 0) { | 4077 | if (err < 0) |
4094 | jack->nid = 0; | ||
4095 | return err; | 4078 | return err; |
4096 | } | 4079 | #endif /* CONFIG_SND_HDA_INPUT_JACK */ |
4097 | jack->jack->private_data = jack; | ||
4098 | jack->jack->private_free = stac92xx_free_jack_priv; | ||
4099 | #endif | ||
4100 | return 0; | 4080 | return 0; |
4101 | } | 4081 | } |
4102 | 4082 | ||
@@ -4399,23 +4379,6 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4399 | return 0; | 4379 | return 0; |
4400 | } | 4380 | } |
4401 | 4381 | ||
4402 | static void stac92xx_free_jacks(struct hda_codec *codec) | ||
4403 | { | ||
4404 | #ifdef CONFIG_SND_HDA_INPUT_JACK | ||
4405 | /* free jack instances manually when clearing/reconfiguring */ | ||
4406 | struct sigmatel_spec *spec = codec->spec; | ||
4407 | if (!codec->bus->shutdown && spec->jacks.list) { | ||
4408 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
4409 | int i; | ||
4410 | for (i = 0; i < spec->jacks.used; i++, jacks++) { | ||
4411 | if (jacks->jack) | ||
4412 | snd_device_free(codec->bus->card, jacks->jack); | ||
4413 | } | ||
4414 | } | ||
4415 | snd_array_free(&spec->jacks); | ||
4416 | #endif | ||
4417 | } | ||
4418 | |||
4419 | static void stac92xx_free_kctls(struct hda_codec *codec) | 4382 | static void stac92xx_free_kctls(struct hda_codec *codec) |
4420 | { | 4383 | { |
4421 | struct sigmatel_spec *spec = codec->spec; | 4384 | struct sigmatel_spec *spec = codec->spec; |
@@ -4449,7 +4412,7 @@ static void stac92xx_free(struct hda_codec *codec) | |||
4449 | return; | 4412 | return; |
4450 | 4413 | ||
4451 | stac92xx_shutup(codec); | 4414 | stac92xx_shutup(codec); |
4452 | stac92xx_free_jacks(codec); | 4415 | snd_hda_input_jack_free(codec); |
4453 | snd_array_free(&spec->events); | 4416 | snd_array_free(&spec->events); |
4454 | 4417 | ||
4455 | kfree(spec); | 4418 | kfree(spec); |
@@ -4667,33 +4630,6 @@ static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid) | |||
4667 | stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); | 4630 | stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid)); |
4668 | } | 4631 | } |
4669 | 4632 | ||
4670 | static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
4671 | { | ||
4672 | struct sigmatel_spec *spec = codec->spec; | ||
4673 | struct sigmatel_jack *jacks = spec->jacks.list; | ||
4674 | |||
4675 | if (jacks) { | ||
4676 | int i; | ||
4677 | for (i = 0; i < spec->jacks.used; i++) { | ||
4678 | if (jacks->nid == nid) { | ||
4679 | unsigned int pin_ctl = | ||
4680 | snd_hda_codec_read(codec, nid, | ||
4681 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, | ||
4682 | 0x00); | ||
4683 | int type = jacks->type; | ||
4684 | if (type == (SND_JACK_LINEOUT | ||
4685 | | SND_JACK_HEADPHONE)) | ||
4686 | type = (pin_ctl & AC_PINCTL_HP_EN) | ||
4687 | ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT; | ||
4688 | snd_jack_report(jacks->jack, | ||
4689 | get_pin_presence(codec, nid) | ||
4690 | ? type : 0); | ||
4691 | } | ||
4692 | jacks++; | ||
4693 | } | ||
4694 | } | ||
4695 | } | ||
4696 | |||
4697 | /* get the pin connection (fixed, none, etc) */ | 4633 | /* get the pin connection (fixed, none, etc) */ |
4698 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | 4634 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) |
4699 | { | 4635 | { |
@@ -4782,7 +4718,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4782 | case STAC_PWR_EVENT: | 4718 | case STAC_PWR_EVENT: |
4783 | if (spec->num_pwrs > 0) | 4719 | if (spec->num_pwrs > 0) |
4784 | stac92xx_pin_sense(codec, event->nid); | 4720 | stac92xx_pin_sense(codec, event->nid); |
4785 | stac92xx_report_jack(codec, event->nid); | 4721 | snd_hda_input_jack_report(codec, event->nid); |
4786 | 4722 | ||
4787 | switch (codec->subsystem_id) { | 4723 | switch (codec->subsystem_id) { |
4788 | case 0x103c308f: | 4724 | case 0x103c308f: |
@@ -5378,6 +5314,105 @@ static int hp_bnb2011_with_dock(struct hda_codec *codec) | |||
5378 | return 0; | 5314 | return 0; |
5379 | } | 5315 | } |
5380 | 5316 | ||
5317 | static void stac92hd8x_add_pin(struct hda_codec *codec, hda_nid_t nid) | ||
5318 | { | ||
5319 | struct sigmatel_spec *spec = codec->spec; | ||
5320 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
5321 | int i; | ||
5322 | |||
5323 | spec->auto_pin_nids[spec->auto_pin_cnt] = nid; | ||
5324 | spec->auto_pin_cnt++; | ||
5325 | |||
5326 | if (get_defcfg_device(def_conf) == AC_JACK_MIC_IN && | ||
5327 | get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) { | ||
5328 | for (i = 0; i < ARRAY_SIZE(stac92hd83xxx_dmic_nids); i++) { | ||
5329 | if (nid == stac92hd83xxx_dmic_nids[i]) { | ||
5330 | spec->auto_dmic_nids[spec->auto_dmic_cnt] = nid; | ||
5331 | spec->auto_dmic_cnt++; | ||
5332 | } | ||
5333 | } | ||
5334 | } | ||
5335 | } | ||
5336 | |||
5337 | static void stac92hd8x_add_adc(struct hda_codec *codec, hda_nid_t nid) | ||
5338 | { | ||
5339 | struct sigmatel_spec *spec = codec->spec; | ||
5340 | |||
5341 | spec->auto_adc_nids[spec->auto_adc_cnt] = nid; | ||
5342 | spec->auto_adc_cnt++; | ||
5343 | } | ||
5344 | |||
5345 | static void stac92hd8x_add_mux(struct hda_codec *codec, hda_nid_t nid) | ||
5346 | { | ||
5347 | int i, j; | ||
5348 | struct sigmatel_spec *spec = codec->spec; | ||
5349 | |||
5350 | for (i = 0; i < spec->auto_adc_cnt; i++) { | ||
5351 | if (get_connection_index(codec, | ||
5352 | spec->auto_adc_nids[i], nid) >= 0) { | ||
5353 | /* mux and volume for adc_nids[i] */ | ||
5354 | if (!spec->auto_mux_nids[i]) { | ||
5355 | spec->auto_mux_nids[i] = nid; | ||
5356 | /* 92hd codecs capture volume is in mux */ | ||
5357 | spec->auto_capvols[i] = HDA_COMPOSE_AMP_VAL(nid, | ||
5358 | 3, 0, HDA_OUTPUT); | ||
5359 | } | ||
5360 | for (j = 0; j < spec->auto_dmic_cnt; j++) { | ||
5361 | if (get_connection_index(codec, nid, | ||
5362 | spec->auto_dmic_nids[j]) >= 0) { | ||
5363 | /* dmux for adc_nids[i] */ | ||
5364 | if (!spec->auto_dmux_nids[i]) | ||
5365 | spec->auto_dmux_nids[i] = nid; | ||
5366 | break; | ||
5367 | } | ||
5368 | } | ||
5369 | break; | ||
5370 | } | ||
5371 | } | ||
5372 | } | ||
5373 | |||
5374 | static void stac92hd8x_fill_auto_spec(struct hda_codec *codec) | ||
5375 | { | ||
5376 | hda_nid_t nid, end_nid; | ||
5377 | unsigned int wid_caps, wid_type; | ||
5378 | struct sigmatel_spec *spec = codec->spec; | ||
5379 | |||
5380 | end_nid = codec->start_nid + codec->num_nodes; | ||
5381 | |||
5382 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
5383 | wid_caps = get_wcaps(codec, nid); | ||
5384 | wid_type = get_wcaps_type(wid_caps); | ||
5385 | |||
5386 | if (wid_type == AC_WID_PIN) | ||
5387 | stac92hd8x_add_pin(codec, nid); | ||
5388 | |||
5389 | if (wid_type == AC_WID_AUD_IN && !(wid_caps & AC_WCAP_DIGITAL)) | ||
5390 | stac92hd8x_add_adc(codec, nid); | ||
5391 | } | ||
5392 | |||
5393 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
5394 | wid_caps = get_wcaps(codec, nid); | ||
5395 | wid_type = get_wcaps_type(wid_caps); | ||
5396 | |||
5397 | if (wid_type == AC_WID_AUD_SEL) | ||
5398 | stac92hd8x_add_mux(codec, nid); | ||
5399 | } | ||
5400 | |||
5401 | spec->pin_nids = spec->auto_pin_nids; | ||
5402 | spec->num_pins = spec->auto_pin_cnt; | ||
5403 | spec->adc_nids = spec->auto_adc_nids; | ||
5404 | spec->num_adcs = spec->auto_adc_cnt; | ||
5405 | spec->capvols = spec->auto_capvols; | ||
5406 | spec->capsws = spec->auto_capvols; | ||
5407 | spec->num_caps = spec->auto_adc_cnt; | ||
5408 | spec->mux_nids = spec->auto_mux_nids; | ||
5409 | spec->num_muxes = spec->auto_adc_cnt; | ||
5410 | spec->dmux_nids = spec->auto_dmux_nids; | ||
5411 | spec->num_dmuxes = spec->auto_adc_cnt; | ||
5412 | spec->dmic_nids = spec->auto_dmic_nids; | ||
5413 | spec->num_dmics = spec->auto_dmic_cnt; | ||
5414 | } | ||
5415 | |||
5381 | static int patch_stac92hd83xxx(struct hda_codec *codec) | 5416 | static int patch_stac92hd83xxx(struct hda_codec *codec) |
5382 | { | 5417 | { |
5383 | struct sigmatel_spec *spec; | 5418 | struct sigmatel_spec *spec; |
@@ -5399,26 +5434,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
5399 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); | 5434 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); |
5400 | codec->no_trigger_sense = 1; | 5435 | codec->no_trigger_sense = 1; |
5401 | codec->spec = spec; | 5436 | codec->spec = spec; |
5437 | |||
5438 | stac92hd8x_fill_auto_spec(codec); | ||
5439 | |||
5402 | spec->linear_tone_beep = 0; | 5440 | spec->linear_tone_beep = 0; |
5403 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 5441 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; |
5404 | spec->digbeep_nid = 0x21; | 5442 | spec->digbeep_nid = 0x21; |
5405 | spec->dmic_nids = stac92hd83xxx_dmic_nids; | ||
5406 | spec->dmux_nids = stac92hd83xxx_mux_nids; | ||
5407 | spec->mux_nids = stac92hd83xxx_mux_nids; | ||
5408 | spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); | ||
5409 | spec->adc_nids = stac92hd83xxx_adc_nids; | ||
5410 | spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids); | ||
5411 | spec->pwr_nids = stac92hd83xxx_pwr_nids; | 5443 | spec->pwr_nids = stac92hd83xxx_pwr_nids; |
5412 | spec->pwr_mapping = stac92hd83xxx_pwr_mapping; | 5444 | spec->pwr_mapping = stac92hd83xxx_pwr_mapping; |
5413 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); | 5445 | spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids); |
5414 | spec->multiout.dac_nids = spec->dac_nids; | 5446 | spec->multiout.dac_nids = spec->dac_nids; |
5415 | |||
5416 | spec->init = stac92hd83xxx_core_init; | 5447 | spec->init = stac92hd83xxx_core_init; |
5417 | spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids); | ||
5418 | spec->pin_nids = stac92hd83xxx_pin_nids; | ||
5419 | spec->num_caps = STAC92HD83XXX_NUM_CAPS; | ||
5420 | spec->capvols = stac92hd83xxx_capvols; | ||
5421 | spec->capsws = stac92hd83xxx_capsws; | ||
5422 | 5448 | ||
5423 | spec->board_config = snd_hda_check_board_config(codec, | 5449 | spec->board_config = snd_hda_check_board_config(codec, |
5424 | STAC_92HD83XXX_MODELS, | 5450 | STAC_92HD83XXX_MODELS, |
@@ -5436,28 +5462,11 @@ again: | |||
5436 | case 0x111d76d1: | 5462 | case 0x111d76d1: |
5437 | case 0x111d76d9: | 5463 | case 0x111d76d9: |
5438 | case 0x111d76e5: | 5464 | case 0x111d76e5: |
5439 | spec->dmic_nids = stac92hd87b_dmic_nids; | ||
5440 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
5441 | stac92hd87b_dmic_nids, | ||
5442 | STAC92HD87B_NUM_DMICS); | ||
5443 | spec->num_pins = ARRAY_SIZE(stac92hd87xxx_pin_nids); | ||
5444 | spec->pin_nids = stac92hd87xxx_pin_nids; | ||
5445 | spec->mono_nid = 0; | ||
5446 | spec->num_pwrs = 0; | ||
5447 | break; | ||
5448 | case 0x111d7666: | 5465 | case 0x111d7666: |
5449 | case 0x111d7667: | 5466 | case 0x111d7667: |
5450 | case 0x111d7668: | 5467 | case 0x111d7668: |
5451 | case 0x111d7669: | 5468 | case 0x111d7669: |
5452 | case 0x111d76e3: | 5469 | case 0x111d76e3: |
5453 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
5454 | stac92hd88xxx_dmic_nids, | ||
5455 | STAC92HD88XXX_NUM_DMICS); | ||
5456 | spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids); | ||
5457 | spec->pin_nids = stac92hd88xxx_pin_nids; | ||
5458 | spec->mono_nid = 0; | ||
5459 | spec->num_pwrs = 0; | ||
5460 | break; | ||
5461 | case 0x111d7604: | 5470 | case 0x111d7604: |
5462 | case 0x111d76d4: | 5471 | case 0x111d76d4: |
5463 | case 0x111d7605: | 5472 | case 0x111d7605: |
@@ -5466,9 +5475,6 @@ again: | |||
5466 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) | 5475 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) |
5467 | break; | 5476 | break; |
5468 | spec->num_pwrs = 0; | 5477 | spec->num_pwrs = 0; |
5469 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
5470 | stac92hd83xxx_dmic_nids, | ||
5471 | STAC92HD83XXX_NUM_DMICS); | ||
5472 | break; | 5478 | break; |
5473 | } | 5479 | } |
5474 | 5480 | ||
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index 13cec1e5ced9..2ae8d29500a8 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
@@ -341,9 +341,9 @@ static int snd_intel8x0m_codec_semaphore(struct intel8x0m *chip, unsigned int co | |||
341 | return -EBUSY; | 341 | return -EBUSY; |
342 | } | 342 | } |
343 | 343 | ||
344 | static void snd_intel8x0_codec_write(struct snd_ac97 *ac97, | 344 | static void snd_intel8x0m_codec_write(struct snd_ac97 *ac97, |
345 | unsigned short reg, | 345 | unsigned short reg, |
346 | unsigned short val) | 346 | unsigned short val) |
347 | { | 347 | { |
348 | struct intel8x0m *chip = ac97->private_data; | 348 | struct intel8x0m *chip = ac97->private_data; |
349 | 349 | ||
@@ -354,8 +354,8 @@ static void snd_intel8x0_codec_write(struct snd_ac97 *ac97, | |||
354 | iaputword(chip, reg + ac97->num * 0x80, val); | 354 | iaputword(chip, reg + ac97->num * 0x80, val); |
355 | } | 355 | } |
356 | 356 | ||
357 | static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, | 357 | static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97, |
358 | unsigned short reg) | 358 | unsigned short reg) |
359 | { | 359 | { |
360 | struct intel8x0m *chip = ac97->private_data; | 360 | struct intel8x0m *chip = ac97->private_data; |
361 | unsigned short res; | 361 | unsigned short res; |
@@ -385,7 +385,7 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97, | |||
385 | /* | 385 | /* |
386 | * DMA I/O | 386 | * DMA I/O |
387 | */ | 387 | */ |
388 | static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev) | 388 | static void snd_intel8x0m_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev) |
389 | { | 389 | { |
390 | int idx; | 390 | int idx; |
391 | u32 *bdbar = ichdev->bdbar; | 391 | u32 *bdbar = ichdev->bdbar; |
@@ -437,7 +437,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ic | |||
437 | * Interrupt handler | 437 | * Interrupt handler |
438 | */ | 438 | */ |
439 | 439 | ||
440 | static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ichdev) | 440 | static inline void snd_intel8x0m_update(struct intel8x0m *chip, struct ichdev *ichdev) |
441 | { | 441 | { |
442 | unsigned long port = ichdev->reg_offset; | 442 | unsigned long port = ichdev->reg_offset; |
443 | int civ, i, step; | 443 | int civ, i, step; |
@@ -489,7 +489,7 @@ static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ic | |||
489 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); | 489 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); |
490 | } | 490 | } |
491 | 491 | ||
492 | static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id) | 492 | static irqreturn_t snd_intel8x0m_interrupt(int irq, void *dev_id) |
493 | { | 493 | { |
494 | struct intel8x0m *chip = dev_id; | 494 | struct intel8x0m *chip = dev_id; |
495 | struct ichdev *ichdev; | 495 | struct ichdev *ichdev; |
@@ -512,7 +512,7 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id) | |||
512 | for (i = 0; i < chip->bdbars_count; i++) { | 512 | for (i = 0; i < chip->bdbars_count; i++) { |
513 | ichdev = &chip->ichd[i]; | 513 | ichdev = &chip->ichd[i]; |
514 | if (status & ichdev->int_sta_mask) | 514 | if (status & ichdev->int_sta_mask) |
515 | snd_intel8x0_update(chip, ichdev); | 515 | snd_intel8x0m_update(chip, ichdev); |
516 | } | 516 | } |
517 | 517 | ||
518 | /* ack them */ | 518 | /* ack them */ |
@@ -526,7 +526,7 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id) | |||
526 | * PCM part | 526 | * PCM part |
527 | */ | 527 | */ |
528 | 528 | ||
529 | static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 529 | static int snd_intel8x0m_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
530 | { | 530 | { |
531 | struct intel8x0m *chip = snd_pcm_substream_chip(substream); | 531 | struct intel8x0m *chip = snd_pcm_substream_chip(substream); |
532 | struct ichdev *ichdev = get_ichdev(substream); | 532 | struct ichdev *ichdev = get_ichdev(substream); |
@@ -561,18 +561,18 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd | |||
561 | return 0; | 561 | return 0; |
562 | } | 562 | } |
563 | 563 | ||
564 | static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream, | 564 | static int snd_intel8x0m_hw_params(struct snd_pcm_substream *substream, |
565 | struct snd_pcm_hw_params *hw_params) | 565 | struct snd_pcm_hw_params *hw_params) |
566 | { | 566 | { |
567 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 567 | return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
568 | } | 568 | } |
569 | 569 | ||
570 | static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream) | 570 | static int snd_intel8x0m_hw_free(struct snd_pcm_substream *substream) |
571 | { | 571 | { |
572 | return snd_pcm_lib_free_pages(substream); | 572 | return snd_pcm_lib_free_pages(substream); |
573 | } | 573 | } |
574 | 574 | ||
575 | static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *substream) | 575 | static snd_pcm_uframes_t snd_intel8x0m_pcm_pointer(struct snd_pcm_substream *substream) |
576 | { | 576 | { |
577 | struct intel8x0m *chip = snd_pcm_substream_chip(substream); | 577 | struct intel8x0m *chip = snd_pcm_substream_chip(substream); |
578 | struct ichdev *ichdev = get_ichdev(substream); | 578 | struct ichdev *ichdev = get_ichdev(substream); |
@@ -600,7 +600,7 @@ static int snd_intel8x0m_pcm_prepare(struct snd_pcm_substream *substream) | |||
600 | ichdev->fragsize = snd_pcm_lib_period_bytes(substream); | 600 | ichdev->fragsize = snd_pcm_lib_period_bytes(substream); |
601 | snd_ac97_write(ichdev->ac97, AC97_LINE1_RATE, runtime->rate); | 601 | snd_ac97_write(ichdev->ac97, AC97_LINE1_RATE, runtime->rate); |
602 | snd_ac97_write(ichdev->ac97, AC97_LINE1_LEVEL, 0); | 602 | snd_ac97_write(ichdev->ac97, AC97_LINE1_LEVEL, 0); |
603 | snd_intel8x0_setup_periods(chip, ichdev); | 603 | snd_intel8x0m_setup_periods(chip, ichdev); |
604 | return 0; | 604 | return 0; |
605 | } | 605 | } |
606 | 606 | ||
@@ -682,22 +682,22 @@ static struct snd_pcm_ops snd_intel8x0m_playback_ops = { | |||
682 | .open = snd_intel8x0m_playback_open, | 682 | .open = snd_intel8x0m_playback_open, |
683 | .close = snd_intel8x0m_playback_close, | 683 | .close = snd_intel8x0m_playback_close, |
684 | .ioctl = snd_pcm_lib_ioctl, | 684 | .ioctl = snd_pcm_lib_ioctl, |
685 | .hw_params = snd_intel8x0_hw_params, | 685 | .hw_params = snd_intel8x0m_hw_params, |
686 | .hw_free = snd_intel8x0_hw_free, | 686 | .hw_free = snd_intel8x0m_hw_free, |
687 | .prepare = snd_intel8x0m_pcm_prepare, | 687 | .prepare = snd_intel8x0m_pcm_prepare, |
688 | .trigger = snd_intel8x0_pcm_trigger, | 688 | .trigger = snd_intel8x0m_pcm_trigger, |
689 | .pointer = snd_intel8x0_pcm_pointer, | 689 | .pointer = snd_intel8x0m_pcm_pointer, |
690 | }; | 690 | }; |
691 | 691 | ||
692 | static struct snd_pcm_ops snd_intel8x0m_capture_ops = { | 692 | static struct snd_pcm_ops snd_intel8x0m_capture_ops = { |
693 | .open = snd_intel8x0m_capture_open, | 693 | .open = snd_intel8x0m_capture_open, |
694 | .close = snd_intel8x0m_capture_close, | 694 | .close = snd_intel8x0m_capture_close, |
695 | .ioctl = snd_pcm_lib_ioctl, | 695 | .ioctl = snd_pcm_lib_ioctl, |
696 | .hw_params = snd_intel8x0_hw_params, | 696 | .hw_params = snd_intel8x0m_hw_params, |
697 | .hw_free = snd_intel8x0_hw_free, | 697 | .hw_free = snd_intel8x0m_hw_free, |
698 | .prepare = snd_intel8x0m_pcm_prepare, | 698 | .prepare = snd_intel8x0m_pcm_prepare, |
699 | .trigger = snd_intel8x0_pcm_trigger, | 699 | .trigger = snd_intel8x0m_pcm_trigger, |
700 | .pointer = snd_intel8x0_pcm_pointer, | 700 | .pointer = snd_intel8x0m_pcm_pointer, |
701 | }; | 701 | }; |
702 | 702 | ||
703 | 703 | ||
@@ -710,7 +710,7 @@ struct ich_pcm_table { | |||
710 | int ac97_idx; | 710 | int ac97_idx; |
711 | }; | 711 | }; |
712 | 712 | ||
713 | static int __devinit snd_intel8x0_pcm1(struct intel8x0m *chip, int device, | 713 | static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device, |
714 | struct ich_pcm_table *rec) | 714 | struct ich_pcm_table *rec) |
715 | { | 715 | { |
716 | struct snd_pcm *pcm; | 716 | struct snd_pcm *pcm; |
@@ -759,7 +759,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = { | |||
759 | }, | 759 | }, |
760 | }; | 760 | }; |
761 | 761 | ||
762 | static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip) | 762 | static int __devinit snd_intel8x0m_pcm(struct intel8x0m *chip) |
763 | { | 763 | { |
764 | int i, tblsize, device, err; | 764 | int i, tblsize, device, err; |
765 | struct ich_pcm_table *tbl, *rec; | 765 | struct ich_pcm_table *tbl, *rec; |
@@ -791,7 +791,7 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip) | |||
791 | if (! chip->ichd[rec->ac97_idx].ac97) | 791 | if (! chip->ichd[rec->ac97_idx].ac97) |
792 | continue; | 792 | continue; |
793 | } | 793 | } |
794 | err = snd_intel8x0_pcm1(chip, device, rec); | 794 | err = snd_intel8x0m_pcm1(chip, device, rec); |
795 | if (err < 0) | 795 | if (err < 0) |
796 | return err; | 796 | return err; |
797 | device++; | 797 | device++; |
@@ -806,20 +806,20 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip) | |||
806 | * Mixer part | 806 | * Mixer part |
807 | */ | 807 | */ |
808 | 808 | ||
809 | static void snd_intel8x0_mixer_free_ac97_bus(struct snd_ac97_bus *bus) | 809 | static void snd_intel8x0m_mixer_free_ac97_bus(struct snd_ac97_bus *bus) |
810 | { | 810 | { |
811 | struct intel8x0m *chip = bus->private_data; | 811 | struct intel8x0m *chip = bus->private_data; |
812 | chip->ac97_bus = NULL; | 812 | chip->ac97_bus = NULL; |
813 | } | 813 | } |
814 | 814 | ||
815 | static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97) | 815 | static void snd_intel8x0m_mixer_free_ac97(struct snd_ac97 *ac97) |
816 | { | 816 | { |
817 | struct intel8x0m *chip = ac97->private_data; | 817 | struct intel8x0m *chip = ac97->private_data; |
818 | chip->ac97 = NULL; | 818 | chip->ac97 = NULL; |
819 | } | 819 | } |
820 | 820 | ||
821 | 821 | ||
822 | static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock) | 822 | static int __devinit snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock) |
823 | { | 823 | { |
824 | struct snd_ac97_bus *pbus; | 824 | struct snd_ac97_bus *pbus; |
825 | struct snd_ac97_template ac97; | 825 | struct snd_ac97_template ac97; |
@@ -827,22 +827,22 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock) | |||
827 | int err; | 827 | int err; |
828 | unsigned int glob_sta = 0; | 828 | unsigned int glob_sta = 0; |
829 | static struct snd_ac97_bus_ops ops = { | 829 | static struct snd_ac97_bus_ops ops = { |
830 | .write = snd_intel8x0_codec_write, | 830 | .write = snd_intel8x0m_codec_write, |
831 | .read = snd_intel8x0_codec_read, | 831 | .read = snd_intel8x0m_codec_read, |
832 | }; | 832 | }; |
833 | 833 | ||
834 | chip->in_ac97_init = 1; | 834 | chip->in_ac97_init = 1; |
835 | 835 | ||
836 | memset(&ac97, 0, sizeof(ac97)); | 836 | memset(&ac97, 0, sizeof(ac97)); |
837 | ac97.private_data = chip; | 837 | ac97.private_data = chip; |
838 | ac97.private_free = snd_intel8x0_mixer_free_ac97; | 838 | ac97.private_free = snd_intel8x0m_mixer_free_ac97; |
839 | ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; | 839 | ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE; |
840 | 840 | ||
841 | glob_sta = igetdword(chip, ICHREG(GLOB_STA)); | 841 | glob_sta = igetdword(chip, ICHREG(GLOB_STA)); |
842 | 842 | ||
843 | if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) | 843 | if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0) |
844 | goto __err; | 844 | goto __err; |
845 | pbus->private_free = snd_intel8x0_mixer_free_ac97_bus; | 845 | pbus->private_free = snd_intel8x0m_mixer_free_ac97_bus; |
846 | if (ac97_clock >= 8000 && ac97_clock <= 48000) | 846 | if (ac97_clock >= 8000 && ac97_clock <= 48000) |
847 | pbus->clock = ac97_clock; | 847 | pbus->clock = ac97_clock; |
848 | chip->ac97_bus = pbus; | 848 | chip->ac97_bus = pbus; |
@@ -894,7 +894,8 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing) | |||
894 | /* finish cold or do warm reset */ | 894 | /* finish cold or do warm reset */ |
895 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; | 895 | cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; |
896 | iputdword(chip, ICHREG(GLOB_CNT), cnt); | 896 | iputdword(chip, ICHREG(GLOB_CNT), cnt); |
897 | end_time = (jiffies + (HZ / 4)) + 1; | 897 | usleep_range(500, 1000); /* give warm reset some time */ |
898 | end_time = jiffies + HZ / 4; | ||
898 | do { | 899 | do { |
899 | if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) | 900 | if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0) |
900 | goto __ok; | 901 | goto __ok; |
@@ -959,7 +960,7 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing) | |||
959 | return 0; | 960 | return 0; |
960 | } | 961 | } |
961 | 962 | ||
962 | static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing) | 963 | static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing) |
963 | { | 964 | { |
964 | unsigned int i; | 965 | unsigned int i; |
965 | int err; | 966 | int err; |
@@ -980,7 +981,7 @@ static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing) | |||
980 | return 0; | 981 | return 0; |
981 | } | 982 | } |
982 | 983 | ||
983 | static int snd_intel8x0_free(struct intel8x0m *chip) | 984 | static int snd_intel8x0m_free(struct intel8x0m *chip) |
984 | { | 985 | { |
985 | unsigned int i; | 986 | unsigned int i; |
986 | 987 | ||
@@ -1045,7 +1046,7 @@ static int intel8x0m_resume(struct pci_dev *pci) | |||
1045 | return -EIO; | 1046 | return -EIO; |
1046 | } | 1047 | } |
1047 | pci_set_master(pci); | 1048 | pci_set_master(pci); |
1048 | if (request_irq(pci->irq, snd_intel8x0_interrupt, | 1049 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, |
1049 | IRQF_SHARED, card->shortname, chip)) { | 1050 | IRQF_SHARED, card->shortname, chip)) { |
1050 | printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " | 1051 | printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, " |
1051 | "disabling device\n", pci->irq); | 1052 | "disabling device\n", pci->irq); |
@@ -1053,7 +1054,7 @@ static int intel8x0m_resume(struct pci_dev *pci) | |||
1053 | return -EIO; | 1054 | return -EIO; |
1054 | } | 1055 | } |
1055 | chip->irq = pci->irq; | 1056 | chip->irq = pci->irq; |
1056 | snd_intel8x0_chip_init(chip, 0); | 1057 | snd_intel8x0m_chip_init(chip, 0); |
1057 | snd_ac97_resume(chip->ac97); | 1058 | snd_ac97_resume(chip->ac97); |
1058 | 1059 | ||
1059 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 1060 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
@@ -1094,10 +1095,10 @@ static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip) | |||
1094 | #endif /* CONFIG_PROC_FS */ | 1095 | #endif /* CONFIG_PROC_FS */ |
1095 | 1096 | ||
1096 | 1097 | ||
1097 | static int snd_intel8x0_dev_free(struct snd_device *device) | 1098 | static int snd_intel8x0m_dev_free(struct snd_device *device) |
1098 | { | 1099 | { |
1099 | struct intel8x0m *chip = device->device_data; | 1100 | struct intel8x0m *chip = device->device_data; |
1100 | return snd_intel8x0_free(chip); | 1101 | return snd_intel8x0m_free(chip); |
1101 | } | 1102 | } |
1102 | 1103 | ||
1103 | struct ich_reg_info { | 1104 | struct ich_reg_info { |
@@ -1108,7 +1109,7 @@ struct ich_reg_info { | |||
1108 | static int __devinit snd_intel8x0m_create(struct snd_card *card, | 1109 | static int __devinit snd_intel8x0m_create(struct snd_card *card, |
1109 | struct pci_dev *pci, | 1110 | struct pci_dev *pci, |
1110 | unsigned long device_type, | 1111 | unsigned long device_type, |
1111 | struct intel8x0m ** r_intel8x0) | 1112 | struct intel8x0m **r_intel8x0m) |
1112 | { | 1113 | { |
1113 | struct intel8x0m *chip; | 1114 | struct intel8x0m *chip; |
1114 | int err; | 1115 | int err; |
@@ -1116,7 +1117,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, | |||
1116 | unsigned int int_sta_masks; | 1117 | unsigned int int_sta_masks; |
1117 | struct ichdev *ichdev; | 1118 | struct ichdev *ichdev; |
1118 | static struct snd_device_ops ops = { | 1119 | static struct snd_device_ops ops = { |
1119 | .dev_free = snd_intel8x0_dev_free, | 1120 | .dev_free = snd_intel8x0m_dev_free, |
1120 | }; | 1121 | }; |
1121 | static struct ich_reg_info intel_regs[2] = { | 1122 | static struct ich_reg_info intel_regs[2] = { |
1122 | { ICH_MIINT, 0 }, | 1123 | { ICH_MIINT, 0 }, |
@@ -1124,7 +1125,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, | |||
1124 | }; | 1125 | }; |
1125 | struct ich_reg_info *tbl; | 1126 | struct ich_reg_info *tbl; |
1126 | 1127 | ||
1127 | *r_intel8x0 = NULL; | 1128 | *r_intel8x0m = NULL; |
1128 | 1129 | ||
1129 | if ((err = pci_enable_device(pci)) < 0) | 1130 | if ((err = pci_enable_device(pci)) < 0) |
1130 | return err; | 1131 | return err; |
@@ -1158,7 +1159,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, | |||
1158 | chip->addr = pci_iomap(pci, 0, 0); | 1159 | chip->addr = pci_iomap(pci, 0, 0); |
1159 | if (!chip->addr) { | 1160 | if (!chip->addr) { |
1160 | snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); | 1161 | snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); |
1161 | snd_intel8x0_free(chip); | 1162 | snd_intel8x0m_free(chip); |
1162 | return -EIO; | 1163 | return -EIO; |
1163 | } | 1164 | } |
1164 | if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */ | 1165 | if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */ |
@@ -1167,15 +1168,15 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, | |||
1167 | chip->bmaddr = pci_iomap(pci, 1, 0); | 1168 | chip->bmaddr = pci_iomap(pci, 1, 0); |
1168 | if (!chip->bmaddr) { | 1169 | if (!chip->bmaddr) { |
1169 | snd_printk(KERN_ERR "Controller space ioremap problem\n"); | 1170 | snd_printk(KERN_ERR "Controller space ioremap problem\n"); |
1170 | snd_intel8x0_free(chip); | 1171 | snd_intel8x0m_free(chip); |
1171 | return -EIO; | 1172 | return -EIO; |
1172 | } | 1173 | } |
1173 | 1174 | ||
1174 | port_inited: | 1175 | port_inited: |
1175 | if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED, | 1176 | if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED, |
1176 | card->shortname, chip)) { | 1177 | card->shortname, chip)) { |
1177 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); | 1178 | snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq); |
1178 | snd_intel8x0_free(chip); | 1179 | snd_intel8x0m_free(chip); |
1179 | return -EBUSY; | 1180 | return -EBUSY; |
1180 | } | 1181 | } |
1181 | chip->irq = pci->irq; | 1182 | chip->irq = pci->irq; |
@@ -1210,7 +1211,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, | |||
1210 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | 1211 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), |
1211 | chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, | 1212 | chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, |
1212 | &chip->bdbars) < 0) { | 1213 | &chip->bdbars) < 0) { |
1213 | snd_intel8x0_free(chip); | 1214 | snd_intel8x0m_free(chip); |
1214 | return -ENOMEM; | 1215 | return -ENOMEM; |
1215 | } | 1216 | } |
1216 | /* tables must be aligned to 8 bytes here, but the kernel pages | 1217 | /* tables must be aligned to 8 bytes here, but the kernel pages |
@@ -1225,19 +1226,19 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card, | |||
1225 | chip->int_sta_reg = ICH_REG_GLOB_STA; | 1226 | chip->int_sta_reg = ICH_REG_GLOB_STA; |
1226 | chip->int_sta_mask = int_sta_masks; | 1227 | chip->int_sta_mask = int_sta_masks; |
1227 | 1228 | ||
1228 | if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) { | 1229 | if ((err = snd_intel8x0m_chip_init(chip, 1)) < 0) { |
1229 | snd_intel8x0_free(chip); | 1230 | snd_intel8x0m_free(chip); |
1230 | return err; | 1231 | return err; |
1231 | } | 1232 | } |
1232 | 1233 | ||
1233 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { | 1234 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { |
1234 | snd_intel8x0_free(chip); | 1235 | snd_intel8x0m_free(chip); |
1235 | return err; | 1236 | return err; |
1236 | } | 1237 | } |
1237 | 1238 | ||
1238 | snd_card_set_dev(card, &pci->dev); | 1239 | snd_card_set_dev(card, &pci->dev); |
1239 | 1240 | ||
1240 | *r_intel8x0 = chip; | 1241 | *r_intel8x0m = chip; |
1241 | return 0; | 1242 | return 0; |
1242 | } | 1243 | } |
1243 | 1244 | ||
@@ -1295,11 +1296,11 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, | |||
1295 | } | 1296 | } |
1296 | card->private_data = chip; | 1297 | card->private_data = chip; |
1297 | 1298 | ||
1298 | if ((err = snd_intel8x0_mixer(chip, ac97_clock)) < 0) { | 1299 | if ((err = snd_intel8x0m_mixer(chip, ac97_clock)) < 0) { |
1299 | snd_card_free(card); | 1300 | snd_card_free(card); |
1300 | return err; | 1301 | return err; |
1301 | } | 1302 | } |
1302 | if ((err = snd_intel8x0_pcm(chip)) < 0) { | 1303 | if ((err = snd_intel8x0m_pcm(chip)) < 0) { |
1303 | snd_card_free(card); | 1304 | snd_card_free(card); |
1304 | return err; | 1305 | return err; |
1305 | } | 1306 | } |
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c index f5eadfc0672a..a323eafb9e03 100644 --- a/sound/pci/rme9652/hdspm.c +++ b/sound/pci/rme9652/hdspm.c | |||
@@ -8,6 +8,21 @@ | |||
8 | * Modified 2006-06-01 for AES32 support by Remy Bruno | 8 | * Modified 2006-06-01 for AES32 support by Remy Bruno |
9 | * <remy.bruno@trinnov.com> | 9 | * <remy.bruno@trinnov.com> |
10 | * | 10 | * |
11 | * Modified 2009-04-13 for proper metering by Florian Faber | ||
12 | * <faber@faberman.de> | ||
13 | * | ||
14 | * Modified 2009-04-14 for native float support by Florian Faber | ||
15 | * <faber@faberman.de> | ||
16 | * | ||
17 | * Modified 2009-04-26 fixed bug in rms metering by Florian Faber | ||
18 | * <faber@faberman.de> | ||
19 | * | ||
20 | * Modified 2009-04-30 added hw serial number support by Florian Faber | ||
21 | * | ||
22 | * Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth | ||
23 | * | ||
24 | * Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth | ||
25 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | 26 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 27 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 28 | * the Free Software Foundation; either version 2 of the License, or |
@@ -35,6 +50,7 @@ | |||
35 | #include <sound/core.h> | 50 | #include <sound/core.h> |
36 | #include <sound/control.h> | 51 | #include <sound/control.h> |
37 | #include <sound/pcm.h> | 52 | #include <sound/pcm.h> |
53 | #include <sound/pcm_params.h> | ||
38 | #include <sound/info.h> | 54 | #include <sound/info.h> |
39 | #include <sound/asoundef.h> | 55 | #include <sound/asoundef.h> |
40 | #include <sound/rawmidi.h> | 56 | #include <sound/rawmidi.h> |
@@ -47,15 +63,6 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | |||
47 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 63 | 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 */ | 64 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */ |
49 | 65 | ||
50 | /* Disable precise pointer at start */ | ||
51 | static int precise_ptr[SNDRV_CARDS]; | ||
52 | |||
53 | /* Send all playback to line outs */ | ||
54 | static int line_outs_monitor[SNDRV_CARDS]; | ||
55 | |||
56 | /* Enable Analog Outs on Channel 63/64 by default */ | ||
57 | static int enable_monitor[SNDRV_CARDS]; | ||
58 | |||
59 | module_param_array(index, int, NULL, 0444); | 66 | module_param_array(index, int, NULL, 0444); |
60 | MODULE_PARM_DESC(index, "Index value for RME HDSPM interface."); | 67 | MODULE_PARM_DESC(index, "Index value for RME HDSPM interface."); |
61 | 68 | ||
@@ -65,42 +72,39 @@ MODULE_PARM_DESC(id, "ID string for RME HDSPM interface."); | |||
65 | module_param_array(enable, bool, NULL, 0444); | 72 | module_param_array(enable, bool, NULL, 0444); |
66 | MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards."); | 73 | MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards."); |
67 | 74 | ||
68 | module_param_array(precise_ptr, bool, NULL, 0444); | ||
69 | MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer."); | ||
70 | |||
71 | module_param_array(line_outs_monitor, bool, NULL, 0444); | ||
72 | MODULE_PARM_DESC(line_outs_monitor, | ||
73 | "Send playback streams to analog outs by default."); | ||
74 | |||
75 | module_param_array(enable_monitor, bool, NULL, 0444); | ||
76 | MODULE_PARM_DESC(enable_monitor, | ||
77 | "Enable Analog Out on Channel 63/64 by default."); | ||
78 | 75 | ||
79 | MODULE_AUTHOR | 76 | MODULE_AUTHOR |
80 | ("Winfried Ritsch <ritsch_AT_iem.at>, " | 77 | ( |
81 | "Paul Davis <paul@linuxaudiosystems.com>, " | 78 | "Winfried Ritsch <ritsch_AT_iem.at>, " |
82 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " | 79 | "Paul Davis <paul@linuxaudiosystems.com>, " |
83 | "Remy Bruno <remy.bruno@trinnov.com>"); | 80 | "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, " |
81 | "Remy Bruno <remy.bruno@trinnov.com>, " | ||
82 | "Florian Faber <faberman@linuxproaudio.org>, " | ||
83 | "Adrian Knoth <adi@drcomp.erfurt.thur.de>" | ||
84 | ); | ||
84 | MODULE_DESCRIPTION("RME HDSPM"); | 85 | MODULE_DESCRIPTION("RME HDSPM"); |
85 | MODULE_LICENSE("GPL"); | 86 | MODULE_LICENSE("GPL"); |
86 | MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | 87 | MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); |
87 | 88 | ||
88 | /* --- Write registers. --- | 89 | /* --- Write registers. --- |
89 | These are defined as byte-offsets from the iobase value. */ | 90 | These are defined as byte-offsets from the iobase value. */ |
90 | 91 | ||
92 | #define HDSPM_WR_SETTINGS 0 | ||
93 | #define HDSPM_outputBufferAddress 32 | ||
94 | #define HDSPM_inputBufferAddress 36 | ||
91 | #define HDSPM_controlRegister 64 | 95 | #define HDSPM_controlRegister 64 |
92 | #define HDSPM_interruptConfirmation 96 | 96 | #define HDSPM_interruptConfirmation 96 |
93 | #define HDSPM_control2Reg 256 /* not in specs ???????? */ | 97 | #define HDSPM_control2Reg 256 /* not in specs ???????? */ |
94 | #define HDSPM_freqReg 256 /* for AES32 */ | 98 | #define HDSPM_freqReg 256 /* for AES32 */ |
95 | #define HDSPM_midiDataOut0 352 /* just believe in old code */ | 99 | #define HDSPM_midiDataOut0 352 /* just believe in old code */ |
96 | #define HDSPM_midiDataOut1 356 | 100 | #define HDSPM_midiDataOut1 356 |
97 | #define HDSPM_eeprom_wr 384 /* for AES32 */ | 101 | #define HDSPM_eeprom_wr 384 /* for AES32 */ |
98 | 102 | ||
99 | /* DMA enable for 64 channels, only Bit 0 is relevant */ | 103 | /* DMA enable for 64 channels, only Bit 0 is relevant */ |
100 | #define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ | 104 | #define HDSPM_outputEnableBase 512 /* 512-767 input DMA */ |
101 | #define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */ | 105 | #define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */ |
102 | 106 | ||
103 | /* 16 page addresses for each of the 64 channels DMA buffer in and out | 107 | /* 16 page addresses for each of the 64 channels DMA buffer in and out |
104 | (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */ | 108 | (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */ |
105 | #define HDSPM_pageAddressBufferOut 8192 | 109 | #define HDSPM_pageAddressBufferOut 8192 |
106 | #define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4) | 110 | #define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4) |
@@ -119,22 +123,84 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
119 | #define HDSPM_statusRegister2 192 | 123 | #define HDSPM_statusRegister2 192 |
120 | #define HDSPM_timecodeRegister 128 | 124 | #define HDSPM_timecodeRegister 128 |
121 | 125 | ||
126 | /* AIO, RayDAT */ | ||
127 | #define HDSPM_RD_STATUS_0 0 | ||
128 | #define HDSPM_RD_STATUS_1 64 | ||
129 | #define HDSPM_RD_STATUS_2 128 | ||
130 | #define HDSPM_RD_STATUS_3 192 | ||
131 | |||
132 | #define HDSPM_RD_TCO 256 | ||
133 | #define HDSPM_RD_PLL_FREQ 512 | ||
134 | #define HDSPM_WR_TCO 128 | ||
135 | |||
136 | #define HDSPM_TCO1_TCO_lock 0x00000001 | ||
137 | #define HDSPM_TCO1_WCK_Input_Range_LSB 0x00000002 | ||
138 | #define HDSPM_TCO1_WCK_Input_Range_MSB 0x00000004 | ||
139 | #define HDSPM_TCO1_LTC_Input_valid 0x00000008 | ||
140 | #define HDSPM_TCO1_WCK_Input_valid 0x00000010 | ||
141 | #define HDSPM_TCO1_Video_Input_Format_NTSC 0x00000020 | ||
142 | #define HDSPM_TCO1_Video_Input_Format_PAL 0x00000040 | ||
143 | |||
144 | #define HDSPM_TCO1_set_TC 0x00000100 | ||
145 | #define HDSPM_TCO1_set_drop_frame_flag 0x00000200 | ||
146 | #define HDSPM_TCO1_LTC_Format_LSB 0x00000400 | ||
147 | #define HDSPM_TCO1_LTC_Format_MSB 0x00000800 | ||
148 | |||
149 | #define HDSPM_TCO2_TC_run 0x00010000 | ||
150 | #define HDSPM_TCO2_WCK_IO_ratio_LSB 0x00020000 | ||
151 | #define HDSPM_TCO2_WCK_IO_ratio_MSB 0x00040000 | ||
152 | #define HDSPM_TCO2_set_num_drop_frames_LSB 0x00080000 | ||
153 | #define HDSPM_TCO2_set_num_drop_frames_MSB 0x00100000 | ||
154 | #define HDSPM_TCO2_set_jam_sync 0x00200000 | ||
155 | #define HDSPM_TCO2_set_flywheel 0x00400000 | ||
156 | |||
157 | #define HDSPM_TCO2_set_01_4 0x01000000 | ||
158 | #define HDSPM_TCO2_set_pull_down 0x02000000 | ||
159 | #define HDSPM_TCO2_set_pull_up 0x04000000 | ||
160 | #define HDSPM_TCO2_set_freq 0x08000000 | ||
161 | #define HDSPM_TCO2_set_term_75R 0x10000000 | ||
162 | #define HDSPM_TCO2_set_input_LSB 0x20000000 | ||
163 | #define HDSPM_TCO2_set_input_MSB 0x40000000 | ||
164 | #define HDSPM_TCO2_set_freq_from_app 0x80000000 | ||
165 | |||
166 | |||
167 | #define HDSPM_midiDataOut0 352 | ||
168 | #define HDSPM_midiDataOut1 356 | ||
169 | #define HDSPM_midiDataOut2 368 | ||
170 | |||
122 | #define HDSPM_midiDataIn0 360 | 171 | #define HDSPM_midiDataIn0 360 |
123 | #define HDSPM_midiDataIn1 364 | 172 | #define HDSPM_midiDataIn1 364 |
173 | #define HDSPM_midiDataIn2 372 | ||
174 | #define HDSPM_midiDataIn3 376 | ||
124 | 175 | ||
125 | /* status is data bytes in MIDI-FIFO (0-128) */ | 176 | /* status is data bytes in MIDI-FIFO (0-128) */ |
126 | #define HDSPM_midiStatusOut0 384 | 177 | #define HDSPM_midiStatusOut0 384 |
127 | #define HDSPM_midiStatusOut1 388 | 178 | #define HDSPM_midiStatusOut1 388 |
128 | #define HDSPM_midiStatusIn0 392 | 179 | #define HDSPM_midiStatusOut2 400 |
129 | #define HDSPM_midiStatusIn1 396 | 180 | |
181 | #define HDSPM_midiStatusIn0 392 | ||
182 | #define HDSPM_midiStatusIn1 396 | ||
183 | #define HDSPM_midiStatusIn2 404 | ||
184 | #define HDSPM_midiStatusIn3 408 | ||
130 | 185 | ||
131 | 186 | ||
132 | /* the meters are regular i/o-mapped registers, but offset | 187 | /* the meters are regular i/o-mapped registers, but offset |
133 | considerably from the rest. the peak registers are reset | 188 | considerably from the rest. the peak registers are reset |
134 | when read; the least-significant 4 bits are full-scale counters; | 189 | when read; the least-significant 4 bits are full-scale counters; |
135 | the actual peak value is in the most-significant 24 bits. | 190 | the actual peak value is in the most-significant 24 bits. |
136 | */ | 191 | */ |
137 | #define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */ | 192 | |
193 | #define HDSPM_MADI_INPUT_PEAK 4096 | ||
194 | #define HDSPM_MADI_PLAYBACK_PEAK 4352 | ||
195 | #define HDSPM_MADI_OUTPUT_PEAK 4608 | ||
196 | |||
197 | #define HDSPM_MADI_INPUT_RMS_L 6144 | ||
198 | #define HDSPM_MADI_PLAYBACK_RMS_L 6400 | ||
199 | #define HDSPM_MADI_OUTPUT_RMS_L 6656 | ||
200 | |||
201 | #define HDSPM_MADI_INPUT_RMS_H 7168 | ||
202 | #define HDSPM_MADI_PLAYBACK_RMS_H 7424 | ||
203 | #define HDSPM_MADI_OUTPUT_RMS_H 7680 | ||
138 | 204 | ||
139 | /* --- Control Register bits --------- */ | 205 | /* --- Control Register bits --------- */ |
140 | #define HDSPM_Start (1<<0) /* start engine */ | 206 | #define HDSPM_Start (1<<0) /* start engine */ |
@@ -143,7 +209,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
143 | #define HDSPM_Latency1 (1<<2) /* where n is defined */ | 209 | #define HDSPM_Latency1 (1<<2) /* where n is defined */ |
144 | #define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */ | 210 | #define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */ |
145 | 211 | ||
146 | #define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */ | 212 | #define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Autosync */ |
213 | #define HDSPM_c0Master 0x1 /* Master clock bit in settings | ||
214 | register [RayDAT, AIO] */ | ||
147 | 215 | ||
148 | #define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */ | 216 | #define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */ |
149 | 217 | ||
@@ -157,7 +225,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
157 | 56channelMODE=0 */ /* MADI ONLY*/ | 225 | 56channelMODE=0 */ /* MADI ONLY*/ |
158 | #define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */ | 226 | #define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */ |
159 | 227 | ||
160 | #define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, | 228 | #define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, |
161 | 0=off, 1=on */ /* MADI ONLY */ | 229 | 0=off, 1=on */ /* MADI ONLY */ |
162 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ | 230 | #define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */ |
163 | 231 | ||
@@ -166,22 +234,23 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
166 | */ | 234 | */ |
167 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ | 235 | #define HDSPM_InputSelect1 (1<<15) /* should be 0 */ |
168 | 236 | ||
169 | #define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ | ||
170 | #define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */ | ||
171 | #define HDSPM_SyncRef2 (1<<13) | 237 | #define HDSPM_SyncRef2 (1<<13) |
172 | #define HDSPM_SyncRef3 (1<<25) | 238 | #define HDSPM_SyncRef3 (1<<25) |
173 | 239 | ||
174 | #define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */ | 240 | #define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */ |
175 | #define HDSPM_clr_tms (1<<19) /* clear track marker, do not use | 241 | #define HDSPM_clr_tms (1<<19) /* clear track marker, do not use |
176 | AES additional bits in | 242 | AES additional bits in |
177 | lower 5 Audiodatabits ??? */ | 243 | lower 5 Audiodatabits ??? */ |
178 | #define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */ | 244 | #define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */ |
179 | #define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */ | 245 | #define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */ |
180 | 246 | ||
181 | #define HDSPM_Midi0InterruptEnable (1<<22) | 247 | #define HDSPM_Midi0InterruptEnable 0x0400000 |
182 | #define HDSPM_Midi1InterruptEnable (1<<23) | 248 | #define HDSPM_Midi1InterruptEnable 0x0800000 |
249 | #define HDSPM_Midi2InterruptEnable 0x0200000 | ||
250 | #define HDSPM_Midi3InterruptEnable 0x4000000 | ||
183 | 251 | ||
184 | #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ | 252 | #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ |
253 | #define HDSPe_FLOAT_FORMAT 0x2000000 | ||
185 | 254 | ||
186 | #define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */ | 255 | #define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */ |
187 | #define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */ | 256 | #define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */ |
@@ -198,11 +267,18 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
198 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) | 267 | #define HDSPM_InputCoaxial (HDSPM_InputSelect0) |
199 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ | 268 | #define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|\ |
200 | HDSPM_SyncRef2|HDSPM_SyncRef3) | 269 | HDSPM_SyncRef2|HDSPM_SyncRef3) |
201 | #define HDSPM_SyncRef_Word 0 | ||
202 | #define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) | ||
203 | 270 | ||
204 | #define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */ | 271 | #define HDSPM_c0_SyncRef0 0x2 |
205 | #define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */ | 272 | #define HDSPM_c0_SyncRef1 0x4 |
273 | #define HDSPM_c0_SyncRef2 0x8 | ||
274 | #define HDSPM_c0_SyncRef3 0x10 | ||
275 | #define HDSPM_c0_SyncRefMask (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\ | ||
276 | HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3) | ||
277 | |||
278 | #define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */ | ||
279 | #define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */ | ||
280 | #define HDSPM_SYNC_FROM_TCO 2 | ||
281 | #define HDSPM_SYNC_FROM_SYNC_IN 3 | ||
206 | 282 | ||
207 | #define HDSPM_Frequency32KHz HDSPM_Frequency0 | 283 | #define HDSPM_Frequency32KHz HDSPM_Frequency0 |
208 | #define HDSPM_Frequency44_1KHz HDSPM_Frequency1 | 284 | #define HDSPM_Frequency44_1KHz HDSPM_Frequency1 |
@@ -216,17 +292,6 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
216 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ | 292 | #define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|\ |
217 | HDSPM_Frequency0) | 293 | HDSPM_Frequency0) |
218 | 294 | ||
219 | /* --- for internal discrimination */ | ||
220 | #define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ | ||
221 | #define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1 | ||
222 | #define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2 | ||
223 | #define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3 | ||
224 | #define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4 | ||
225 | #define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5 | ||
226 | #define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6 | ||
227 | #define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7 | ||
228 | #define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8 | ||
229 | #define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9 | ||
230 | 295 | ||
231 | /* Synccheck Status */ | 296 | /* Synccheck Status */ |
232 | #define HDSPM_SYNC_CHECK_NO_LOCK 0 | 297 | #define HDSPM_SYNC_CHECK_NO_LOCK 0 |
@@ -236,14 +301,16 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
236 | /* AutoSync References - used by "autosync_ref" control switch */ | 301 | /* AutoSync References - used by "autosync_ref" control switch */ |
237 | #define HDSPM_AUTOSYNC_FROM_WORD 0 | 302 | #define HDSPM_AUTOSYNC_FROM_WORD 0 |
238 | #define HDSPM_AUTOSYNC_FROM_MADI 1 | 303 | #define HDSPM_AUTOSYNC_FROM_MADI 1 |
239 | #define HDSPM_AUTOSYNC_FROM_NONE 2 | 304 | #define HDSPM_AUTOSYNC_FROM_TCO 2 |
305 | #define HDSPM_AUTOSYNC_FROM_SYNC_IN 3 | ||
306 | #define HDSPM_AUTOSYNC_FROM_NONE 4 | ||
240 | 307 | ||
241 | /* Possible sources of MADI input */ | 308 | /* Possible sources of MADI input */ |
242 | #define HDSPM_OPTICAL 0 /* optical */ | 309 | #define HDSPM_OPTICAL 0 /* optical */ |
243 | #define HDSPM_COAXIAL 1 /* BNC */ | 310 | #define HDSPM_COAXIAL 1 /* BNC */ |
244 | 311 | ||
245 | #define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask) | 312 | #define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask) |
246 | #define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1) | 313 | #define hdspm_decode_latency(x) ((((x) & HDSPM_LatencyMask)>>1)) |
247 | 314 | ||
248 | #define hdspm_encode_in(x) (((x)&0x3)<<14) | 315 | #define hdspm_encode_in(x) (((x)&0x3)<<14) |
249 | #define hdspm_decode_in(x) (((x)>>14)&0x3) | 316 | #define hdspm_decode_in(x) (((x)>>14)&0x3) |
@@ -270,13 +337,21 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
270 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 | 337 | #define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 |
271 | * (like inp0) | 338 | * (like inp0) |
272 | */ | 339 | */ |
340 | |||
273 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ | 341 | #define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */ |
342 | #define HDSPM_madiSync (1<<18) /* MADI is in sync */ | ||
343 | |||
344 | #define HDSPM_tcoLock 0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */ | ||
345 | #define HDSPM_tcoSync 0x10000000 /* Optional TCO sync status */ | ||
346 | |||
347 | #define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */ | ||
348 | #define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */ | ||
274 | 349 | ||
275 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ | 350 | #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */ |
276 | /* since 64byte accurate last 6 bits | 351 | /* since 64byte accurate, last 6 bits are not used */ |
277 | are not used */ | 352 | |
353 | |||
278 | 354 | ||
279 | #define HDSPM_madiSync (1<<18) /* MADI is in sync */ | ||
280 | #define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */ | 355 | #define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */ |
281 | 356 | ||
282 | #define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */ | 357 | #define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */ |
@@ -287,8 +362,19 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
287 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with | 362 | #define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with |
288 | * Interrupt | 363 | * Interrupt |
289 | */ | 364 | */ |
290 | #define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */ | 365 | #define HDSPM_tco_detect 0x08000000 |
291 | #define HDSPM_midi1IRQPending (1<<31) /* and aktiv */ | 366 | #define HDSPM_tco_lock 0x20000000 |
367 | |||
368 | #define HDSPM_s2_tco_detect 0x00000040 | ||
369 | #define HDSPM_s2_AEBO_D 0x00000080 | ||
370 | #define HDSPM_s2_AEBI_D 0x00000100 | ||
371 | |||
372 | |||
373 | #define HDSPM_midi0IRQPending 0x40000000 | ||
374 | #define HDSPM_midi1IRQPending 0x80000000 | ||
375 | #define HDSPM_midi2IRQPending 0x20000000 | ||
376 | #define HDSPM_midi2IRQPendingAES 0x00000020 | ||
377 | #define HDSPM_midi3IRQPending 0x00200000 | ||
292 | 378 | ||
293 | /* --- status bit helpers */ | 379 | /* --- status bit helpers */ |
294 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ | 380 | #define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|\ |
@@ -317,7 +403,10 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
317 | #define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ | 403 | #define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */ |
318 | /* missing Bit for 111=128, 1000=176.4, 1001=192 */ | 404 | /* missing Bit for 111=128, 1000=176.4, 1001=192 */ |
319 | 405 | ||
320 | #define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */ | 406 | #define HDSPM_SyncRef0 0x10000 /* Sync Reference */ |
407 | #define HDSPM_SyncRef1 0x20000 | ||
408 | |||
409 | #define HDSPM_SelSyncRef0 (1<<8) /* AutoSync Source */ | ||
321 | #define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */ | 410 | #define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */ |
322 | #define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */ | 411 | #define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */ |
323 | 412 | ||
@@ -331,11 +420,19 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
331 | #define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) | 420 | #define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2) |
332 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) | 421 | #define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2) |
333 | 422 | ||
423 | #define HDSPM_status1_F_0 0x0400000 | ||
424 | #define HDSPM_status1_F_1 0x0800000 | ||
425 | #define HDSPM_status1_F_2 0x1000000 | ||
426 | #define HDSPM_status1_F_3 0x2000000 | ||
427 | #define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3) | ||
428 | |||
334 | 429 | ||
335 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ | 430 | #define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
336 | HDSPM_SelSyncRef2) | 431 | HDSPM_SelSyncRef2) |
337 | #define HDSPM_SelSyncRef_WORD 0 | 432 | #define HDSPM_SelSyncRef_WORD 0 |
338 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) | 433 | #define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) |
434 | #define HDSPM_SelSyncRef_TCO (HDSPM_SelSyncRef1) | ||
435 | #define HDSPM_SelSyncRef_SyncIn (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1) | ||
339 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ | 436 | #define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\ |
340 | HDSPM_SelSyncRef2) | 437 | HDSPM_SelSyncRef2) |
341 | 438 | ||
@@ -345,7 +442,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
345 | /* status */ | 442 | /* status */ |
346 | #define HDSPM_AES32_wcLock 0x0200000 | 443 | #define HDSPM_AES32_wcLock 0x0200000 |
347 | #define HDSPM_AES32_wcFreq_bit 22 | 444 | #define HDSPM_AES32_wcFreq_bit 22 |
348 | /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function | 445 | /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function |
349 | HDSPM_bit2freq */ | 446 | HDSPM_bit2freq */ |
350 | #define HDSPM_AES32_syncref_bit 16 | 447 | #define HDSPM_AES32_syncref_bit 16 |
351 | /* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */ | 448 | /* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */ |
@@ -398,28 +495,348 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); | |||
398 | #define MADI_DS_CHANNELS 32 | 495 | #define MADI_DS_CHANNELS 32 |
399 | #define MADI_QS_CHANNELS 16 | 496 | #define MADI_QS_CHANNELS 16 |
400 | 497 | ||
498 | #define RAYDAT_SS_CHANNELS 36 | ||
499 | #define RAYDAT_DS_CHANNELS 20 | ||
500 | #define RAYDAT_QS_CHANNELS 12 | ||
501 | |||
502 | #define AIO_IN_SS_CHANNELS 14 | ||
503 | #define AIO_IN_DS_CHANNELS 10 | ||
504 | #define AIO_IN_QS_CHANNELS 8 | ||
505 | #define AIO_OUT_SS_CHANNELS 16 | ||
506 | #define AIO_OUT_DS_CHANNELS 12 | ||
507 | #define AIO_OUT_QS_CHANNELS 10 | ||
508 | |||
509 | #define AES32_CHANNELS 16 | ||
510 | |||
401 | /* the size of a substream (1 mono data stream) */ | 511 | /* the size of a substream (1 mono data stream) */ |
402 | #define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024) | 512 | #define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024) |
403 | #define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES) | 513 | #define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES) |
404 | 514 | ||
405 | /* the size of the area we need to allocate for DMA transfers. the | 515 | /* the size of the area we need to allocate for DMA transfers. the |
406 | size is the same regardless of the number of channels, and | 516 | size is the same regardless of the number of channels, and |
407 | also the latency to use. | 517 | also the latency to use. |
408 | for one direction !!! | 518 | for one direction !!! |
409 | */ | 519 | */ |
410 | #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) | 520 | #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) |
411 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) | 521 | #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) |
412 | 522 | ||
413 | /* revisions >= 230 indicate AES32 card */ | 523 | /* revisions >= 230 indicate AES32 card */ |
414 | #define HDSPM_AESREVISION 230 | 524 | #define HDSPM_MADI_REV 210 |
525 | #define HDSPM_RAYDAT_REV 211 | ||
526 | #define HDSPM_AIO_REV 212 | ||
527 | #define HDSPM_MADIFACE_REV 213 | ||
528 | #define HDSPM_AES_REV 240 | ||
529 | #define HDSPM_AES32_REV 234 | ||
530 | #define HDSPM_AES32_OLD_REV 233 | ||
415 | 531 | ||
416 | /* speed factor modes */ | 532 | /* speed factor modes */ |
417 | #define HDSPM_SPEED_SINGLE 0 | 533 | #define HDSPM_SPEED_SINGLE 0 |
418 | #define HDSPM_SPEED_DOUBLE 1 | 534 | #define HDSPM_SPEED_DOUBLE 1 |
419 | #define HDSPM_SPEED_QUAD 2 | 535 | #define HDSPM_SPEED_QUAD 2 |
536 | |||
420 | /* names for speed modes */ | 537 | /* names for speed modes */ |
421 | static char *hdspm_speed_names[] = { "single", "double", "quad" }; | 538 | static char *hdspm_speed_names[] = { "single", "double", "quad" }; |
422 | 539 | ||
540 | static char *texts_autosync_aes_tco[] = { "Word Clock", | ||
541 | "AES1", "AES2", "AES3", "AES4", | ||
542 | "AES5", "AES6", "AES7", "AES8", | ||
543 | "TCO" }; | ||
544 | static char *texts_autosync_aes[] = { "Word Clock", | ||
545 | "AES1", "AES2", "AES3", "AES4", | ||
546 | "AES5", "AES6", "AES7", "AES8" }; | ||
547 | static char *texts_autosync_madi_tco[] = { "Word Clock", | ||
548 | "MADI", "TCO", "Sync In" }; | ||
549 | static char *texts_autosync_madi[] = { "Word Clock", | ||
550 | "MADI", "Sync In" }; | ||
551 | |||
552 | static char *texts_autosync_raydat_tco[] = { | ||
553 | "Word Clock", | ||
554 | "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4", | ||
555 | "AES", "SPDIF", "TCO", "Sync In" | ||
556 | }; | ||
557 | static char *texts_autosync_raydat[] = { | ||
558 | "Word Clock", | ||
559 | "ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4", | ||
560 | "AES", "SPDIF", "Sync In" | ||
561 | }; | ||
562 | static char *texts_autosync_aio_tco[] = { | ||
563 | "Word Clock", | ||
564 | "ADAT", "AES", "SPDIF", "TCO", "Sync In" | ||
565 | }; | ||
566 | static char *texts_autosync_aio[] = { "Word Clock", | ||
567 | "ADAT", "AES", "SPDIF", "Sync In" }; | ||
568 | |||
569 | static char *texts_freq[] = { | ||
570 | "No Lock", | ||
571 | "32 kHz", | ||
572 | "44.1 kHz", | ||
573 | "48 kHz", | ||
574 | "64 kHz", | ||
575 | "88.2 kHz", | ||
576 | "96 kHz", | ||
577 | "128 kHz", | ||
578 | "176.4 kHz", | ||
579 | "192 kHz" | ||
580 | }; | ||
581 | |||
582 | static char *texts_ports_madi[] = { | ||
583 | "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6", | ||
584 | "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12", | ||
585 | "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18", | ||
586 | "MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24", | ||
587 | "MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30", | ||
588 | "MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36", | ||
589 | "MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42", | ||
590 | "MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48", | ||
591 | "MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54", | ||
592 | "MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60", | ||
593 | "MADI.61", "MADI.62", "MADI.63", "MADI.64", | ||
594 | }; | ||
595 | |||
596 | |||
597 | static char *texts_ports_raydat_ss[] = { | ||
598 | "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6", | ||
599 | "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", | ||
600 | "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2", | ||
601 | "ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8", | ||
602 | "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6", | ||
603 | "ADAT4.7", "ADAT4.8", | ||
604 | "AES.L", "AES.R", | ||
605 | "SPDIF.L", "SPDIF.R" | ||
606 | }; | ||
607 | |||
608 | static char *texts_ports_raydat_ds[] = { | ||
609 | "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", | ||
610 | "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4", | ||
611 | "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4", | ||
612 | "ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", | ||
613 | "AES.L", "AES.R", | ||
614 | "SPDIF.L", "SPDIF.R" | ||
615 | }; | ||
616 | |||
617 | static char *texts_ports_raydat_qs[] = { | ||
618 | "ADAT1.1", "ADAT1.2", | ||
619 | "ADAT2.1", "ADAT2.2", | ||
620 | "ADAT3.1", "ADAT3.2", | ||
621 | "ADAT4.1", "ADAT4.2", | ||
622 | "AES.L", "AES.R", | ||
623 | "SPDIF.L", "SPDIF.R" | ||
624 | }; | ||
625 | |||
626 | |||
627 | static char *texts_ports_aio_in_ss[] = { | ||
628 | "Analogue.L", "Analogue.R", | ||
629 | "AES.L", "AES.R", | ||
630 | "SPDIF.L", "SPDIF.R", | ||
631 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6", | ||
632 | "ADAT.7", "ADAT.8" | ||
633 | }; | ||
634 | |||
635 | static char *texts_ports_aio_out_ss[] = { | ||
636 | "Analogue.L", "Analogue.R", | ||
637 | "AES.L", "AES.R", | ||
638 | "SPDIF.L", "SPDIF.R", | ||
639 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6", | ||
640 | "ADAT.7", "ADAT.8", | ||
641 | "Phone.L", "Phone.R" | ||
642 | }; | ||
643 | |||
644 | static char *texts_ports_aio_in_ds[] = { | ||
645 | "Analogue.L", "Analogue.R", | ||
646 | "AES.L", "AES.R", | ||
647 | "SPDIF.L", "SPDIF.R", | ||
648 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4" | ||
649 | }; | ||
650 | |||
651 | static char *texts_ports_aio_out_ds[] = { | ||
652 | "Analogue.L", "Analogue.R", | ||
653 | "AES.L", "AES.R", | ||
654 | "SPDIF.L", "SPDIF.R", | ||
655 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", | ||
656 | "Phone.L", "Phone.R" | ||
657 | }; | ||
658 | |||
659 | static char *texts_ports_aio_in_qs[] = { | ||
660 | "Analogue.L", "Analogue.R", | ||
661 | "AES.L", "AES.R", | ||
662 | "SPDIF.L", "SPDIF.R", | ||
663 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4" | ||
664 | }; | ||
665 | |||
666 | static char *texts_ports_aio_out_qs[] = { | ||
667 | "Analogue.L", "Analogue.R", | ||
668 | "AES.L", "AES.R", | ||
669 | "SPDIF.L", "SPDIF.R", | ||
670 | "ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", | ||
671 | "Phone.L", "Phone.R" | ||
672 | }; | ||
673 | |||
674 | static char *texts_ports_aes32[] = { | ||
675 | "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7", | ||
676 | "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14", | ||
677 | "AES.15", "AES.16" | ||
678 | }; | ||
679 | |||
680 | /* These tables map the ALSA channels 1..N to the channels that we | ||
681 | need to use in order to find the relevant channel buffer. RME | ||
682 | refers to this kind of mapping as between "the ADAT channel and | ||
683 | the DMA channel." We index it using the logical audio channel, | ||
684 | and the value is the DMA channel (i.e. channel buffer number) | ||
685 | where the data for that channel can be read/written from/to. | ||
686 | */ | ||
687 | |||
688 | static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = { | ||
689 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
690 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
691 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
692 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
693 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
694 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
695 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
696 | 56, 57, 58, 59, 60, 61, 62, 63 | ||
697 | }; | ||
698 | |||
699 | static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = { | ||
700 | 4, 5, 6, 7, 8, 9, 10, 11, /* ADAT 1 */ | ||
701 | 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */ | ||
702 | 20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */ | ||
703 | 28, 29, 30, 31, 32, 33, 34, 35, /* ADAT 4 */ | ||
704 | 0, 1, /* AES */ | ||
705 | 2, 3, /* SPDIF */ | ||
706 | -1, -1, -1, -1, | ||
707 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
708 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
709 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
710 | }; | ||
711 | |||
712 | static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = { | ||
713 | 4, 5, 6, 7, /* ADAT 1 */ | ||
714 | 8, 9, 10, 11, /* ADAT 2 */ | ||
715 | 12, 13, 14, 15, /* ADAT 3 */ | ||
716 | 16, 17, 18, 19, /* ADAT 4 */ | ||
717 | 0, 1, /* AES */ | ||
718 | 2, 3, /* SPDIF */ | ||
719 | -1, -1, -1, -1, | ||
720 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
721 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
722 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
723 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
724 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
725 | }; | ||
726 | |||
727 | static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = { | ||
728 | 4, 5, /* ADAT 1 */ | ||
729 | 6, 7, /* ADAT 2 */ | ||
730 | 8, 9, /* ADAT 3 */ | ||
731 | 10, 11, /* ADAT 4 */ | ||
732 | 0, 1, /* AES */ | ||
733 | 2, 3, /* SPDIF */ | ||
734 | -1, -1, -1, -1, | ||
735 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
736 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
737 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
738 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
739 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
740 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
741 | }; | ||
742 | |||
743 | static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = { | ||
744 | 0, 1, /* line in */ | ||
745 | 8, 9, /* aes in, */ | ||
746 | 10, 11, /* spdif in */ | ||
747 | 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT in */ | ||
748 | -1, -1, | ||
749 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
750 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
751 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
752 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
753 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
754 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
755 | }; | ||
756 | |||
757 | static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = { | ||
758 | 0, 1, /* line out */ | ||
759 | 8, 9, /* aes out */ | ||
760 | 10, 11, /* spdif out */ | ||
761 | 12, 13, 14, 15, 16, 17, 18, 19, /* ADAT out */ | ||
762 | 6, 7, /* phone out */ | ||
763 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
764 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
765 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
766 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
767 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
768 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
769 | }; | ||
770 | |||
771 | static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = { | ||
772 | 0, 1, /* line in */ | ||
773 | 8, 9, /* aes in */ | ||
774 | 10, 11, /* spdif in */ | ||
775 | 12, 14, 16, 18, /* adat in */ | ||
776 | -1, -1, -1, -1, -1, -1, | ||
777 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
778 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
779 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
780 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
781 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
782 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
783 | }; | ||
784 | |||
785 | static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = { | ||
786 | 0, 1, /* line out */ | ||
787 | 8, 9, /* aes out */ | ||
788 | 10, 11, /* spdif out */ | ||
789 | 12, 14, 16, 18, /* adat out */ | ||
790 | 6, 7, /* phone out */ | ||
791 | -1, -1, -1, -1, | ||
792 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
793 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
794 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
795 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
796 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
797 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
798 | }; | ||
799 | |||
800 | static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = { | ||
801 | 0, 1, /* line in */ | ||
802 | 8, 9, /* aes in */ | ||
803 | 10, 11, /* spdif in */ | ||
804 | 12, 16, /* adat in */ | ||
805 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
806 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
807 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
808 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
809 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
810 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
811 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
812 | }; | ||
813 | |||
814 | static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = { | ||
815 | 0, 1, /* line out */ | ||
816 | 8, 9, /* aes out */ | ||
817 | 10, 11, /* spdif out */ | ||
818 | 12, 16, /* adat out */ | ||
819 | 6, 7, /* phone out */ | ||
820 | -1, -1, -1, -1, -1, -1, | ||
821 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
822 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
823 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
824 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
825 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
826 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
827 | }; | ||
828 | |||
829 | static char channel_map_aes32[HDSPM_MAX_CHANNELS] = { | ||
830 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
831 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
832 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
833 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
834 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
835 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
836 | -1, -1, -1, -1, -1, -1, -1, -1, | ||
837 | -1, -1, -1, -1, -1, -1, -1, -1 | ||
838 | }; | ||
839 | |||
423 | struct hdspm_midi { | 840 | struct hdspm_midi { |
424 | struct hdspm *hdspm; | 841 | struct hdspm *hdspm; |
425 | int id; | 842 | int id; |
@@ -430,6 +847,21 @@ struct hdspm_midi { | |||
430 | struct timer_list timer; | 847 | struct timer_list timer; |
431 | spinlock_t lock; | 848 | spinlock_t lock; |
432 | int pending; | 849 | int pending; |
850 | int dataIn; | ||
851 | int statusIn; | ||
852 | int dataOut; | ||
853 | int statusOut; | ||
854 | int ie; | ||
855 | int irq; | ||
856 | }; | ||
857 | |||
858 | struct hdspm_tco { | ||
859 | int input; | ||
860 | int framerate; | ||
861 | int wordclock; | ||
862 | int samplerate; | ||
863 | int pull; | ||
864 | int term; /* 0 = off, 1 = on */ | ||
433 | }; | 865 | }; |
434 | 866 | ||
435 | struct hdspm { | 867 | struct hdspm { |
@@ -441,21 +873,39 @@ struct hdspm { | |||
441 | char *card_name; /* for procinfo */ | 873 | char *card_name; /* for procinfo */ |
442 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ | 874 | unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/ |
443 | 875 | ||
444 | unsigned char is_aes32; /* indicates if card is AES32 */ | 876 | uint8_t io_type; |
445 | 877 | ||
446 | int precise_ptr; /* use precise pointers, to be tested */ | ||
447 | int monitor_outs; /* set up monitoring outs init flag */ | 878 | int monitor_outs; /* set up monitoring outs init flag */ |
448 | 879 | ||
449 | u32 control_register; /* cached value */ | 880 | u32 control_register; /* cached value */ |
450 | u32 control2_register; /* cached value */ | 881 | u32 control2_register; /* cached value */ |
882 | u32 settings_register; | ||
451 | 883 | ||
452 | struct hdspm_midi midi[2]; | 884 | struct hdspm_midi midi[4]; |
453 | struct tasklet_struct midi_tasklet; | 885 | struct tasklet_struct midi_tasklet; |
454 | 886 | ||
455 | size_t period_bytes; | 887 | size_t period_bytes; |
456 | unsigned char ss_channels; /* channels of card in single speed */ | 888 | unsigned char ss_in_channels; |
457 | unsigned char ds_channels; /* Double Speed */ | 889 | unsigned char ds_in_channels; |
458 | unsigned char qs_channels; /* Quad Speed */ | 890 | unsigned char qs_in_channels; |
891 | unsigned char ss_out_channels; | ||
892 | unsigned char ds_out_channels; | ||
893 | unsigned char qs_out_channels; | ||
894 | |||
895 | unsigned char max_channels_in; | ||
896 | unsigned char max_channels_out; | ||
897 | |||
898 | char *channel_map_in; | ||
899 | char *channel_map_out; | ||
900 | |||
901 | char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs; | ||
902 | char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs; | ||
903 | |||
904 | char **port_names_in; | ||
905 | char **port_names_out; | ||
906 | |||
907 | char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs; | ||
908 | char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs; | ||
459 | 909 | ||
460 | unsigned char *playback_buffer; /* suitably aligned address */ | 910 | unsigned char *playback_buffer; /* suitably aligned address */ |
461 | unsigned char *capture_buffer; /* suitably aligned address */ | 911 | unsigned char *capture_buffer; /* suitably aligned address */ |
@@ -468,14 +918,13 @@ struct hdspm { | |||
468 | int last_internal_sample_rate; | 918 | int last_internal_sample_rate; |
469 | int system_sample_rate; | 919 | int system_sample_rate; |
470 | 920 | ||
471 | char *channel_map; /* channel map for DS and Quadspeed */ | ||
472 | |||
473 | int dev; /* Hardware vars... */ | 921 | int dev; /* Hardware vars... */ |
474 | int irq; | 922 | int irq; |
475 | unsigned long port; | 923 | unsigned long port; |
476 | void __iomem *iobase; | 924 | void __iomem *iobase; |
477 | 925 | ||
478 | int irq_count; /* for debug */ | 926 | int irq_count; /* for debug */ |
927 | int midiPorts; | ||
479 | 928 | ||
480 | struct snd_card *card; /* one card */ | 929 | struct snd_card *card; /* one card */ |
481 | struct snd_pcm *pcm; /* has one pcm */ | 930 | struct snd_pcm *pcm; /* has one pcm */ |
@@ -487,28 +936,17 @@ struct hdspm { | |||
487 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; | 936 | struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; |
488 | /* but input to much, so not used */ | 937 | /* but input to much, so not used */ |
489 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; | 938 | struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS]; |
490 | /* full mixer accessible over mixer ioctl or hwdep-device */ | 939 | /* full mixer accessable over mixer ioctl or hwdep-device */ |
491 | struct hdspm_mixer *mixer; | 940 | struct hdspm_mixer *mixer; |
492 | 941 | ||
493 | }; | 942 | struct hdspm_tco *tco; /* NULL if no TCO detected */ |
494 | 943 | ||
495 | /* These tables map the ALSA channels 1..N to the channels that we | 944 | char **texts_autosync; |
496 | need to use in order to find the relevant channel buffer. RME | 945 | int texts_autosync_items; |
497 | refer to this kind of mapping as between "the ADAT channel and | 946 | |
498 | the DMA channel." We index it using the logical audio channel, | 947 | cycles_t last_interrupt; |
499 | and the value is the DMA channel (i.e. channel buffer number) | ||
500 | where the data for that channel can be read/written from/to. | ||
501 | */ | ||
502 | 948 | ||
503 | static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = { | 949 | struct hdspm_peak_rms peak_rms; |
504 | 0, 1, 2, 3, 4, 5, 6, 7, | ||
505 | 8, 9, 10, 11, 12, 13, 14, 15, | ||
506 | 16, 17, 18, 19, 20, 21, 22, 23, | ||
507 | 24, 25, 26, 27, 28, 29, 30, 31, | ||
508 | 32, 33, 34, 35, 36, 37, 38, 39, | ||
509 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
510 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
511 | 56, 57, 58, 59, 60, 61, 62, 63 | ||
512 | }; | 950 | }; |
513 | 951 | ||
514 | 952 | ||
@@ -532,11 +970,11 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
532 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | 970 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, |
533 | struct hdspm * hdspm); | 971 | struct hdspm * hdspm); |
534 | 972 | ||
535 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm); | 973 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm); |
536 | static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm); | 974 | static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm); |
537 | static int hdspm_autosync_ref(struct hdspm * hdspm); | 975 | static int hdspm_autosync_ref(struct hdspm *hdspm); |
538 | static int snd_hdspm_set_defaults(struct hdspm * hdspm); | 976 | static int snd_hdspm_set_defaults(struct hdspm *hdspm); |
539 | static void hdspm_set_sgbuf(struct hdspm * hdspm, | 977 | static void hdspm_set_sgbuf(struct hdspm *hdspm, |
540 | struct snd_pcm_substream *substream, | 978 | struct snd_pcm_substream *substream, |
541 | unsigned int reg, int channels); | 979 | unsigned int reg, int channels); |
542 | 980 | ||
@@ -550,7 +988,7 @@ static inline int HDSPM_bit2freq(int n) | |||
550 | return bit2freq_tab[n]; | 988 | return bit2freq_tab[n]; |
551 | } | 989 | } |
552 | 990 | ||
553 | /* Write/read to/from HDSPM with Addresses in Bytes | 991 | /* Write/read to/from HDSPM with Adresses in Bytes |
554 | not words but only 32Bit writes are allowed */ | 992 | not words but only 32Bit writes are allowed */ |
555 | 993 | ||
556 | static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg, | 994 | static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg, |
@@ -564,8 +1002,8 @@ static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg) | |||
564 | return readl(hdspm->iobase + reg); | 1002 | return readl(hdspm->iobase + reg); |
565 | } | 1003 | } |
566 | 1004 | ||
567 | /* for each output channel (chan) I have an Input (in) and Playback (pb) Fader | 1005 | /* for each output channel (chan) I have an Input (in) and Playback (pb) Fader |
568 | mixer is write only on hardware so we have to cache him for read | 1006 | mixer is write only on hardware so we have to cache him for read |
569 | each fader is a u32, but uses only the first 16 bit */ | 1007 | each fader is a u32, but uses only the first 16 bit */ |
570 | 1008 | ||
571 | static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, | 1009 | static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan, |
@@ -641,30 +1079,67 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm) | |||
641 | /* check for external sample rate */ | 1079 | /* check for external sample rate */ |
642 | static int hdspm_external_sample_rate(struct hdspm *hdspm) | 1080 | static int hdspm_external_sample_rate(struct hdspm *hdspm) |
643 | { | 1081 | { |
644 | if (hdspm->is_aes32) { | 1082 | unsigned int status, status2, timecode; |
645 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 1083 | int syncref, rate = 0, rate_bits; |
646 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
647 | unsigned int timecode = | ||
648 | hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
649 | 1084 | ||
650 | int syncref = hdspm_autosync_ref(hdspm); | 1085 | switch (hdspm->io_type) { |
1086 | case AES32: | ||
1087 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
1088 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
1089 | timecode = hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
1090 | |||
1091 | syncref = hdspm_autosync_ref(hdspm); | ||
651 | 1092 | ||
652 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && | 1093 | if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD && |
653 | status & HDSPM_AES32_wcLock) | 1094 | status & HDSPM_AES32_wcLock) |
654 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) | 1095 | return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF); |
655 | & 0xF); | 1096 | |
656 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && | 1097 | if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 && |
657 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && | 1098 | syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 && |
658 | status2 & (HDSPM_LockAES >> | 1099 | status2 & (HDSPM_LockAES >> |
659 | (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))) | 1100 | (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1))) |
660 | return HDSPM_bit2freq((timecode >> | 1101 | return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF); |
661 | (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF); | ||
662 | return 0; | 1102 | return 0; |
663 | } else { | 1103 | break; |
664 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 1104 | |
665 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 1105 | case MADIface: |
666 | unsigned int rate_bits; | 1106 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
667 | int rate = 0; | 1107 | |
1108 | if (!(status & HDSPM_madiLock)) { | ||
1109 | rate = 0; /* no lock */ | ||
1110 | } else { | ||
1111 | switch (status & (HDSPM_status1_freqMask)) { | ||
1112 | case HDSPM_status1_F_0*1: | ||
1113 | rate = 32000; break; | ||
1114 | case HDSPM_status1_F_0*2: | ||
1115 | rate = 44100; break; | ||
1116 | case HDSPM_status1_F_0*3: | ||
1117 | rate = 48000; break; | ||
1118 | case HDSPM_status1_F_0*4: | ||
1119 | rate = 64000; break; | ||
1120 | case HDSPM_status1_F_0*5: | ||
1121 | rate = 88200; break; | ||
1122 | case HDSPM_status1_F_0*6: | ||
1123 | rate = 96000; break; | ||
1124 | case HDSPM_status1_F_0*7: | ||
1125 | rate = 128000; break; | ||
1126 | case HDSPM_status1_F_0*8: | ||
1127 | rate = 176400; break; | ||
1128 | case HDSPM_status1_F_0*9: | ||
1129 | rate = 192000; break; | ||
1130 | default: | ||
1131 | rate = 0; break; | ||
1132 | } | ||
1133 | } | ||
1134 | |||
1135 | break; | ||
1136 | |||
1137 | case MADI: | ||
1138 | case AIO: | ||
1139 | case RayDAT: | ||
1140 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
1141 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
1142 | rate = 0; | ||
668 | 1143 | ||
669 | /* if wordclock has synced freq and wordclock is valid */ | 1144 | /* if wordclock has synced freq and wordclock is valid */ |
670 | if ((status2 & HDSPM_wcLock) != 0 && | 1145 | if ((status2 & HDSPM_wcLock) != 0 && |
@@ -672,6 +1147,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
672 | 1147 | ||
673 | rate_bits = status2 & HDSPM_wcFreqMask; | 1148 | rate_bits = status2 & HDSPM_wcFreqMask; |
674 | 1149 | ||
1150 | |||
675 | switch (rate_bits) { | 1151 | switch (rate_bits) { |
676 | case HDSPM_wcFreq32: | 1152 | case HDSPM_wcFreq32: |
677 | rate = 32000; | 1153 | rate = 32000; |
@@ -691,7 +1167,6 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
691 | case HDSPM_wcFreq96: | 1167 | case HDSPM_wcFreq96: |
692 | rate = 96000; | 1168 | rate = 96000; |
693 | break; | 1169 | break; |
694 | /* Quadspeed Bit missing ???? */ | ||
695 | default: | 1170 | default: |
696 | rate = 0; | 1171 | rate = 0; |
697 | break; | 1172 | break; |
@@ -702,10 +1177,10 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
702 | * word has priority to MADI | 1177 | * word has priority to MADI |
703 | */ | 1178 | */ |
704 | if (rate != 0 && | 1179 | if (rate != 0 && |
705 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) | 1180 | (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) |
706 | return rate; | 1181 | return rate; |
707 | 1182 | ||
708 | /* maby a madi input (which is taken if sel sync is madi) */ | 1183 | /* maybe a madi input (which is taken if sel sync is madi) */ |
709 | if (status & HDSPM_madiLock) { | 1184 | if (status & HDSPM_madiLock) { |
710 | rate_bits = status & HDSPM_madiFreqMask; | 1185 | rate_bits = status & HDSPM_madiFreqMask; |
711 | 1186 | ||
@@ -742,36 +1217,35 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm) | |||
742 | break; | 1217 | break; |
743 | } | 1218 | } |
744 | } | 1219 | } |
745 | return rate; | 1220 | break; |
746 | } | 1221 | } |
1222 | |||
1223 | return rate; | ||
747 | } | 1224 | } |
748 | 1225 | ||
749 | /* Latency function */ | 1226 | /* Latency function */ |
750 | static inline void hdspm_compute_period_size(struct hdspm * hdspm) | 1227 | static inline void hdspm_compute_period_size(struct hdspm *hdspm) |
751 | { | 1228 | { |
752 | hdspm->period_bytes = | 1229 | hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8)); |
753 | 1 << ((hdspm_decode_latency(hdspm->control_register) + 8)); | ||
754 | } | 1230 | } |
755 | 1231 | ||
756 | static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm) | 1232 | |
1233 | static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm) | ||
757 | { | 1234 | { |
758 | int position; | 1235 | int position; |
759 | 1236 | ||
760 | position = hdspm_read(hdspm, HDSPM_statusRegister); | 1237 | position = hdspm_read(hdspm, HDSPM_statusRegister); |
761 | 1238 | ||
762 | if (!hdspm->precise_ptr) | 1239 | switch (hdspm->io_type) { |
763 | return (position & HDSPM_BufferID) ? | 1240 | case RayDAT: |
1241 | case AIO: | ||
1242 | position &= HDSPM_BufferPositionMask; | ||
1243 | position /= 4; /* Bytes per sample */ | ||
1244 | break; | ||
1245 | default: | ||
1246 | position = (position & HDSPM_BufferID) ? | ||
764 | (hdspm->period_bytes / 4) : 0; | 1247 | (hdspm->period_bytes / 4) : 0; |
765 | 1248 | } | |
766 | /* hwpointer comes in bytes and is 64Bytes accurate (by docu since | ||
767 | PCI Burst) | ||
768 | i have experimented that it is at most 64 Byte to much for playing | ||
769 | so substraction of 64 byte should be ok for ALSA, but use it only | ||
770 | for application where you know what you do since if you come to | ||
771 | near with record pointer it can be a disaster */ | ||
772 | |||
773 | position &= HDSPM_BufferPositionMask; | ||
774 | position = ((position - 64) % (2 * hdspm->period_bytes)) / 4; | ||
775 | 1249 | ||
776 | return position; | 1250 | return position; |
777 | } | 1251 | } |
@@ -805,7 +1279,7 @@ static void hdspm_silence_playback(struct hdspm *hdspm) | |||
805 | } | 1279 | } |
806 | } | 1280 | } |
807 | 1281 | ||
808 | static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames) | 1282 | static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames) |
809 | { | 1283 | { |
810 | int n; | 1284 | int n; |
811 | 1285 | ||
@@ -829,21 +1303,53 @@ static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames) | |||
829 | return 0; | 1303 | return 0; |
830 | } | 1304 | } |
831 | 1305 | ||
1306 | static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period) | ||
1307 | { | ||
1308 | u64 freq_const; | ||
1309 | |||
1310 | if (period == 0) | ||
1311 | return 0; | ||
1312 | |||
1313 | switch (hdspm->io_type) { | ||
1314 | case MADI: | ||
1315 | case AES32: | ||
1316 | freq_const = 110069313433624ULL; | ||
1317 | break; | ||
1318 | case RayDAT: | ||
1319 | case AIO: | ||
1320 | freq_const = 104857600000000ULL; | ||
1321 | break; | ||
1322 | case MADIface: | ||
1323 | freq_const = 131072000000000ULL; | ||
1324 | } | ||
1325 | |||
1326 | return div_u64(freq_const, period); | ||
1327 | } | ||
1328 | |||
1329 | |||
832 | static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) | 1330 | static void hdspm_set_dds_value(struct hdspm *hdspm, int rate) |
833 | { | 1331 | { |
834 | u64 n; | 1332 | u64 n; |
835 | 1333 | ||
836 | if (rate >= 112000) | 1334 | if (rate >= 112000) |
837 | rate /= 4; | 1335 | rate /= 4; |
838 | else if (rate >= 56000) | 1336 | else if (rate >= 56000) |
839 | rate /= 2; | 1337 | rate /= 2; |
840 | 1338 | ||
841 | /* RME says n = 104857600000000, but in the windows MADI driver, I see: | 1339 | switch (hdspm->io_type) { |
842 | // return 104857600000000 / rate; // 100 MHz | 1340 | case MADIface: |
843 | return 110100480000000 / rate; // 105 MHz | 1341 | n = 131072000000000ULL; /* 125 MHz */ |
844 | */ | 1342 | break; |
845 | /* n = 104857600000000ULL; */ /* = 2^20 * 10^8 */ | 1343 | case MADI: |
846 | n = 110100480000000ULL; /* Value checked for AES32 and MADI */ | 1344 | case AES32: |
1345 | n = 110069313433624ULL; /* 105 MHz */ | ||
1346 | break; | ||
1347 | case RayDAT: | ||
1348 | case AIO: | ||
1349 | n = 104857600000000ULL; /* 100 MHz */ | ||
1350 | break; | ||
1351 | } | ||
1352 | |||
847 | n = div_u64(n, rate); | 1353 | n = div_u64(n, rate); |
848 | /* n should be less than 2^32 for being written to FREQ register */ | 1354 | /* n should be less than 2^32 for being written to FREQ register */ |
849 | snd_BUG_ON(n >> 32); | 1355 | snd_BUG_ON(n >> 32); |
@@ -864,13 +1370,13 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
864 | 1370 | ||
865 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { | 1371 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { |
866 | 1372 | ||
867 | /* SLAVE --- */ | 1373 | /* SLAVE --- */ |
868 | if (called_internally) { | 1374 | if (called_internally) { |
869 | 1375 | ||
870 | /* request from ctl or card initialization | 1376 | /* request from ctl or card initialization |
871 | just make a warning an remember setting | 1377 | just make a warning an remember setting |
872 | for future master mode switching */ | 1378 | for future master mode switching */ |
873 | 1379 | ||
874 | snd_printk(KERN_WARNING "HDSPM: " | 1380 | snd_printk(KERN_WARNING "HDSPM: " |
875 | "Warning: device is not running " | 1381 | "Warning: device is not running " |
876 | "as a clock master.\n"); | 1382 | "as a clock master.\n"); |
@@ -907,7 +1413,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
907 | 1413 | ||
908 | Note that a similar but essentially insoluble problem exists for | 1414 | Note that a similar but essentially insoluble problem exists for |
909 | externally-driven rate changes. All we can do is to flag rate | 1415 | externally-driven rate changes. All we can do is to flag rate |
910 | changes in the read/write routines. | 1416 | changes in the read/write routines. |
911 | */ | 1417 | */ |
912 | 1418 | ||
913 | if (current_rate <= 48000) | 1419 | if (current_rate <= 48000) |
@@ -975,16 +1481,35 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally) | |||
975 | /* For AES32, need to set DDS value in FREQ register | 1481 | /* For AES32, need to set DDS value in FREQ register |
976 | For MADI, also apparently */ | 1482 | For MADI, also apparently */ |
977 | hdspm_set_dds_value(hdspm, rate); | 1483 | hdspm_set_dds_value(hdspm, rate); |
978 | 1484 | ||
979 | if (hdspm->is_aes32 && rate != current_rate) | 1485 | if (AES32 == hdspm->io_type && rate != current_rate) |
980 | hdspm_write(hdspm, HDSPM_eeprom_wr, 0); | 1486 | hdspm_write(hdspm, HDSPM_eeprom_wr, 0); |
981 | |||
982 | /* For AES32 and for MADI (at least rev 204), channel_map needs to | ||
983 | * always be channel_map_madi_ss, whatever the sample rate */ | ||
984 | hdspm->channel_map = channel_map_madi_ss; | ||
985 | 1487 | ||
986 | hdspm->system_sample_rate = rate; | 1488 | hdspm->system_sample_rate = rate; |
987 | 1489 | ||
1490 | if (rate <= 48000) { | ||
1491 | hdspm->channel_map_in = hdspm->channel_map_in_ss; | ||
1492 | hdspm->channel_map_out = hdspm->channel_map_out_ss; | ||
1493 | hdspm->max_channels_in = hdspm->ss_in_channels; | ||
1494 | hdspm->max_channels_out = hdspm->ss_out_channels; | ||
1495 | hdspm->port_names_in = hdspm->port_names_in_ss; | ||
1496 | hdspm->port_names_out = hdspm->port_names_out_ss; | ||
1497 | } else if (rate <= 96000) { | ||
1498 | hdspm->channel_map_in = hdspm->channel_map_in_ds; | ||
1499 | hdspm->channel_map_out = hdspm->channel_map_out_ds; | ||
1500 | hdspm->max_channels_in = hdspm->ds_in_channels; | ||
1501 | hdspm->max_channels_out = hdspm->ds_out_channels; | ||
1502 | hdspm->port_names_in = hdspm->port_names_in_ds; | ||
1503 | hdspm->port_names_out = hdspm->port_names_out_ds; | ||
1504 | } else { | ||
1505 | hdspm->channel_map_in = hdspm->channel_map_in_qs; | ||
1506 | hdspm->channel_map_out = hdspm->channel_map_out_qs; | ||
1507 | hdspm->max_channels_in = hdspm->qs_in_channels; | ||
1508 | hdspm->max_channels_out = hdspm->qs_out_channels; | ||
1509 | hdspm->port_names_in = hdspm->port_names_in_qs; | ||
1510 | hdspm->port_names_out = hdspm->port_names_out_qs; | ||
1511 | } | ||
1512 | |||
988 | if (not_set != 0) | 1513 | if (not_set != 0) |
989 | return -1; | 1514 | return -1; |
990 | 1515 | ||
@@ -1019,39 +1544,26 @@ static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm, | |||
1019 | int id) | 1544 | int id) |
1020 | { | 1545 | { |
1021 | /* the hardware already does the relevant bit-mask with 0xff */ | 1546 | /* the hardware already does the relevant bit-mask with 0xff */ |
1022 | if (id) | 1547 | return hdspm_read(hdspm, hdspm->midi[id].dataIn); |
1023 | return hdspm_read(hdspm, HDSPM_midiDataIn1); | ||
1024 | else | ||
1025 | return hdspm_read(hdspm, HDSPM_midiDataIn0); | ||
1026 | } | 1548 | } |
1027 | 1549 | ||
1028 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, | 1550 | static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id, |
1029 | int val) | 1551 | int val) |
1030 | { | 1552 | { |
1031 | /* the hardware already does the relevant bit-mask with 0xff */ | 1553 | /* the hardware already does the relevant bit-mask with 0xff */ |
1032 | if (id) | 1554 | return hdspm_write(hdspm, hdspm->midi[id].dataOut, val); |
1033 | hdspm_write(hdspm, HDSPM_midiDataOut1, val); | ||
1034 | else | ||
1035 | hdspm_write(hdspm, HDSPM_midiDataOut0, val); | ||
1036 | } | 1555 | } |
1037 | 1556 | ||
1038 | static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id) | 1557 | static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id) |
1039 | { | 1558 | { |
1040 | if (id) | 1559 | return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF; |
1041 | return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff); | ||
1042 | else | ||
1043 | return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff); | ||
1044 | } | 1560 | } |
1045 | 1561 | ||
1046 | static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) | 1562 | static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id) |
1047 | { | 1563 | { |
1048 | int fifo_bytes_used; | 1564 | int fifo_bytes_used; |
1049 | 1565 | ||
1050 | if (id) | 1566 | fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF; |
1051 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1); | ||
1052 | else | ||
1053 | fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0); | ||
1054 | fifo_bytes_used &= 0xff; | ||
1055 | 1567 | ||
1056 | if (fifo_bytes_used < 128) | 1568 | if (fifo_bytes_used < 128) |
1057 | return 128 - fifo_bytes_used; | 1569 | return 128 - fifo_bytes_used; |
@@ -1074,7 +1586,7 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1074 | unsigned char buf[128]; | 1586 | unsigned char buf[128]; |
1075 | 1587 | ||
1076 | /* Output is not interrupt driven */ | 1588 | /* Output is not interrupt driven */ |
1077 | 1589 | ||
1078 | spin_lock_irqsave (&hmidi->lock, flags); | 1590 | spin_lock_irqsave (&hmidi->lock, flags); |
1079 | if (hmidi->output && | 1591 | if (hmidi->output && |
1080 | !snd_rawmidi_transmit_empty (hmidi->output)) { | 1592 | !snd_rawmidi_transmit_empty (hmidi->output)) { |
@@ -1083,11 +1595,11 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi) | |||
1083 | if (n_pending > 0) { | 1595 | if (n_pending > 0) { |
1084 | if (n_pending > (int)sizeof (buf)) | 1596 | if (n_pending > (int)sizeof (buf)) |
1085 | n_pending = sizeof (buf); | 1597 | n_pending = sizeof (buf); |
1086 | 1598 | ||
1087 | to_write = snd_rawmidi_transmit (hmidi->output, buf, | 1599 | to_write = snd_rawmidi_transmit (hmidi->output, buf, |
1088 | n_pending); | 1600 | n_pending); |
1089 | if (to_write > 0) { | 1601 | if (to_write > 0) { |
1090 | for (i = 0; i < to_write; ++i) | 1602 | for (i = 0; i < to_write; ++i) |
1091 | snd_hdspm_midi_write_byte (hmidi->hdspm, | 1603 | snd_hdspm_midi_write_byte (hmidi->hdspm, |
1092 | hmidi->id, | 1604 | hmidi->id, |
1093 | buf[i]); | 1605 | buf[i]); |
@@ -1127,12 +1639,11 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi) | |||
1127 | } | 1639 | } |
1128 | } | 1640 | } |
1129 | hmidi->pending = 0; | 1641 | hmidi->pending = 0; |
1130 | if (hmidi->id) | 1642 | |
1131 | hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable; | 1643 | hmidi->hdspm->control_register |= hmidi->ie; |
1132 | else | ||
1133 | hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable; | ||
1134 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, | 1644 | hdspm_write(hmidi->hdspm, HDSPM_controlRegister, |
1135 | hmidi->hdspm->control_register); | 1645 | hmidi->hdspm->control_register); |
1646 | |||
1136 | spin_unlock_irqrestore (&hmidi->lock, flags); | 1647 | spin_unlock_irqrestore (&hmidi->lock, flags); |
1137 | return snd_hdspm_midi_output_write (hmidi); | 1648 | return snd_hdspm_midi_output_write (hmidi); |
1138 | } | 1649 | } |
@@ -1143,20 +1654,18 @@ snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) | |||
1143 | struct hdspm *hdspm; | 1654 | struct hdspm *hdspm; |
1144 | struct hdspm_midi *hmidi; | 1655 | struct hdspm_midi *hmidi; |
1145 | unsigned long flags; | 1656 | unsigned long flags; |
1146 | u32 ie; | ||
1147 | 1657 | ||
1148 | hmidi = substream->rmidi->private_data; | 1658 | hmidi = substream->rmidi->private_data; |
1149 | hdspm = hmidi->hdspm; | 1659 | hdspm = hmidi->hdspm; |
1150 | ie = hmidi->id ? | 1660 | |
1151 | HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable; | ||
1152 | spin_lock_irqsave (&hdspm->lock, flags); | 1661 | spin_lock_irqsave (&hdspm->lock, flags); |
1153 | if (up) { | 1662 | if (up) { |
1154 | if (!(hdspm->control_register & ie)) { | 1663 | if (!(hdspm->control_register & hmidi->ie)) { |
1155 | snd_hdspm_flush_midi_input (hdspm, hmidi->id); | 1664 | snd_hdspm_flush_midi_input (hdspm, hmidi->id); |
1156 | hdspm->control_register |= ie; | 1665 | hdspm->control_register |= hmidi->ie; |
1157 | } | 1666 | } |
1158 | } else { | 1667 | } else { |
1159 | hdspm->control_register &= ~ie; | 1668 | hdspm->control_register &= ~hmidi->ie; |
1160 | } | 1669 | } |
1161 | 1670 | ||
1162 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 1671 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); |
@@ -1167,14 +1676,14 @@ static void snd_hdspm_midi_output_timer(unsigned long data) | |||
1167 | { | 1676 | { |
1168 | struct hdspm_midi *hmidi = (struct hdspm_midi *) data; | 1677 | struct hdspm_midi *hmidi = (struct hdspm_midi *) data; |
1169 | unsigned long flags; | 1678 | unsigned long flags; |
1170 | 1679 | ||
1171 | snd_hdspm_midi_output_write(hmidi); | 1680 | snd_hdspm_midi_output_write(hmidi); |
1172 | spin_lock_irqsave (&hmidi->lock, flags); | 1681 | spin_lock_irqsave (&hmidi->lock, flags); |
1173 | 1682 | ||
1174 | /* this does not bump hmidi->istimer, because the | 1683 | /* this does not bump hmidi->istimer, because the |
1175 | kernel automatically removed the timer when it | 1684 | kernel automatically removed the timer when it |
1176 | expired, and we are now adding it back, thus | 1685 | expired, and we are now adding it back, thus |
1177 | leaving istimer wherever it was set before. | 1686 | leaving istimer wherever it was set before. |
1178 | */ | 1687 | */ |
1179 | 1688 | ||
1180 | if (hmidi->istimer) { | 1689 | if (hmidi->istimer) { |
@@ -1288,22 +1797,103 @@ static int __devinit snd_hdspm_create_midi (struct snd_card *card, | |||
1288 | hdspm->midi[id].hdspm = hdspm; | 1797 | hdspm->midi[id].hdspm = hdspm; |
1289 | spin_lock_init (&hdspm->midi[id].lock); | 1798 | spin_lock_init (&hdspm->midi[id].lock); |
1290 | 1799 | ||
1291 | sprintf (buf, "%s MIDI %d", card->shortname, id+1); | 1800 | if (0 == id) { |
1292 | err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi); | 1801 | if (MADIface == hdspm->io_type) { |
1293 | if (err < 0) | 1802 | /* MIDI-over-MADI on HDSPe MADIface */ |
1294 | return err; | 1803 | hdspm->midi[0].dataIn = HDSPM_midiDataIn2; |
1804 | hdspm->midi[0].statusIn = HDSPM_midiStatusIn2; | ||
1805 | hdspm->midi[0].dataOut = HDSPM_midiDataOut2; | ||
1806 | hdspm->midi[0].statusOut = HDSPM_midiStatusOut2; | ||
1807 | hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable; | ||
1808 | hdspm->midi[0].irq = HDSPM_midi2IRQPending; | ||
1809 | } else { | ||
1810 | hdspm->midi[0].dataIn = HDSPM_midiDataIn0; | ||
1811 | hdspm->midi[0].statusIn = HDSPM_midiStatusIn0; | ||
1812 | hdspm->midi[0].dataOut = HDSPM_midiDataOut0; | ||
1813 | hdspm->midi[0].statusOut = HDSPM_midiStatusOut0; | ||
1814 | hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable; | ||
1815 | hdspm->midi[0].irq = HDSPM_midi0IRQPending; | ||
1816 | } | ||
1817 | } else if (1 == id) { | ||
1818 | hdspm->midi[1].dataIn = HDSPM_midiDataIn1; | ||
1819 | hdspm->midi[1].statusIn = HDSPM_midiStatusIn1; | ||
1820 | hdspm->midi[1].dataOut = HDSPM_midiDataOut1; | ||
1821 | hdspm->midi[1].statusOut = HDSPM_midiStatusOut1; | ||
1822 | hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable; | ||
1823 | hdspm->midi[1].irq = HDSPM_midi1IRQPending; | ||
1824 | } else if ((2 == id) && (MADI == hdspm->io_type)) { | ||
1825 | /* MIDI-over-MADI on HDSPe MADI */ | ||
1826 | hdspm->midi[2].dataIn = HDSPM_midiDataIn2; | ||
1827 | hdspm->midi[2].statusIn = HDSPM_midiStatusIn2; | ||
1828 | hdspm->midi[2].dataOut = HDSPM_midiDataOut2; | ||
1829 | hdspm->midi[2].statusOut = HDSPM_midiStatusOut2; | ||
1830 | hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable; | ||
1831 | hdspm->midi[2].irq = HDSPM_midi2IRQPending; | ||
1832 | } else if (2 == id) { | ||
1833 | /* TCO MTC, read only */ | ||
1834 | hdspm->midi[2].dataIn = HDSPM_midiDataIn2; | ||
1835 | hdspm->midi[2].statusIn = HDSPM_midiStatusIn2; | ||
1836 | hdspm->midi[2].dataOut = -1; | ||
1837 | hdspm->midi[2].statusOut = -1; | ||
1838 | hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable; | ||
1839 | hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES; | ||
1840 | } else if (3 == id) { | ||
1841 | /* TCO MTC on HDSPe MADI */ | ||
1842 | hdspm->midi[3].dataIn = HDSPM_midiDataIn3; | ||
1843 | hdspm->midi[3].statusIn = HDSPM_midiStatusIn3; | ||
1844 | hdspm->midi[3].dataOut = -1; | ||
1845 | hdspm->midi[3].statusOut = -1; | ||
1846 | hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable; | ||
1847 | hdspm->midi[3].irq = HDSPM_midi3IRQPending; | ||
1848 | } | ||
1295 | 1849 | ||
1296 | sprintf(hdspm->midi[id].rmidi->name, "HDSPM MIDI %d", id+1); | 1850 | if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) || |
1297 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; | 1851 | (MADIface == hdspm->io_type)))) { |
1852 | if ((id == 0) && (MADIface == hdspm->io_type)) { | ||
1853 | sprintf(buf, "%s MIDIoverMADI", card->shortname); | ||
1854 | } else if ((id == 2) && (MADI == hdspm->io_type)) { | ||
1855 | sprintf(buf, "%s MIDIoverMADI", card->shortname); | ||
1856 | } else { | ||
1857 | sprintf(buf, "%s MIDI %d", card->shortname, id+1); | ||
1858 | } | ||
1859 | err = snd_rawmidi_new(card, buf, id, 1, 1, | ||
1860 | &hdspm->midi[id].rmidi); | ||
1861 | if (err < 0) | ||
1862 | return err; | ||
1298 | 1863 | ||
1299 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, | 1864 | sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d", |
1300 | &snd_hdspm_midi_output); | 1865 | card->id, id+1); |
1301 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, | 1866 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; |
1302 | &snd_hdspm_midi_input); | 1867 | |
1868 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, | ||
1869 | SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
1870 | &snd_hdspm_midi_output); | ||
1871 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, | ||
1872 | SNDRV_RAWMIDI_STREAM_INPUT, | ||
1873 | &snd_hdspm_midi_input); | ||
1874 | |||
1875 | hdspm->midi[id].rmidi->info_flags |= | ||
1876 | SNDRV_RAWMIDI_INFO_OUTPUT | | ||
1877 | SNDRV_RAWMIDI_INFO_INPUT | | ||
1878 | SNDRV_RAWMIDI_INFO_DUPLEX; | ||
1879 | } else { | ||
1880 | /* TCO MTC, read only */ | ||
1881 | sprintf(buf, "%s MTC %d", card->shortname, id+1); | ||
1882 | err = snd_rawmidi_new(card, buf, id, 1, 1, | ||
1883 | &hdspm->midi[id].rmidi); | ||
1884 | if (err < 0) | ||
1885 | return err; | ||
1303 | 1886 | ||
1304 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | | 1887 | sprintf(hdspm->midi[id].rmidi->name, |
1305 | SNDRV_RAWMIDI_INFO_INPUT | | 1888 | "%s MTC %d", card->id, id+1); |
1306 | SNDRV_RAWMIDI_INFO_DUPLEX; | 1889 | hdspm->midi[id].rmidi->private_data = &hdspm->midi[id]; |
1890 | |||
1891 | snd_rawmidi_set_ops(hdspm->midi[id].rmidi, | ||
1892 | SNDRV_RAWMIDI_STREAM_INPUT, | ||
1893 | &snd_hdspm_midi_input); | ||
1894 | |||
1895 | hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT; | ||
1896 | } | ||
1307 | 1897 | ||
1308 | return 0; | 1898 | return 0; |
1309 | } | 1899 | } |
@@ -1312,12 +1902,15 @@ static int __devinit snd_hdspm_create_midi (struct snd_card *card, | |||
1312 | static void hdspm_midi_tasklet(unsigned long arg) | 1902 | static void hdspm_midi_tasklet(unsigned long arg) |
1313 | { | 1903 | { |
1314 | struct hdspm *hdspm = (struct hdspm *)arg; | 1904 | struct hdspm *hdspm = (struct hdspm *)arg; |
1315 | 1905 | int i = 0; | |
1316 | if (hdspm->midi[0].pending) | 1906 | |
1317 | snd_hdspm_midi_input_read (&hdspm->midi[0]); | 1907 | while (i < hdspm->midiPorts) { |
1318 | if (hdspm->midi[1].pending) | 1908 | if (hdspm->midi[i].pending) |
1319 | snd_hdspm_midi_input_read (&hdspm->midi[1]); | 1909 | snd_hdspm_midi_input_read(&hdspm->midi[i]); |
1320 | } | 1910 | |
1911 | i++; | ||
1912 | } | ||
1913 | } | ||
1321 | 1914 | ||
1322 | 1915 | ||
1323 | /*----------------------------------------------------------------------------- | 1916 | /*----------------------------------------------------------------------------- |
@@ -1326,6 +1919,22 @@ static void hdspm_midi_tasklet(unsigned long arg) | |||
1326 | 1919 | ||
1327 | /* get the system sample rate which is set */ | 1920 | /* get the system sample rate which is set */ |
1328 | 1921 | ||
1922 | |||
1923 | /** | ||
1924 | * Calculate the real sample rate from the | ||
1925 | * current DDS value. | ||
1926 | **/ | ||
1927 | static int hdspm_get_system_sample_rate(struct hdspm *hdspm) | ||
1928 | { | ||
1929 | unsigned int period, rate; | ||
1930 | |||
1931 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
1932 | rate = hdspm_calc_dds_value(hdspm, period); | ||
1933 | |||
1934 | return rate; | ||
1935 | } | ||
1936 | |||
1937 | |||
1329 | #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ | 1938 | #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \ |
1330 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 1939 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1331 | .name = xname, \ | 1940 | .name = xname, \ |
@@ -1340,112 +1949,274 @@ static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol, | |||
1340 | { | 1949 | { |
1341 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 1950 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1342 | uinfo->count = 1; | 1951 | uinfo->count = 1; |
1952 | uinfo->value.integer.min = 27000; | ||
1953 | uinfo->value.integer.max = 207000; | ||
1954 | uinfo->value.integer.step = 1; | ||
1343 | return 0; | 1955 | return 0; |
1344 | } | 1956 | } |
1345 | 1957 | ||
1958 | |||
1346 | static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol, | 1959 | static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol, |
1347 | struct snd_ctl_elem_value * | 1960 | struct snd_ctl_elem_value * |
1348 | ucontrol) | 1961 | ucontrol) |
1349 | { | 1962 | { |
1350 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 1963 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1351 | 1964 | ||
1352 | ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate; | 1965 | ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm); |
1966 | return 0; | ||
1967 | } | ||
1968 | |||
1969 | |||
1970 | /** | ||
1971 | * Returns the WordClock sample rate class for the given card. | ||
1972 | **/ | ||
1973 | static int hdspm_get_wc_sample_rate(struct hdspm *hdspm) | ||
1974 | { | ||
1975 | int status; | ||
1976 | |||
1977 | switch (hdspm->io_type) { | ||
1978 | case RayDAT: | ||
1979 | case AIO: | ||
1980 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
1981 | return (status >> 16) & 0xF; | ||
1982 | break; | ||
1983 | default: | ||
1984 | break; | ||
1985 | } | ||
1986 | |||
1987 | |||
1988 | return 0; | ||
1989 | } | ||
1990 | |||
1991 | |||
1992 | /** | ||
1993 | * Returns the TCO sample rate class for the given card. | ||
1994 | **/ | ||
1995 | static int hdspm_get_tco_sample_rate(struct hdspm *hdspm) | ||
1996 | { | ||
1997 | int status; | ||
1998 | |||
1999 | if (hdspm->tco) { | ||
2000 | switch (hdspm->io_type) { | ||
2001 | case RayDAT: | ||
2002 | case AIO: | ||
2003 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
2004 | return (status >> 20) & 0xF; | ||
2005 | break; | ||
2006 | default: | ||
2007 | break; | ||
2008 | } | ||
2009 | } | ||
2010 | |||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
2014 | |||
2015 | /** | ||
2016 | * Returns the SYNC_IN sample rate class for the given card. | ||
2017 | **/ | ||
2018 | static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm) | ||
2019 | { | ||
2020 | int status; | ||
2021 | |||
2022 | if (hdspm->tco) { | ||
2023 | switch (hdspm->io_type) { | ||
2024 | case RayDAT: | ||
2025 | case AIO: | ||
2026 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_2); | ||
2027 | return (status >> 12) & 0xF; | ||
2028 | break; | ||
2029 | default: | ||
2030 | break; | ||
2031 | } | ||
2032 | } | ||
2033 | |||
1353 | return 0; | 2034 | return 0; |
1354 | } | 2035 | } |
1355 | 2036 | ||
2037 | |||
2038 | /** | ||
2039 | * Returns the sample rate class for input source <idx> for | ||
2040 | * 'new style' cards like the AIO and RayDAT. | ||
2041 | **/ | ||
2042 | static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx) | ||
2043 | { | ||
2044 | int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2); | ||
2045 | |||
2046 | return (status >> (idx*4)) & 0xF; | ||
2047 | } | ||
2048 | |||
2049 | |||
2050 | |||
1356 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ | 2051 | #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \ |
1357 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2052 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1358 | .name = xname, \ | 2053 | .name = xname, \ |
1359 | .index = xindex, \ | 2054 | .private_value = xindex, \ |
1360 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | 2055 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ |
1361 | .info = snd_hdspm_info_autosync_sample_rate, \ | 2056 | .info = snd_hdspm_info_autosync_sample_rate, \ |
1362 | .get = snd_hdspm_get_autosync_sample_rate \ | 2057 | .get = snd_hdspm_get_autosync_sample_rate \ |
1363 | } | 2058 | } |
1364 | 2059 | ||
2060 | |||
1365 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, | 2061 | static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol, |
1366 | struct snd_ctl_elem_info *uinfo) | 2062 | struct snd_ctl_elem_info *uinfo) |
1367 | { | 2063 | { |
1368 | static char *texts[] = { "32000", "44100", "48000", | ||
1369 | "64000", "88200", "96000", | ||
1370 | "128000", "176400", "192000", | ||
1371 | "None" | ||
1372 | }; | ||
1373 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2064 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1374 | uinfo->count = 1; | 2065 | uinfo->count = 1; |
1375 | uinfo->value.enumerated.items = 10; | 2066 | uinfo->value.enumerated.items = 10; |
2067 | |||
1376 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 2068 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1377 | uinfo->value.enumerated.item = | 2069 | uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; |
1378 | uinfo->value.enumerated.items - 1; | ||
1379 | strcpy(uinfo->value.enumerated.name, | 2070 | strcpy(uinfo->value.enumerated.name, |
1380 | texts[uinfo->value.enumerated.item]); | 2071 | texts_freq[uinfo->value.enumerated.item]); |
1381 | return 0; | 2072 | return 0; |
1382 | } | 2073 | } |
1383 | 2074 | ||
2075 | |||
1384 | static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, | 2076 | static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol, |
1385 | struct snd_ctl_elem_value * | 2077 | struct snd_ctl_elem_value * |
1386 | ucontrol) | 2078 | ucontrol) |
1387 | { | 2079 | { |
1388 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2080 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1389 | 2081 | ||
1390 | switch (hdspm_external_sample_rate(hdspm)) { | 2082 | switch (hdspm->io_type) { |
1391 | case 32000: | 2083 | case RayDAT: |
1392 | ucontrol->value.enumerated.item[0] = 0; | 2084 | switch (kcontrol->private_value) { |
1393 | break; | 2085 | case 0: |
1394 | case 44100: | 2086 | ucontrol->value.enumerated.item[0] = |
1395 | ucontrol->value.enumerated.item[0] = 1; | 2087 | hdspm_get_wc_sample_rate(hdspm); |
1396 | break; | 2088 | break; |
1397 | case 48000: | 2089 | case 7: |
1398 | ucontrol->value.enumerated.item[0] = 2; | 2090 | ucontrol->value.enumerated.item[0] = |
1399 | break; | 2091 | hdspm_get_tco_sample_rate(hdspm); |
1400 | case 64000: | 2092 | break; |
1401 | ucontrol->value.enumerated.item[0] = 3; | 2093 | case 8: |
1402 | break; | 2094 | ucontrol->value.enumerated.item[0] = |
1403 | case 88200: | 2095 | hdspm_get_sync_in_sample_rate(hdspm); |
1404 | ucontrol->value.enumerated.item[0] = 4; | 2096 | break; |
1405 | break; | 2097 | default: |
1406 | case 96000: | 2098 | ucontrol->value.enumerated.item[0] = |
1407 | ucontrol->value.enumerated.item[0] = 5; | 2099 | hdspm_get_s1_sample_rate(hdspm, |
1408 | break; | 2100 | kcontrol->private_value-1); |
1409 | case 128000: | 2101 | } |
1410 | ucontrol->value.enumerated.item[0] = 6; | 2102 | |
1411 | break; | 2103 | case AIO: |
1412 | case 176400: | 2104 | switch (kcontrol->private_value) { |
1413 | ucontrol->value.enumerated.item[0] = 7; | 2105 | case 0: /* WC */ |
1414 | break; | 2106 | ucontrol->value.enumerated.item[0] = |
1415 | case 192000: | 2107 | hdspm_get_wc_sample_rate(hdspm); |
1416 | ucontrol->value.enumerated.item[0] = 8; | 2108 | break; |
1417 | break; | 2109 | case 4: /* TCO */ |
2110 | ucontrol->value.enumerated.item[0] = | ||
2111 | hdspm_get_tco_sample_rate(hdspm); | ||
2112 | break; | ||
2113 | case 5: /* SYNC_IN */ | ||
2114 | ucontrol->value.enumerated.item[0] = | ||
2115 | hdspm_get_sync_in_sample_rate(hdspm); | ||
2116 | break; | ||
2117 | default: | ||
2118 | ucontrol->value.enumerated.item[0] = | ||
2119 | hdspm_get_s1_sample_rate(hdspm, | ||
2120 | ucontrol->id.index-1); | ||
2121 | } | ||
2122 | |||
2123 | case AES32: | ||
1418 | 2124 | ||
2125 | switch (kcontrol->private_value) { | ||
2126 | case 0: /* WC */ | ||
2127 | ucontrol->value.enumerated.item[0] = | ||
2128 | hdspm_get_wc_sample_rate(hdspm); | ||
2129 | break; | ||
2130 | case 9: /* TCO */ | ||
2131 | ucontrol->value.enumerated.item[0] = | ||
2132 | hdspm_get_tco_sample_rate(hdspm); | ||
2133 | break; | ||
2134 | case 10: /* SYNC_IN */ | ||
2135 | ucontrol->value.enumerated.item[0] = | ||
2136 | hdspm_get_sync_in_sample_rate(hdspm); | ||
2137 | break; | ||
2138 | default: /* AES1 to AES8 */ | ||
2139 | ucontrol->value.enumerated.item[0] = | ||
2140 | hdspm_get_s1_sample_rate(hdspm, | ||
2141 | kcontrol->private_value-1); | ||
2142 | break; | ||
2143 | |||
2144 | } | ||
1419 | default: | 2145 | default: |
1420 | ucontrol->value.enumerated.item[0] = 9; | 2146 | break; |
1421 | } | 2147 | } |
2148 | |||
1422 | return 0; | 2149 | return 0; |
1423 | } | 2150 | } |
1424 | 2151 | ||
2152 | |||
1425 | #define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \ | 2153 | #define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \ |
1426 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2154 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1427 | .name = xname, \ | 2155 | .name = xname, \ |
1428 | .index = xindex, \ | 2156 | .index = xindex, \ |
1429 | .access = SNDRV_CTL_ELEM_ACCESS_READ, \ | 2157 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ |
1430 | .info = snd_hdspm_info_system_clock_mode, \ | 2158 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
1431 | .get = snd_hdspm_get_system_clock_mode, \ | 2159 | .info = snd_hdspm_info_system_clock_mode, \ |
1432 | } | 2160 | .get = snd_hdspm_get_system_clock_mode, \ |
2161 | .put = snd_hdspm_put_system_clock_mode, \ | ||
2162 | } | ||
2163 | |||
2164 | |||
2165 | /** | ||
2166 | * Returns the system clock mode for the given card. | ||
2167 | * @returns 0 - master, 1 - slave | ||
2168 | **/ | ||
2169 | static int hdspm_system_clock_mode(struct hdspm *hdspm) | ||
2170 | { | ||
2171 | switch (hdspm->io_type) { | ||
2172 | case AIO: | ||
2173 | case RayDAT: | ||
2174 | if (hdspm->settings_register & HDSPM_c0Master) | ||
2175 | return 0; | ||
2176 | break; | ||
2177 | |||
2178 | default: | ||
2179 | if (hdspm->control_register & HDSPM_ClockModeMaster) | ||
2180 | return 0; | ||
2181 | } | ||
1433 | 2182 | ||
2183 | return 1; | ||
2184 | } | ||
1434 | 2185 | ||
1435 | 2186 | ||
1436 | static int hdspm_system_clock_mode(struct hdspm * hdspm) | 2187 | /** |
2188 | * Sets the system clock mode. | ||
2189 | * @param mode 0 - master, 1 - slave | ||
2190 | **/ | ||
2191 | static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode) | ||
1437 | { | 2192 | { |
1438 | /* Always reflect the hardware info, rme is never wrong !!!! */ | 2193 | switch (hdspm->io_type) { |
2194 | case AIO: | ||
2195 | case RayDAT: | ||
2196 | if (0 == mode) | ||
2197 | hdspm->settings_register |= HDSPM_c0Master; | ||
2198 | else | ||
2199 | hdspm->settings_register &= ~HDSPM_c0Master; | ||
1439 | 2200 | ||
1440 | if (hdspm->control_register & HDSPM_ClockModeMaster) | 2201 | hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); |
1441 | return 0; | 2202 | break; |
1442 | return 1; | 2203 | |
2204 | default: | ||
2205 | if (0 == mode) | ||
2206 | hdspm->control_register |= HDSPM_ClockModeMaster; | ||
2207 | else | ||
2208 | hdspm->control_register &= ~HDSPM_ClockModeMaster; | ||
2209 | |||
2210 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
2211 | hdspm->control_register); | ||
2212 | } | ||
1443 | } | 2213 | } |
1444 | 2214 | ||
2215 | |||
1445 | static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, | 2216 | static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol, |
1446 | struct snd_ctl_elem_info *uinfo) | 2217 | struct snd_ctl_elem_info *uinfo) |
1447 | { | 2218 | { |
1448 | static char *texts[] = { "Master", "Slave" }; | 2219 | static char *texts[] = { "Master", "AutoSync" }; |
1449 | 2220 | ||
1450 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2221 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1451 | uinfo->count = 1; | 2222 | uinfo->count = 1; |
@@ -1463,96 +2234,83 @@ static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol, | |||
1463 | { | 2234 | { |
1464 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2235 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1465 | 2236 | ||
1466 | ucontrol->value.enumerated.item[0] = | 2237 | ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm); |
1467 | hdspm_system_clock_mode(hdspm); | ||
1468 | return 0; | 2238 | return 0; |
1469 | } | 2239 | } |
1470 | 2240 | ||
1471 | #define HDSPM_CLOCK_SOURCE(xname, xindex) \ | 2241 | static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol, |
1472 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2242 | struct snd_ctl_elem_value *ucontrol) |
1473 | .name = xname, \ | 2243 | { |
1474 | .index = xindex, \ | 2244 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1475 | .info = snd_hdspm_info_clock_source, \ | 2245 | int val; |
1476 | .get = snd_hdspm_get_clock_source, \ | 2246 | |
1477 | .put = snd_hdspm_put_clock_source \ | 2247 | if (!snd_hdspm_use_is_exclusive(hdspm)) |
2248 | return -EBUSY; | ||
2249 | |||
2250 | val = ucontrol->value.enumerated.item[0]; | ||
2251 | if (val < 0) | ||
2252 | val = 0; | ||
2253 | else if (val > 1) | ||
2254 | val = 1; | ||
2255 | |||
2256 | hdspm_set_system_clock_mode(hdspm, val); | ||
2257 | |||
2258 | return 0; | ||
1478 | } | 2259 | } |
1479 | 2260 | ||
2261 | |||
2262 | #define HDSPM_INTERNAL_CLOCK(xname, xindex) \ | ||
2263 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2264 | .name = xname, \ | ||
2265 | .index = xindex, \ | ||
2266 | .info = snd_hdspm_info_clock_source, \ | ||
2267 | .get = snd_hdspm_get_clock_source, \ | ||
2268 | .put = snd_hdspm_put_clock_source \ | ||
2269 | } | ||
2270 | |||
2271 | |||
1480 | static int hdspm_clock_source(struct hdspm * hdspm) | 2272 | static int hdspm_clock_source(struct hdspm * hdspm) |
1481 | { | 2273 | { |
1482 | if (hdspm->control_register & HDSPM_ClockModeMaster) { | 2274 | switch (hdspm->system_sample_rate) { |
1483 | switch (hdspm->system_sample_rate) { | 2275 | case 32000: return 0; |
1484 | case 32000: | 2276 | case 44100: return 1; |
1485 | return 1; | 2277 | case 48000: return 2; |
1486 | case 44100: | 2278 | case 64000: return 3; |
1487 | return 2; | 2279 | case 88200: return 4; |
1488 | case 48000: | 2280 | case 96000: return 5; |
1489 | return 3; | 2281 | case 128000: return 6; |
1490 | case 64000: | 2282 | case 176400: return 7; |
1491 | return 4; | 2283 | case 192000: return 8; |
1492 | case 88200: | ||
1493 | return 5; | ||
1494 | case 96000: | ||
1495 | return 6; | ||
1496 | case 128000: | ||
1497 | return 7; | ||
1498 | case 176400: | ||
1499 | return 8; | ||
1500 | case 192000: | ||
1501 | return 9; | ||
1502 | default: | ||
1503 | return 3; | ||
1504 | } | ||
1505 | } else { | ||
1506 | return 0; | ||
1507 | } | 2284 | } |
2285 | |||
2286 | return -1; | ||
1508 | } | 2287 | } |
1509 | 2288 | ||
1510 | static int hdspm_set_clock_source(struct hdspm * hdspm, int mode) | 2289 | static int hdspm_set_clock_source(struct hdspm * hdspm, int mode) |
1511 | { | 2290 | { |
1512 | int rate; | 2291 | int rate; |
1513 | switch (mode) { | 2292 | switch (mode) { |
1514 | 2293 | case 0: | |
1515 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | 2294 | rate = 32000; break; |
1516 | if (hdspm_external_sample_rate(hdspm) != 0) { | 2295 | case 1: |
1517 | hdspm->control_register &= ~HDSPM_ClockModeMaster; | 2296 | rate = 44100; break; |
1518 | hdspm_write(hdspm, HDSPM_controlRegister, | 2297 | case 2: |
1519 | hdspm->control_register); | 2298 | rate = 48000; break; |
1520 | return 0; | 2299 | case 3: |
1521 | } | 2300 | rate = 64000; break; |
1522 | return -1; | 2301 | case 4: |
1523 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | 2302 | rate = 88200; break; |
1524 | rate = 32000; | 2303 | case 5: |
1525 | break; | 2304 | rate = 96000; break; |
1526 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | 2305 | case 6: |
1527 | rate = 44100; | 2306 | rate = 128000; break; |
1528 | break; | 2307 | case 7: |
1529 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | 2308 | rate = 176400; break; |
1530 | rate = 48000; | 2309 | case 8: |
1531 | break; | 2310 | rate = 192000; break; |
1532 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
1533 | rate = 64000; | ||
1534 | break; | ||
1535 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
1536 | rate = 88200; | ||
1537 | break; | ||
1538 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
1539 | rate = 96000; | ||
1540 | break; | ||
1541 | case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ: | ||
1542 | rate = 128000; | ||
1543 | break; | ||
1544 | case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ: | ||
1545 | rate = 176400; | ||
1546 | break; | ||
1547 | case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ: | ||
1548 | rate = 192000; | ||
1549 | break; | ||
1550 | |||
1551 | default: | 2311 | default: |
1552 | rate = 44100; | 2312 | rate = 48000; |
1553 | } | 2313 | } |
1554 | hdspm->control_register |= HDSPM_ClockModeMaster; | ||
1555 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
1556 | hdspm_set_rate(hdspm, rate, 1); | 2314 | hdspm_set_rate(hdspm, rate, 1); |
1557 | return 0; | 2315 | return 0; |
1558 | } | 2316 | } |
@@ -1560,25 +2318,16 @@ static int hdspm_set_clock_source(struct hdspm * hdspm, int mode) | |||
1560 | static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol, | 2318 | static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol, |
1561 | struct snd_ctl_elem_info *uinfo) | 2319 | struct snd_ctl_elem_info *uinfo) |
1562 | { | 2320 | { |
1563 | static char *texts[] = { "AutoSync", | ||
1564 | "Internal 32.0 kHz", "Internal 44.1 kHz", | ||
1565 | "Internal 48.0 kHz", | ||
1566 | "Internal 64.0 kHz", "Internal 88.2 kHz", | ||
1567 | "Internal 96.0 kHz", | ||
1568 | "Internal 128.0 kHz", "Internal 176.4 kHz", | ||
1569 | "Internal 192.0 kHz" | ||
1570 | }; | ||
1571 | |||
1572 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2321 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1573 | uinfo->count = 1; | 2322 | uinfo->count = 1; |
1574 | uinfo->value.enumerated.items = 10; | 2323 | uinfo->value.enumerated.items = 9; |
1575 | 2324 | ||
1576 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 2325 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1577 | uinfo->value.enumerated.item = | 2326 | uinfo->value.enumerated.item = |
1578 | uinfo->value.enumerated.items - 1; | 2327 | uinfo->value.enumerated.items - 1; |
1579 | 2328 | ||
1580 | strcpy(uinfo->value.enumerated.name, | 2329 | strcpy(uinfo->value.enumerated.name, |
1581 | texts[uinfo->value.enumerated.item]); | 2330 | texts_freq[uinfo->value.enumerated.item+1]); |
1582 | 2331 | ||
1583 | return 0; | 2332 | return 0; |
1584 | } | 2333 | } |
@@ -1615,134 +2364,301 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol, | |||
1615 | return change; | 2364 | return change; |
1616 | } | 2365 | } |
1617 | 2366 | ||
1618 | #define HDSPM_PREF_SYNC_REF(xname, xindex) \ | ||
1619 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
1620 | .name = xname, \ | ||
1621 | .index = xindex, \ | ||
1622 | .info = snd_hdspm_info_pref_sync_ref, \ | ||
1623 | .get = snd_hdspm_get_pref_sync_ref, \ | ||
1624 | .put = snd_hdspm_put_pref_sync_ref \ | ||
1625 | } | ||
1626 | 2367 | ||
2368 | #define HDSPM_PREF_SYNC_REF(xname, xindex) \ | ||
2369 | {.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
2370 | .name = xname, \ | ||
2371 | .index = xindex, \ | ||
2372 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
2373 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
2374 | .info = snd_hdspm_info_pref_sync_ref, \ | ||
2375 | .get = snd_hdspm_get_pref_sync_ref, \ | ||
2376 | .put = snd_hdspm_put_pref_sync_ref \ | ||
2377 | } | ||
2378 | |||
2379 | |||
2380 | /** | ||
2381 | * Returns the current preferred sync reference setting. | ||
2382 | * The semantics of the return value are depending on the | ||
2383 | * card, please see the comments for clarification. | ||
2384 | **/ | ||
1627 | static int hdspm_pref_sync_ref(struct hdspm * hdspm) | 2385 | static int hdspm_pref_sync_ref(struct hdspm * hdspm) |
1628 | { | 2386 | { |
1629 | /* Notice that this looks at the requested sync source, | 2387 | switch (hdspm->io_type) { |
1630 | not the one actually in use. | 2388 | case AES32: |
1631 | */ | ||
1632 | if (hdspm->is_aes32) { | ||
1633 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | 2389 | switch (hdspm->control_register & HDSPM_SyncRefMask) { |
1634 | /* number gives AES index, except for 0 which | 2390 | case 0: return 0; /* WC */ |
1635 | corresponds to WordClock */ | 2391 | case HDSPM_SyncRef0: return 1; /* AES 1 */ |
1636 | case 0: return 0; | 2392 | case HDSPM_SyncRef1: return 2; /* AES 2 */ |
1637 | case HDSPM_SyncRef0: return 1; | 2393 | case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */ |
1638 | case HDSPM_SyncRef1: return 2; | 2394 | case HDSPM_SyncRef2: return 4; /* AES 4 */ |
1639 | case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; | 2395 | case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */ |
1640 | case HDSPM_SyncRef2: return 4; | 2396 | case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */ |
1641 | case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; | 2397 | case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: |
1642 | case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; | 2398 | return 7; /* AES 7 */ |
1643 | case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7; | 2399 | case HDSPM_SyncRef3: return 8; /* AES 8 */ |
1644 | case HDSPM_SyncRef3: return 8; | 2400 | case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */ |
1645 | } | 2401 | } |
1646 | } else { | 2402 | break; |
1647 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | 2403 | |
1648 | case HDSPM_SyncRef_Word: | 2404 | case MADI: |
1649 | return HDSPM_SYNC_FROM_WORD; | 2405 | case MADIface: |
1650 | case HDSPM_SyncRef_MADI: | 2406 | if (hdspm->tco) { |
1651 | return HDSPM_SYNC_FROM_MADI; | 2407 | switch (hdspm->control_register & HDSPM_SyncRefMask) { |
2408 | case 0: return 0; /* WC */ | ||
2409 | case HDSPM_SyncRef0: return 1; /* MADI */ | ||
2410 | case HDSPM_SyncRef1: return 2; /* TCO */ | ||
2411 | case HDSPM_SyncRef1+HDSPM_SyncRef0: | ||
2412 | return 3; /* SYNC_IN */ | ||
2413 | } | ||
2414 | } else { | ||
2415 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | ||
2416 | case 0: return 0; /* WC */ | ||
2417 | case HDSPM_SyncRef0: return 1; /* MADI */ | ||
2418 | case HDSPM_SyncRef1+HDSPM_SyncRef0: | ||
2419 | return 2; /* SYNC_IN */ | ||
2420 | } | ||
2421 | } | ||
2422 | break; | ||
2423 | |||
2424 | case RayDAT: | ||
2425 | if (hdspm->tco) { | ||
2426 | switch ((hdspm->settings_register & | ||
2427 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2428 | case 0: return 0; /* WC */ | ||
2429 | case 3: return 1; /* ADAT 1 */ | ||
2430 | case 4: return 2; /* ADAT 2 */ | ||
2431 | case 5: return 3; /* ADAT 3 */ | ||
2432 | case 6: return 4; /* ADAT 4 */ | ||
2433 | case 1: return 5; /* AES */ | ||
2434 | case 2: return 6; /* SPDIF */ | ||
2435 | case 9: return 7; /* TCO */ | ||
2436 | case 10: return 8; /* SYNC_IN */ | ||
2437 | } | ||
2438 | } else { | ||
2439 | switch ((hdspm->settings_register & | ||
2440 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2441 | case 0: return 0; /* WC */ | ||
2442 | case 3: return 1; /* ADAT 1 */ | ||
2443 | case 4: return 2; /* ADAT 2 */ | ||
2444 | case 5: return 3; /* ADAT 3 */ | ||
2445 | case 6: return 4; /* ADAT 4 */ | ||
2446 | case 1: return 5; /* AES */ | ||
2447 | case 2: return 6; /* SPDIF */ | ||
2448 | case 10: return 7; /* SYNC_IN */ | ||
2449 | } | ||
1652 | } | 2450 | } |
2451 | |||
2452 | break; | ||
2453 | |||
2454 | case AIO: | ||
2455 | if (hdspm->tco) { | ||
2456 | switch ((hdspm->settings_register & | ||
2457 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2458 | case 0: return 0; /* WC */ | ||
2459 | case 3: return 1; /* ADAT */ | ||
2460 | case 1: return 2; /* AES */ | ||
2461 | case 2: return 3; /* SPDIF */ | ||
2462 | case 9: return 4; /* TCO */ | ||
2463 | case 10: return 5; /* SYNC_IN */ | ||
2464 | } | ||
2465 | } else { | ||
2466 | switch ((hdspm->settings_register & | ||
2467 | HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) { | ||
2468 | case 0: return 0; /* WC */ | ||
2469 | case 3: return 1; /* ADAT */ | ||
2470 | case 1: return 2; /* AES */ | ||
2471 | case 2: return 3; /* SPDIF */ | ||
2472 | case 10: return 4; /* SYNC_IN */ | ||
2473 | } | ||
2474 | } | ||
2475 | |||
2476 | break; | ||
1653 | } | 2477 | } |
1654 | 2478 | ||
1655 | return HDSPM_SYNC_FROM_WORD; | 2479 | return -1; |
1656 | } | 2480 | } |
1657 | 2481 | ||
2482 | |||
2483 | /** | ||
2484 | * Set the preferred sync reference to <pref>. The semantics | ||
2485 | * of <pref> are depending on the card type, see the comments | ||
2486 | * for clarification. | ||
2487 | **/ | ||
1658 | static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) | 2488 | static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref) |
1659 | { | 2489 | { |
1660 | hdspm->control_register &= ~HDSPM_SyncRefMask; | 2490 | int p = 0; |
1661 | 2491 | ||
1662 | if (hdspm->is_aes32) { | 2492 | switch (hdspm->io_type) { |
1663 | switch (pref) { | 2493 | case AES32: |
1664 | case 0: | 2494 | hdspm->control_register &= ~HDSPM_SyncRefMask; |
1665 | hdspm->control_register |= 0; | ||
1666 | break; | ||
1667 | case 1: | ||
1668 | hdspm->control_register |= HDSPM_SyncRef0; | ||
1669 | break; | ||
1670 | case 2: | ||
1671 | hdspm->control_register |= HDSPM_SyncRef1; | ||
1672 | break; | ||
1673 | case 3: | ||
1674 | hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1675 | break; | ||
1676 | case 4: | ||
1677 | hdspm->control_register |= HDSPM_SyncRef2; | ||
1678 | break; | ||
1679 | case 5: | ||
1680 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0; | ||
1681 | break; | ||
1682 | case 6: | ||
1683 | hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1; | ||
1684 | break; | ||
1685 | case 7: | ||
1686 | hdspm->control_register |= | ||
1687 | HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
1688 | break; | ||
1689 | case 8: | ||
1690 | hdspm->control_register |= HDSPM_SyncRef3; | ||
1691 | break; | ||
1692 | default: | ||
1693 | return -1; | ||
1694 | } | ||
1695 | } else { | ||
1696 | switch (pref) { | 2495 | switch (pref) { |
1697 | case HDSPM_SYNC_FROM_MADI: | 2496 | case 0: /* WC */ |
1698 | hdspm->control_register |= HDSPM_SyncRef_MADI; | 2497 | break; |
2498 | case 1: /* AES 1 */ | ||
2499 | hdspm->control_register |= HDSPM_SyncRef0; | ||
2500 | break; | ||
2501 | case 2: /* AES 2 */ | ||
2502 | hdspm->control_register |= HDSPM_SyncRef1; | ||
2503 | break; | ||
2504 | case 3: /* AES 3 */ | ||
2505 | hdspm->control_register |= | ||
2506 | HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
2507 | break; | ||
2508 | case 4: /* AES 4 */ | ||
2509 | hdspm->control_register |= HDSPM_SyncRef2; | ||
2510 | break; | ||
2511 | case 5: /* AES 5 */ | ||
2512 | hdspm->control_register |= | ||
2513 | HDSPM_SyncRef2+HDSPM_SyncRef0; | ||
1699 | break; | 2514 | break; |
1700 | case HDSPM_SYNC_FROM_WORD: | 2515 | case 6: /* AES 6 */ |
1701 | hdspm->control_register |= HDSPM_SyncRef_Word; | 2516 | hdspm->control_register |= |
2517 | HDSPM_SyncRef2+HDSPM_SyncRef1; | ||
2518 | break; | ||
2519 | case 7: /* AES 7 */ | ||
2520 | hdspm->control_register |= | ||
2521 | HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0; | ||
2522 | break; | ||
2523 | case 8: /* AES 8 */ | ||
2524 | hdspm->control_register |= HDSPM_SyncRef3; | ||
2525 | break; | ||
2526 | case 9: /* TCO */ | ||
2527 | hdspm->control_register |= | ||
2528 | HDSPM_SyncRef3+HDSPM_SyncRef0; | ||
1702 | break; | 2529 | break; |
1703 | default: | 2530 | default: |
1704 | return -1; | 2531 | return -1; |
1705 | } | 2532 | } |
2533 | |||
2534 | break; | ||
2535 | |||
2536 | case MADI: | ||
2537 | case MADIface: | ||
2538 | hdspm->control_register &= ~HDSPM_SyncRefMask; | ||
2539 | if (hdspm->tco) { | ||
2540 | switch (pref) { | ||
2541 | case 0: /* WC */ | ||
2542 | break; | ||
2543 | case 1: /* MADI */ | ||
2544 | hdspm->control_register |= HDSPM_SyncRef0; | ||
2545 | break; | ||
2546 | case 2: /* TCO */ | ||
2547 | hdspm->control_register |= HDSPM_SyncRef1; | ||
2548 | break; | ||
2549 | case 3: /* SYNC_IN */ | ||
2550 | hdspm->control_register |= | ||
2551 | HDSPM_SyncRef0+HDSPM_SyncRef1; | ||
2552 | break; | ||
2553 | default: | ||
2554 | return -1; | ||
2555 | } | ||
2556 | } else { | ||
2557 | switch (pref) { | ||
2558 | case 0: /* WC */ | ||
2559 | break; | ||
2560 | case 1: /* MADI */ | ||
2561 | hdspm->control_register |= HDSPM_SyncRef0; | ||
2562 | break; | ||
2563 | case 2: /* SYNC_IN */ | ||
2564 | hdspm->control_register |= | ||
2565 | HDSPM_SyncRef0+HDSPM_SyncRef1; | ||
2566 | break; | ||
2567 | default: | ||
2568 | return -1; | ||
2569 | } | ||
2570 | } | ||
2571 | |||
2572 | break; | ||
2573 | |||
2574 | case RayDAT: | ||
2575 | if (hdspm->tco) { | ||
2576 | switch (pref) { | ||
2577 | case 0: p = 0; break; /* WC */ | ||
2578 | case 1: p = 3; break; /* ADAT 1 */ | ||
2579 | case 2: p = 4; break; /* ADAT 2 */ | ||
2580 | case 3: p = 5; break; /* ADAT 3 */ | ||
2581 | case 4: p = 6; break; /* ADAT 4 */ | ||
2582 | case 5: p = 1; break; /* AES */ | ||
2583 | case 6: p = 2; break; /* SPDIF */ | ||
2584 | case 7: p = 9; break; /* TCO */ | ||
2585 | case 8: p = 10; break; /* SYNC_IN */ | ||
2586 | default: return -1; | ||
2587 | } | ||
2588 | } else { | ||
2589 | switch (pref) { | ||
2590 | case 0: p = 0; break; /* WC */ | ||
2591 | case 1: p = 3; break; /* ADAT 1 */ | ||
2592 | case 2: p = 4; break; /* ADAT 2 */ | ||
2593 | case 3: p = 5; break; /* ADAT 3 */ | ||
2594 | case 4: p = 6; break; /* ADAT 4 */ | ||
2595 | case 5: p = 1; break; /* AES */ | ||
2596 | case 6: p = 2; break; /* SPDIF */ | ||
2597 | case 7: p = 10; break; /* SYNC_IN */ | ||
2598 | default: return -1; | ||
2599 | } | ||
2600 | } | ||
2601 | break; | ||
2602 | |||
2603 | case AIO: | ||
2604 | if (hdspm->tco) { | ||
2605 | switch (pref) { | ||
2606 | case 0: p = 0; break; /* WC */ | ||
2607 | case 1: p = 3; break; /* ADAT */ | ||
2608 | case 2: p = 1; break; /* AES */ | ||
2609 | case 3: p = 2; break; /* SPDIF */ | ||
2610 | case 4: p = 9; break; /* TCO */ | ||
2611 | case 5: p = 10; break; /* SYNC_IN */ | ||
2612 | default: return -1; | ||
2613 | } | ||
2614 | } else { | ||
2615 | switch (pref) { | ||
2616 | case 0: p = 0; break; /* WC */ | ||
2617 | case 1: p = 3; break; /* ADAT */ | ||
2618 | case 2: p = 1; break; /* AES */ | ||
2619 | case 3: p = 2; break; /* SPDIF */ | ||
2620 | case 4: p = 10; break; /* SYNC_IN */ | ||
2621 | default: return -1; | ||
2622 | } | ||
2623 | } | ||
2624 | break; | ||
1706 | } | 2625 | } |
1707 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 2626 | |
2627 | switch (hdspm->io_type) { | ||
2628 | case RayDAT: | ||
2629 | case AIO: | ||
2630 | hdspm->settings_register &= ~HDSPM_c0_SyncRefMask; | ||
2631 | hdspm->settings_register |= HDSPM_c0_SyncRef0 * p; | ||
2632 | hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); | ||
2633 | break; | ||
2634 | |||
2635 | case MADI: | ||
2636 | case MADIface: | ||
2637 | case AES32: | ||
2638 | hdspm_write(hdspm, HDSPM_controlRegister, | ||
2639 | hdspm->control_register); | ||
2640 | } | ||
2641 | |||
1708 | return 0; | 2642 | return 0; |
1709 | } | 2643 | } |
1710 | 2644 | ||
2645 | |||
1711 | static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, | 2646 | static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, |
1712 | struct snd_ctl_elem_info *uinfo) | 2647 | struct snd_ctl_elem_info *uinfo) |
1713 | { | 2648 | { |
1714 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2649 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1715 | 2650 | ||
1716 | if (hdspm->is_aes32) { | 2651 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1717 | static char *texts[] = { "Word", "AES1", "AES2", "AES3", | 2652 | uinfo->count = 1; |
1718 | "AES4", "AES5", "AES6", "AES7", "AES8" }; | 2653 | uinfo->value.enumerated.items = hdspm->texts_autosync_items; |
1719 | |||
1720 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
1721 | uinfo->count = 1; | ||
1722 | |||
1723 | uinfo->value.enumerated.items = 9; | ||
1724 | |||
1725 | if (uinfo->value.enumerated.item >= | ||
1726 | uinfo->value.enumerated.items) | ||
1727 | uinfo->value.enumerated.item = | ||
1728 | uinfo->value.enumerated.items - 1; | ||
1729 | strcpy(uinfo->value.enumerated.name, | ||
1730 | texts[uinfo->value.enumerated.item]); | ||
1731 | } else { | ||
1732 | static char *texts[] = { "Word", "MADI" }; | ||
1733 | 2654 | ||
1734 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2655 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
1735 | uinfo->count = 1; | 2656 | uinfo->value.enumerated.item = |
2657 | uinfo->value.enumerated.items - 1; | ||
1736 | 2658 | ||
1737 | uinfo->value.enumerated.items = 2; | 2659 | strcpy(uinfo->value.enumerated.name, |
2660 | hdspm->texts_autosync[uinfo->value.enumerated.item]); | ||
1738 | 2661 | ||
1739 | if (uinfo->value.enumerated.item >= | ||
1740 | uinfo->value.enumerated.items) | ||
1741 | uinfo->value.enumerated.item = | ||
1742 | uinfo->value.enumerated.items - 1; | ||
1743 | strcpy(uinfo->value.enumerated.name, | ||
1744 | texts[uinfo->value.enumerated.item]); | ||
1745 | } | ||
1746 | return 0; | 2662 | return 0; |
1747 | } | 2663 | } |
1748 | 2664 | ||
@@ -1750,32 +2666,41 @@ static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1750 | struct snd_ctl_elem_value *ucontrol) | 2666 | struct snd_ctl_elem_value *ucontrol) |
1751 | { | 2667 | { |
1752 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2668 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2669 | int psf = hdspm_pref_sync_ref(hdspm); | ||
1753 | 2670 | ||
1754 | ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm); | 2671 | if (psf >= 0) { |
1755 | return 0; | 2672 | ucontrol->value.enumerated.item[0] = psf; |
2673 | return 0; | ||
2674 | } | ||
2675 | |||
2676 | return -1; | ||
1756 | } | 2677 | } |
1757 | 2678 | ||
1758 | static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, | 2679 | static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, |
1759 | struct snd_ctl_elem_value *ucontrol) | 2680 | struct snd_ctl_elem_value *ucontrol) |
1760 | { | 2681 | { |
1761 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2682 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1762 | int change, max; | 2683 | int val, change = 0; |
1763 | unsigned int val; | ||
1764 | |||
1765 | max = hdspm->is_aes32 ? 9 : 2; | ||
1766 | 2684 | ||
1767 | if (!snd_hdspm_use_is_exclusive(hdspm)) | 2685 | if (!snd_hdspm_use_is_exclusive(hdspm)) |
1768 | return -EBUSY; | 2686 | return -EBUSY; |
1769 | 2687 | ||
1770 | val = ucontrol->value.enumerated.item[0] % max; | 2688 | val = ucontrol->value.enumerated.item[0]; |
2689 | |||
2690 | if (val < 0) | ||
2691 | val = 0; | ||
2692 | else if (val >= hdspm->texts_autosync_items) | ||
2693 | val = hdspm->texts_autosync_items-1; | ||
1771 | 2694 | ||
1772 | spin_lock_irq(&hdspm->lock); | 2695 | spin_lock_irq(&hdspm->lock); |
1773 | change = (int) val != hdspm_pref_sync_ref(hdspm); | 2696 | if (val != hdspm_pref_sync_ref(hdspm)) |
1774 | hdspm_set_pref_sync_ref(hdspm, val); | 2697 | change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0; |
2698 | |||
1775 | spin_unlock_irq(&hdspm->lock); | 2699 | spin_unlock_irq(&hdspm->lock); |
1776 | return change; | 2700 | return change; |
1777 | } | 2701 | } |
1778 | 2702 | ||
2703 | |||
1779 | #define HDSPM_AUTOSYNC_REF(xname, xindex) \ | 2704 | #define HDSPM_AUTOSYNC_REF(xname, xindex) \ |
1780 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2705 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1781 | .name = xname, \ | 2706 | .name = xname, \ |
@@ -1785,18 +2710,18 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol, | |||
1785 | .get = snd_hdspm_get_autosync_ref, \ | 2710 | .get = snd_hdspm_get_autosync_ref, \ |
1786 | } | 2711 | } |
1787 | 2712 | ||
1788 | static int hdspm_autosync_ref(struct hdspm * hdspm) | 2713 | static int hdspm_autosync_ref(struct hdspm *hdspm) |
1789 | { | 2714 | { |
1790 | if (hdspm->is_aes32) { | 2715 | if (AES32 == hdspm->io_type) { |
1791 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); | 2716 | unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); |
1792 | unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & | 2717 | unsigned int syncref = |
1793 | 0xF; | 2718 | (status >> HDSPM_AES32_syncref_bit) & 0xF; |
1794 | if (syncref == 0) | 2719 | if (syncref == 0) |
1795 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; | 2720 | return HDSPM_AES32_AUTOSYNC_FROM_WORD; |
1796 | if (syncref <= 8) | 2721 | if (syncref <= 8) |
1797 | return syncref; | 2722 | return syncref; |
1798 | return HDSPM_AES32_AUTOSYNC_FROM_NONE; | 2723 | return HDSPM_AES32_AUTOSYNC_FROM_NONE; |
1799 | } else { | 2724 | } else if (MADI == hdspm->io_type) { |
1800 | /* This looks at the autosync selected sync reference */ | 2725 | /* This looks at the autosync selected sync reference */ |
1801 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 2726 | unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
1802 | 2727 | ||
@@ -1805,22 +2730,27 @@ static int hdspm_autosync_ref(struct hdspm * hdspm) | |||
1805 | return HDSPM_AUTOSYNC_FROM_WORD; | 2730 | return HDSPM_AUTOSYNC_FROM_WORD; |
1806 | case HDSPM_SelSyncRef_MADI: | 2731 | case HDSPM_SelSyncRef_MADI: |
1807 | return HDSPM_AUTOSYNC_FROM_MADI; | 2732 | return HDSPM_AUTOSYNC_FROM_MADI; |
2733 | case HDSPM_SelSyncRef_TCO: | ||
2734 | return HDSPM_AUTOSYNC_FROM_TCO; | ||
2735 | case HDSPM_SelSyncRef_SyncIn: | ||
2736 | return HDSPM_AUTOSYNC_FROM_SYNC_IN; | ||
1808 | case HDSPM_SelSyncRef_NVALID: | 2737 | case HDSPM_SelSyncRef_NVALID: |
1809 | return HDSPM_AUTOSYNC_FROM_NONE; | 2738 | return HDSPM_AUTOSYNC_FROM_NONE; |
1810 | default: | 2739 | default: |
1811 | return 0; | 2740 | return 0; |
1812 | } | 2741 | } |
1813 | 2742 | ||
1814 | return 0; | ||
1815 | } | 2743 | } |
2744 | return 0; | ||
1816 | } | 2745 | } |
1817 | 2746 | ||
2747 | |||
1818 | static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, | 2748 | static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, |
1819 | struct snd_ctl_elem_info *uinfo) | 2749 | struct snd_ctl_elem_info *uinfo) |
1820 | { | 2750 | { |
1821 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 2751 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
1822 | 2752 | ||
1823 | if (hdspm->is_aes32) { | 2753 | if (AES32 == hdspm->io_type) { |
1824 | static char *texts[] = { "WordClock", "AES1", "AES2", "AES3", | 2754 | static char *texts[] = { "WordClock", "AES1", "AES2", "AES3", |
1825 | "AES4", "AES5", "AES6", "AES7", "AES8", "None"}; | 2755 | "AES4", "AES5", "AES6", "AES7", "AES8", "None"}; |
1826 | 2756 | ||
@@ -1833,14 +2763,15 @@ static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1833 | uinfo->value.enumerated.items - 1; | 2763 | uinfo->value.enumerated.items - 1; |
1834 | strcpy(uinfo->value.enumerated.name, | 2764 | strcpy(uinfo->value.enumerated.name, |
1835 | texts[uinfo->value.enumerated.item]); | 2765 | texts[uinfo->value.enumerated.item]); |
1836 | } else { | 2766 | } else if (MADI == hdspm->io_type) { |
1837 | static char *texts[] = { "WordClock", "MADI", "None" }; | 2767 | static char *texts[] = {"Word Clock", "MADI", "TCO", |
2768 | "Sync In", "None" }; | ||
1838 | 2769 | ||
1839 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 2770 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1840 | uinfo->count = 1; | 2771 | uinfo->count = 1; |
1841 | uinfo->value.enumerated.items = 3; | 2772 | uinfo->value.enumerated.items = 5; |
1842 | if (uinfo->value.enumerated.item >= | 2773 | if (uinfo->value.enumerated.item >= |
1843 | uinfo->value.enumerated.items) | 2774 | uinfo->value.enumerated.items) |
1844 | uinfo->value.enumerated.item = | 2775 | uinfo->value.enumerated.item = |
1845 | uinfo->value.enumerated.items - 1; | 2776 | uinfo->value.enumerated.items - 1; |
1846 | strcpy(uinfo->value.enumerated.name, | 2777 | strcpy(uinfo->value.enumerated.name, |
@@ -1858,6 +2789,7 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol, | |||
1858 | return 0; | 2789 | return 0; |
1859 | } | 2790 | } |
1860 | 2791 | ||
2792 | |||
1861 | #define HDSPM_LINE_OUT(xname, xindex) \ | 2793 | #define HDSPM_LINE_OUT(xname, xindex) \ |
1862 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2794 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1863 | .name = xname, \ | 2795 | .name = xname, \ |
@@ -1914,6 +2846,7 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol, | |||
1914 | return change; | 2846 | return change; |
1915 | } | 2847 | } |
1916 | 2848 | ||
2849 | |||
1917 | #define HDSPM_TX_64(xname, xindex) \ | 2850 | #define HDSPM_TX_64(xname, xindex) \ |
1918 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2851 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1919 | .name = xname, \ | 2852 | .name = xname, \ |
@@ -1969,6 +2902,7 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol, | |||
1969 | return change; | 2902 | return change; |
1970 | } | 2903 | } |
1971 | 2904 | ||
2905 | |||
1972 | #define HDSPM_C_TMS(xname, xindex) \ | 2906 | #define HDSPM_C_TMS(xname, xindex) \ |
1973 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2907 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
1974 | .name = xname, \ | 2908 | .name = xname, \ |
@@ -2024,6 +2958,7 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol, | |||
2024 | return change; | 2958 | return change; |
2025 | } | 2959 | } |
2026 | 2960 | ||
2961 | |||
2027 | #define HDSPM_SAFE_MODE(xname, xindex) \ | 2962 | #define HDSPM_SAFE_MODE(xname, xindex) \ |
2028 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 2963 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2029 | .name = xname, \ | 2964 | .name = xname, \ |
@@ -2079,6 +3014,7 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol, | |||
2079 | return change; | 3014 | return change; |
2080 | } | 3015 | } |
2081 | 3016 | ||
3017 | |||
2082 | #define HDSPM_EMPHASIS(xname, xindex) \ | 3018 | #define HDSPM_EMPHASIS(xname, xindex) \ |
2083 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3019 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2084 | .name = xname, \ | 3020 | .name = xname, \ |
@@ -2134,6 +3070,7 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol, | |||
2134 | return change; | 3070 | return change; |
2135 | } | 3071 | } |
2136 | 3072 | ||
3073 | |||
2137 | #define HDSPM_DOLBY(xname, xindex) \ | 3074 | #define HDSPM_DOLBY(xname, xindex) \ |
2138 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3075 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2139 | .name = xname, \ | 3076 | .name = xname, \ |
@@ -2189,6 +3126,7 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol, | |||
2189 | return change; | 3126 | return change; |
2190 | } | 3127 | } |
2191 | 3128 | ||
3129 | |||
2192 | #define HDSPM_PROFESSIONAL(xname, xindex) \ | 3130 | #define HDSPM_PROFESSIONAL(xname, xindex) \ |
2193 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3131 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2194 | .name = xname, \ | 3132 | .name = xname, \ |
@@ -2315,6 +3253,7 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol, | |||
2315 | return change; | 3253 | return change; |
2316 | } | 3254 | } |
2317 | 3255 | ||
3256 | |||
2318 | #define HDSPM_DS_WIRE(xname, xindex) \ | 3257 | #define HDSPM_DS_WIRE(xname, xindex) \ |
2319 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3258 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2320 | .name = xname, \ | 3259 | .name = xname, \ |
@@ -2386,6 +3325,7 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol, | |||
2386 | return change; | 3325 | return change; |
2387 | } | 3326 | } |
2388 | 3327 | ||
3328 | |||
2389 | #define HDSPM_QS_WIRE(xname, xindex) \ | 3329 | #define HDSPM_QS_WIRE(xname, xindex) \ |
2390 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3330 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2391 | .name = xname, \ | 3331 | .name = xname, \ |
@@ -2472,15 +3412,6 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol, | |||
2472 | return change; | 3412 | return change; |
2473 | } | 3413 | } |
2474 | 3414 | ||
2475 | /* Simple Mixer | ||
2476 | deprecated since to much faders ??? | ||
2477 | MIXER interface says output (source, destination, value) | ||
2478 | where source > MAX_channels are playback channels | ||
2479 | on MADICARD | ||
2480 | - playback mixer matrix: [channelout+64] [output] [value] | ||
2481 | - input(thru) mixer matrix: [channelin] [output] [value] | ||
2482 | (better do 2 kontrols for separation ?) | ||
2483 | */ | ||
2484 | 3415 | ||
2485 | #define HDSPM_MIXER(xname, xindex) \ | 3416 | #define HDSPM_MIXER(xname, xindex) \ |
2486 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ | 3417 | { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \ |
@@ -2586,7 +3517,7 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol, | |||
2586 | 3517 | ||
2587 | /* The simple mixer control(s) provide gain control for the | 3518 | /* The simple mixer control(s) provide gain control for the |
2588 | basic 1:1 mappings of playback streams to output | 3519 | basic 1:1 mappings of playback streams to output |
2589 | streams. | 3520 | streams. |
2590 | */ | 3521 | */ |
2591 | 3522 | ||
2592 | #define HDSPM_PLAYBACK_MIXER \ | 3523 | #define HDSPM_PLAYBACK_MIXER \ |
@@ -2604,7 +3535,7 @@ static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2604 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 3535 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
2605 | uinfo->count = 1; | 3536 | uinfo->count = 1; |
2606 | uinfo->value.integer.min = 0; | 3537 | uinfo->value.integer.min = 0; |
2607 | uinfo->value.integer.max = 65536; | 3538 | uinfo->value.integer.max = 64; |
2608 | uinfo->value.integer.step = 1; | 3539 | uinfo->value.integer.step = 1; |
2609 | return 0; | 3540 | return 0; |
2610 | } | 3541 | } |
@@ -2614,28 +3545,17 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2614 | { | 3545 | { |
2615 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 3546 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2616 | int channel; | 3547 | int channel; |
2617 | int mapped_channel; | ||
2618 | 3548 | ||
2619 | channel = ucontrol->id.index - 1; | 3549 | channel = ucontrol->id.index - 1; |
2620 | 3550 | ||
2621 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) | 3551 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) |
2622 | return -EINVAL; | 3552 | return -EINVAL; |
2623 | 3553 | ||
2624 | mapped_channel = hdspm->channel_map[channel]; | ||
2625 | if (mapped_channel < 0) | ||
2626 | return -EINVAL; | ||
2627 | |||
2628 | spin_lock_irq(&hdspm->lock); | 3554 | spin_lock_irq(&hdspm->lock); |
2629 | ucontrol->value.integer.value[0] = | 3555 | ucontrol->value.integer.value[0] = |
2630 | hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel); | 3556 | (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN; |
2631 | spin_unlock_irq(&hdspm->lock); | 3557 | spin_unlock_irq(&hdspm->lock); |
2632 | 3558 | ||
2633 | /* | ||
2634 | snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, " | ||
2635 | "value %d\n", | ||
2636 | ucontrol->id.index, channel, mapped_channel, | ||
2637 | ucontrol->value.integer.value[0]); | ||
2638 | */ | ||
2639 | return 0; | 3559 | return 0; |
2640 | } | 3560 | } |
2641 | 3561 | ||
@@ -2645,7 +3565,6 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2645 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 3565 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2646 | int change; | 3566 | int change; |
2647 | int channel; | 3567 | int channel; |
2648 | int mapped_channel; | ||
2649 | int gain; | 3568 | int gain; |
2650 | 3569 | ||
2651 | if (!snd_hdspm_use_is_exclusive(hdspm)) | 3570 | if (!snd_hdspm_use_is_exclusive(hdspm)) |
@@ -2656,59 +3575,60 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol, | |||
2656 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) | 3575 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) |
2657 | return -EINVAL; | 3576 | return -EINVAL; |
2658 | 3577 | ||
2659 | mapped_channel = hdspm->channel_map[channel]; | 3578 | gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64; |
2660 | if (mapped_channel < 0) | ||
2661 | return -EINVAL; | ||
2662 | |||
2663 | gain = ucontrol->value.integer.value[0]; | ||
2664 | 3579 | ||
2665 | spin_lock_irq(&hdspm->lock); | 3580 | spin_lock_irq(&hdspm->lock); |
2666 | change = | 3581 | change = |
2667 | gain != hdspm_read_pb_gain(hdspm, mapped_channel, | 3582 | gain != hdspm_read_pb_gain(hdspm, channel, |
2668 | mapped_channel); | 3583 | channel); |
2669 | if (change) | 3584 | if (change) |
2670 | hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel, | 3585 | hdspm_write_pb_gain(hdspm, channel, channel, |
2671 | gain); | 3586 | gain); |
2672 | spin_unlock_irq(&hdspm->lock); | 3587 | spin_unlock_irq(&hdspm->lock); |
2673 | return change; | 3588 | return change; |
2674 | } | 3589 | } |
2675 | 3590 | ||
2676 | #define HDSPM_WC_SYNC_CHECK(xname, xindex) \ | 3591 | #define HDSPM_SYNC_CHECK(xname, xindex) \ |
2677 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3592 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
2678 | .name = xname, \ | 3593 | .name = xname, \ |
2679 | .index = xindex, \ | 3594 | .private_value = xindex, \ |
2680 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | 3595 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ |
2681 | .info = snd_hdspm_info_sync_check, \ | 3596 | .info = snd_hdspm_info_sync_check, \ |
2682 | .get = snd_hdspm_get_wc_sync_check \ | 3597 | .get = snd_hdspm_get_sync_check \ |
2683 | } | 3598 | } |
2684 | 3599 | ||
3600 | |||
2685 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, | 3601 | static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol, |
2686 | struct snd_ctl_elem_info *uinfo) | 3602 | struct snd_ctl_elem_info *uinfo) |
2687 | { | 3603 | { |
2688 | static char *texts[] = { "No Lock", "Lock", "Sync" }; | 3604 | static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" }; |
2689 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 3605 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
2690 | uinfo->count = 1; | 3606 | uinfo->count = 1; |
2691 | uinfo->value.enumerated.items = 3; | 3607 | uinfo->value.enumerated.items = 4; |
2692 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | 3608 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) |
2693 | uinfo->value.enumerated.item = | 3609 | uinfo->value.enumerated.item = |
2694 | uinfo->value.enumerated.items - 1; | 3610 | uinfo->value.enumerated.items - 1; |
2695 | strcpy(uinfo->value.enumerated.name, | 3611 | strcpy(uinfo->value.enumerated.name, |
2696 | texts[uinfo->value.enumerated.item]); | 3612 | texts[uinfo->value.enumerated.item]); |
2697 | return 0; | 3613 | return 0; |
2698 | } | 3614 | } |
2699 | 3615 | ||
2700 | static int hdspm_wc_sync_check(struct hdspm * hdspm) | 3616 | static int hdspm_wc_sync_check(struct hdspm *hdspm) |
2701 | { | 3617 | { |
2702 | if (hdspm->is_aes32) { | 3618 | int status, status2; |
2703 | int status = hdspm_read(hdspm, HDSPM_statusRegister); | 3619 | |
2704 | if (status & HDSPM_AES32_wcLock) { | 3620 | switch (hdspm->io_type) { |
2705 | /* I don't know how to differenciate sync from lock. | 3621 | case AES32: |
2706 | Doing as if sync for now */ | 3622 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
3623 | if (status & HDSPM_wcSync) | ||
2707 | return 2; | 3624 | return 2; |
2708 | } | 3625 | else if (status & HDSPM_wcLock) |
3626 | return 1; | ||
2709 | return 0; | 3627 | return 0; |
2710 | } else { | 3628 | break; |
2711 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 3629 | |
3630 | case MADI: | ||
3631 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
2712 | if (status2 & HDSPM_wcLock) { | 3632 | if (status2 & HDSPM_wcLock) { |
2713 | if (status2 & HDSPM_wcSync) | 3633 | if (status2 & HDSPM_wcSync) |
2714 | return 2; | 3634 | return 2; |
@@ -2716,29 +3636,30 @@ static int hdspm_wc_sync_check(struct hdspm * hdspm) | |||
2716 | return 1; | 3636 | return 1; |
2717 | } | 3637 | } |
2718 | return 0; | 3638 | return 0; |
2719 | } | 3639 | break; |
2720 | } | ||
2721 | 3640 | ||
2722 | static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol, | 3641 | case RayDAT: |
2723 | struct snd_ctl_elem_value *ucontrol) | 3642 | case AIO: |
2724 | { | 3643 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
2725 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
2726 | 3644 | ||
2727 | ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm); | 3645 | if (status & 0x2000000) |
2728 | return 0; | 3646 | return 2; |
2729 | } | 3647 | else if (status & 0x1000000) |
3648 | return 1; | ||
3649 | return 0; | ||
2730 | 3650 | ||
3651 | break; | ||
2731 | 3652 | ||
2732 | #define HDSPM_MADI_SYNC_CHECK(xname, xindex) \ | 3653 | case MADIface: |
2733 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3654 | break; |
2734 | .name = xname, \ | 3655 | } |
2735 | .index = xindex, \ | 3656 | |
2736 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | 3657 | |
2737 | .info = snd_hdspm_info_sync_check, \ | 3658 | return 3; |
2738 | .get = snd_hdspm_get_madisync_sync_check \ | ||
2739 | } | 3659 | } |
2740 | 3660 | ||
2741 | static int hdspm_madisync_sync_check(struct hdspm * hdspm) | 3661 | |
3662 | static int hdspm_madi_sync_check(struct hdspm *hdspm) | ||
2742 | { | 3663 | { |
2743 | int status = hdspm_read(hdspm, HDSPM_statusRegister); | 3664 | int status = hdspm_read(hdspm, HDSPM_statusRegister); |
2744 | if (status & HDSPM_madiLock) { | 3665 | if (status & HDSPM_madiLock) { |
@@ -2750,89 +3671,726 @@ static int hdspm_madisync_sync_check(struct hdspm * hdspm) | |||
2750 | return 0; | 3671 | return 0; |
2751 | } | 3672 | } |
2752 | 3673 | ||
2753 | static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol, | 3674 | |
2754 | struct snd_ctl_elem_value * | 3675 | static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx) |
2755 | ucontrol) | ||
2756 | { | 3676 | { |
2757 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 3677 | int status, lock, sync; |
3678 | |||
3679 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
3680 | |||
3681 | lock = (status & (0x1<<idx)) ? 1 : 0; | ||
3682 | sync = (status & (0x100<<idx)) ? 1 : 0; | ||
2758 | 3683 | ||
2759 | ucontrol->value.enumerated.item[0] = | 3684 | if (lock && sync) |
2760 | hdspm_madisync_sync_check(hdspm); | 3685 | return 2; |
3686 | else if (lock) | ||
3687 | return 1; | ||
2761 | return 0; | 3688 | return 0; |
2762 | } | 3689 | } |
2763 | 3690 | ||
2764 | 3691 | ||
2765 | #define HDSPM_AES_SYNC_CHECK(xname, xindex) \ | 3692 | static int hdspm_sync_in_sync_check(struct hdspm *hdspm) |
2766 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 3693 | { |
2767 | .name = xname, \ | 3694 | int status, lock = 0, sync = 0; |
2768 | .index = xindex, \ | 3695 | |
2769 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | 3696 | switch (hdspm->io_type) { |
2770 | .info = snd_hdspm_info_sync_check, \ | 3697 | case RayDAT: |
2771 | .get = snd_hdspm_get_aes_sync_check \ | 3698 | case AIO: |
3699 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_3); | ||
3700 | lock = (status & 0x400) ? 1 : 0; | ||
3701 | sync = (status & 0x800) ? 1 : 0; | ||
3702 | break; | ||
3703 | |||
3704 | case MADI: | ||
3705 | case AES32: | ||
3706 | status = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
3707 | lock = (status & HDSPM_syncInLock) ? 1 : 0; | ||
3708 | sync = (status & HDSPM_syncInSync) ? 1 : 0; | ||
3709 | break; | ||
3710 | |||
3711 | case MADIface: | ||
3712 | break; | ||
3713 | } | ||
3714 | |||
3715 | if (lock && sync) | ||
3716 | return 2; | ||
3717 | else if (lock) | ||
3718 | return 1; | ||
3719 | |||
3720 | return 0; | ||
2772 | } | 3721 | } |
2773 | 3722 | ||
2774 | static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx) | 3723 | static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx) |
2775 | { | 3724 | { |
2776 | int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 3725 | int status2, lock, sync; |
2777 | if (status2 & (HDSPM_LockAES >> idx)) { | 3726 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
2778 | /* I don't know how to differenciate sync from lock. | 3727 | |
2779 | Doing as if sync for now */ | 3728 | lock = (status2 & (0x0080 >> idx)) ? 1 : 0; |
3729 | sync = (status2 & (0x8000 >> idx)) ? 1 : 0; | ||
3730 | |||
3731 | if (sync) | ||
2780 | return 2; | 3732 | return 2; |
3733 | else if (lock) | ||
3734 | return 1; | ||
3735 | return 0; | ||
3736 | } | ||
3737 | |||
3738 | |||
3739 | static int hdspm_tco_sync_check(struct hdspm *hdspm) | ||
3740 | { | ||
3741 | int status; | ||
3742 | |||
3743 | if (hdspm->tco) { | ||
3744 | switch (hdspm->io_type) { | ||
3745 | case MADI: | ||
3746 | case AES32: | ||
3747 | status = hdspm_read(hdspm, HDSPM_statusRegister); | ||
3748 | if (status & HDSPM_tcoLock) { | ||
3749 | if (status & HDSPM_tcoSync) | ||
3750 | return 2; | ||
3751 | else | ||
3752 | return 1; | ||
3753 | } | ||
3754 | return 0; | ||
3755 | |||
3756 | break; | ||
3757 | |||
3758 | case RayDAT: | ||
3759 | case AIO: | ||
3760 | status = hdspm_read(hdspm, HDSPM_RD_STATUS_1); | ||
3761 | |||
3762 | if (status & 0x8000000) | ||
3763 | return 2; /* Sync */ | ||
3764 | if (status & 0x4000000) | ||
3765 | return 1; /* Lock */ | ||
3766 | return 0; /* No signal */ | ||
3767 | break; | ||
3768 | |||
3769 | default: | ||
3770 | break; | ||
3771 | } | ||
3772 | } | ||
3773 | |||
3774 | return 3; /* N/A */ | ||
3775 | } | ||
3776 | |||
3777 | |||
3778 | static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol, | ||
3779 | struct snd_ctl_elem_value *ucontrol) | ||
3780 | { | ||
3781 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3782 | int val = -1; | ||
3783 | |||
3784 | switch (hdspm->io_type) { | ||
3785 | case RayDAT: | ||
3786 | switch (kcontrol->private_value) { | ||
3787 | case 0: /* WC */ | ||
3788 | val = hdspm_wc_sync_check(hdspm); break; | ||
3789 | case 7: /* TCO */ | ||
3790 | val = hdspm_tco_sync_check(hdspm); break; | ||
3791 | case 8: /* SYNC IN */ | ||
3792 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3793 | default: | ||
3794 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); | ||
3795 | } | ||
3796 | |||
3797 | case AIO: | ||
3798 | switch (kcontrol->private_value) { | ||
3799 | case 0: /* WC */ | ||
3800 | val = hdspm_wc_sync_check(hdspm); break; | ||
3801 | case 4: /* TCO */ | ||
3802 | val = hdspm_tco_sync_check(hdspm); break; | ||
3803 | case 5: /* SYNC IN */ | ||
3804 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3805 | default: | ||
3806 | val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1); | ||
3807 | } | ||
3808 | |||
3809 | case MADI: | ||
3810 | switch (kcontrol->private_value) { | ||
3811 | case 0: /* WC */ | ||
3812 | val = hdspm_wc_sync_check(hdspm); break; | ||
3813 | case 1: /* MADI */ | ||
3814 | val = hdspm_madi_sync_check(hdspm); break; | ||
3815 | case 2: /* TCO */ | ||
3816 | val = hdspm_tco_sync_check(hdspm); break; | ||
3817 | case 3: /* SYNC_IN */ | ||
3818 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3819 | } | ||
3820 | |||
3821 | case MADIface: | ||
3822 | val = hdspm_madi_sync_check(hdspm); /* MADI */ | ||
3823 | break; | ||
3824 | |||
3825 | case AES32: | ||
3826 | switch (kcontrol->private_value) { | ||
3827 | case 0: /* WC */ | ||
3828 | val = hdspm_wc_sync_check(hdspm); break; | ||
3829 | case 9: /* TCO */ | ||
3830 | val = hdspm_tco_sync_check(hdspm); break; | ||
3831 | case 10 /* SYNC IN */: | ||
3832 | val = hdspm_sync_in_sync_check(hdspm); break; | ||
3833 | default: /* AES1 to AES8 */ | ||
3834 | val = hdspm_aes_sync_check(hdspm, | ||
3835 | kcontrol->private_value-1); | ||
3836 | } | ||
3837 | |||
2781 | } | 3838 | } |
3839 | |||
3840 | if (-1 == val) | ||
3841 | val = 3; | ||
3842 | |||
3843 | ucontrol->value.enumerated.item[0] = val; | ||
2782 | return 0; | 3844 | return 0; |
2783 | } | 3845 | } |
2784 | 3846 | ||
2785 | static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol, | 3847 | |
3848 | |||
3849 | /** | ||
3850 | * TCO controls | ||
3851 | **/ | ||
3852 | static void hdspm_tco_write(struct hdspm *hdspm) | ||
3853 | { | ||
3854 | unsigned int tc[4] = { 0, 0, 0, 0}; | ||
3855 | |||
3856 | switch (hdspm->tco->input) { | ||
3857 | case 0: | ||
3858 | tc[2] |= HDSPM_TCO2_set_input_MSB; | ||
3859 | break; | ||
3860 | case 1: | ||
3861 | tc[2] |= HDSPM_TCO2_set_input_LSB; | ||
3862 | break; | ||
3863 | default: | ||
3864 | break; | ||
3865 | } | ||
3866 | |||
3867 | switch (hdspm->tco->framerate) { | ||
3868 | case 1: | ||
3869 | tc[1] |= HDSPM_TCO1_LTC_Format_LSB; | ||
3870 | break; | ||
3871 | case 2: | ||
3872 | tc[1] |= HDSPM_TCO1_LTC_Format_MSB; | ||
3873 | break; | ||
3874 | case 3: | ||
3875 | tc[1] |= HDSPM_TCO1_LTC_Format_MSB + | ||
3876 | HDSPM_TCO1_set_drop_frame_flag; | ||
3877 | break; | ||
3878 | case 4: | ||
3879 | tc[1] |= HDSPM_TCO1_LTC_Format_LSB + | ||
3880 | HDSPM_TCO1_LTC_Format_MSB; | ||
3881 | break; | ||
3882 | case 5: | ||
3883 | tc[1] |= HDSPM_TCO1_LTC_Format_LSB + | ||
3884 | HDSPM_TCO1_LTC_Format_MSB + | ||
3885 | HDSPM_TCO1_set_drop_frame_flag; | ||
3886 | break; | ||
3887 | default: | ||
3888 | break; | ||
3889 | } | ||
3890 | |||
3891 | switch (hdspm->tco->wordclock) { | ||
3892 | case 1: | ||
3893 | tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB; | ||
3894 | break; | ||
3895 | case 2: | ||
3896 | tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB; | ||
3897 | break; | ||
3898 | default: | ||
3899 | break; | ||
3900 | } | ||
3901 | |||
3902 | switch (hdspm->tco->samplerate) { | ||
3903 | case 1: | ||
3904 | tc[2] |= HDSPM_TCO2_set_freq; | ||
3905 | break; | ||
3906 | case 2: | ||
3907 | tc[2] |= HDSPM_TCO2_set_freq_from_app; | ||
3908 | break; | ||
3909 | default: | ||
3910 | break; | ||
3911 | } | ||
3912 | |||
3913 | switch (hdspm->tco->pull) { | ||
3914 | case 1: | ||
3915 | tc[2] |= HDSPM_TCO2_set_pull_up; | ||
3916 | break; | ||
3917 | case 2: | ||
3918 | tc[2] |= HDSPM_TCO2_set_pull_down; | ||
3919 | break; | ||
3920 | case 3: | ||
3921 | tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4; | ||
3922 | break; | ||
3923 | case 4: | ||
3924 | tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4; | ||
3925 | break; | ||
3926 | default: | ||
3927 | break; | ||
3928 | } | ||
3929 | |||
3930 | if (1 == hdspm->tco->term) { | ||
3931 | tc[2] |= HDSPM_TCO2_set_term_75R; | ||
3932 | } | ||
3933 | |||
3934 | hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]); | ||
3935 | hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]); | ||
3936 | hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]); | ||
3937 | hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]); | ||
3938 | } | ||
3939 | |||
3940 | |||
3941 | #define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \ | ||
3942 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3943 | .name = xname, \ | ||
3944 | .index = xindex, \ | ||
3945 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
3946 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
3947 | .info = snd_hdspm_info_tco_sample_rate, \ | ||
3948 | .get = snd_hdspm_get_tco_sample_rate, \ | ||
3949 | .put = snd_hdspm_put_tco_sample_rate \ | ||
3950 | } | ||
3951 | |||
3952 | static int snd_hdspm_info_tco_sample_rate(struct snd_kcontrol *kcontrol, | ||
3953 | struct snd_ctl_elem_info *uinfo) | ||
3954 | { | ||
3955 | static char *texts[] = { "44.1 kHz", "48 kHz" }; | ||
3956 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
3957 | uinfo->count = 1; | ||
3958 | uinfo->value.enumerated.items = 2; | ||
3959 | |||
3960 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
3961 | uinfo->value.enumerated.item = | ||
3962 | uinfo->value.enumerated.items - 1; | ||
3963 | |||
3964 | strcpy(uinfo->value.enumerated.name, | ||
3965 | texts[uinfo->value.enumerated.item]); | ||
3966 | |||
3967 | return 0; | ||
3968 | } | ||
3969 | |||
3970 | static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol, | ||
3971 | struct snd_ctl_elem_value *ucontrol) | ||
3972 | { | ||
3973 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3974 | |||
3975 | ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate; | ||
3976 | |||
3977 | return 0; | ||
3978 | } | ||
3979 | |||
3980 | static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol, | ||
3981 | struct snd_ctl_elem_value *ucontrol) | ||
3982 | { | ||
3983 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
3984 | |||
3985 | if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) { | ||
3986 | hdspm->tco->samplerate = ucontrol->value.enumerated.item[0]; | ||
3987 | |||
3988 | hdspm_tco_write(hdspm); | ||
3989 | |||
3990 | return 1; | ||
3991 | } | ||
3992 | |||
3993 | return 0; | ||
3994 | } | ||
3995 | |||
3996 | |||
3997 | #define HDSPM_TCO_PULL(xname, xindex) \ | ||
3998 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
3999 | .name = xname, \ | ||
4000 | .index = xindex, \ | ||
4001 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
4002 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
4003 | .info = snd_hdspm_info_tco_pull, \ | ||
4004 | .get = snd_hdspm_get_tco_pull, \ | ||
4005 | .put = snd_hdspm_put_tco_pull \ | ||
4006 | } | ||
4007 | |||
4008 | static int snd_hdspm_info_tco_pull(struct snd_kcontrol *kcontrol, | ||
4009 | struct snd_ctl_elem_info *uinfo) | ||
4010 | { | ||
4011 | static char *texts[] = { "0", "+ 0.1 %", "- 0.1 %", "+ 4 %", "- 4 %" }; | ||
4012 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
4013 | uinfo->count = 1; | ||
4014 | uinfo->value.enumerated.items = 5; | ||
4015 | |||
4016 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
4017 | uinfo->value.enumerated.item = | ||
4018 | uinfo->value.enumerated.items - 1; | ||
4019 | |||
4020 | strcpy(uinfo->value.enumerated.name, | ||
4021 | texts[uinfo->value.enumerated.item]); | ||
4022 | |||
4023 | return 0; | ||
4024 | } | ||
4025 | |||
4026 | static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol, | ||
4027 | struct snd_ctl_elem_value *ucontrol) | ||
4028 | { | ||
4029 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4030 | |||
4031 | ucontrol->value.enumerated.item[0] = hdspm->tco->pull; | ||
4032 | |||
4033 | return 0; | ||
4034 | } | ||
4035 | |||
4036 | static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol, | ||
4037 | struct snd_ctl_elem_value *ucontrol) | ||
4038 | { | ||
4039 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4040 | |||
4041 | if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) { | ||
4042 | hdspm->tco->pull = ucontrol->value.enumerated.item[0]; | ||
4043 | |||
4044 | hdspm_tco_write(hdspm); | ||
4045 | |||
4046 | return 1; | ||
4047 | } | ||
4048 | |||
4049 | return 0; | ||
4050 | } | ||
4051 | |||
4052 | #define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \ | ||
4053 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4054 | .name = xname, \ | ||
4055 | .index = xindex, \ | ||
4056 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
4057 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
4058 | .info = snd_hdspm_info_tco_wck_conversion, \ | ||
4059 | .get = snd_hdspm_get_tco_wck_conversion, \ | ||
4060 | .put = snd_hdspm_put_tco_wck_conversion \ | ||
4061 | } | ||
4062 | |||
4063 | static int snd_hdspm_info_tco_wck_conversion(struct snd_kcontrol *kcontrol, | ||
4064 | struct snd_ctl_elem_info *uinfo) | ||
4065 | { | ||
4066 | static char *texts[] = { "1:1", "44.1 -> 48", "48 -> 44.1" }; | ||
4067 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
4068 | uinfo->count = 1; | ||
4069 | uinfo->value.enumerated.items = 3; | ||
4070 | |||
4071 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
4072 | uinfo->value.enumerated.item = | ||
4073 | uinfo->value.enumerated.items - 1; | ||
4074 | |||
4075 | strcpy(uinfo->value.enumerated.name, | ||
4076 | texts[uinfo->value.enumerated.item]); | ||
4077 | |||
4078 | return 0; | ||
4079 | } | ||
4080 | |||
4081 | static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol, | ||
4082 | struct snd_ctl_elem_value *ucontrol) | ||
4083 | { | ||
4084 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4085 | |||
4086 | ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock; | ||
4087 | |||
4088 | return 0; | ||
4089 | } | ||
4090 | |||
4091 | static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol, | ||
4092 | struct snd_ctl_elem_value *ucontrol) | ||
4093 | { | ||
4094 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4095 | |||
4096 | if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) { | ||
4097 | hdspm->tco->wordclock = ucontrol->value.enumerated.item[0]; | ||
4098 | |||
4099 | hdspm_tco_write(hdspm); | ||
4100 | |||
4101 | return 1; | ||
4102 | } | ||
4103 | |||
4104 | return 0; | ||
4105 | } | ||
4106 | |||
4107 | |||
4108 | #define HDSPM_TCO_FRAME_RATE(xname, xindex) \ | ||
4109 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4110 | .name = xname, \ | ||
4111 | .index = xindex, \ | ||
4112 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
4113 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
4114 | .info = snd_hdspm_info_tco_frame_rate, \ | ||
4115 | .get = snd_hdspm_get_tco_frame_rate, \ | ||
4116 | .put = snd_hdspm_put_tco_frame_rate \ | ||
4117 | } | ||
4118 | |||
4119 | static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol, | ||
4120 | struct snd_ctl_elem_info *uinfo) | ||
4121 | { | ||
4122 | static char *texts[] = { "24 fps", "25 fps", "29.97fps", | ||
4123 | "29.97 dfps", "30 fps", "30 dfps" }; | ||
4124 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
4125 | uinfo->count = 1; | ||
4126 | uinfo->value.enumerated.items = 6; | ||
4127 | |||
4128 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
4129 | uinfo->value.enumerated.item = | ||
4130 | uinfo->value.enumerated.items - 1; | ||
4131 | |||
4132 | strcpy(uinfo->value.enumerated.name, | ||
4133 | texts[uinfo->value.enumerated.item]); | ||
4134 | |||
4135 | return 0; | ||
4136 | } | ||
4137 | |||
4138 | static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol, | ||
2786 | struct snd_ctl_elem_value *ucontrol) | 4139 | struct snd_ctl_elem_value *ucontrol) |
2787 | { | 4140 | { |
2788 | int offset; | ||
2789 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | 4141 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); |
2790 | 4142 | ||
2791 | offset = ucontrol->id.index - 1; | 4143 | ucontrol->value.enumerated.item[0] = hdspm->tco->framerate; |
2792 | if (offset < 0 || offset >= 8) | ||
2793 | return -EINVAL; | ||
2794 | 4144 | ||
2795 | ucontrol->value.enumerated.item[0] = | ||
2796 | hdspm_aes_sync_check(hdspm, offset); | ||
2797 | return 0; | 4145 | return 0; |
2798 | } | 4146 | } |
2799 | 4147 | ||
4148 | static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol, | ||
4149 | struct snd_ctl_elem_value *ucontrol) | ||
4150 | { | ||
4151 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4152 | |||
4153 | if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) { | ||
4154 | hdspm->tco->framerate = ucontrol->value.enumerated.item[0]; | ||
2800 | 4155 | ||
2801 | static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | 4156 | hdspm_tco_write(hdspm); |
4157 | |||
4158 | return 1; | ||
4159 | } | ||
4160 | |||
4161 | return 0; | ||
4162 | } | ||
2802 | 4163 | ||
2803 | HDSPM_MIXER("Mixer", 0), | ||
2804 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | ||
2805 | HDSPM_CLOCK_SOURCE("Sample Clock Source", 0), | ||
2806 | 4164 | ||
4165 | #define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \ | ||
4166 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4167 | .name = xname, \ | ||
4168 | .index = xindex, \ | ||
4169 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
4170 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
4171 | .info = snd_hdspm_info_tco_sync_source, \ | ||
4172 | .get = snd_hdspm_get_tco_sync_source, \ | ||
4173 | .put = snd_hdspm_put_tco_sync_source \ | ||
4174 | } | ||
4175 | |||
4176 | static int snd_hdspm_info_tco_sync_source(struct snd_kcontrol *kcontrol, | ||
4177 | struct snd_ctl_elem_info *uinfo) | ||
4178 | { | ||
4179 | static char *texts[] = { "LTC", "Video", "WCK" }; | ||
4180 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
4181 | uinfo->count = 1; | ||
4182 | uinfo->value.enumerated.items = 3; | ||
4183 | |||
4184 | if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) | ||
4185 | uinfo->value.enumerated.item = | ||
4186 | uinfo->value.enumerated.items - 1; | ||
4187 | |||
4188 | strcpy(uinfo->value.enumerated.name, | ||
4189 | texts[uinfo->value.enumerated.item]); | ||
4190 | |||
4191 | return 0; | ||
4192 | } | ||
4193 | |||
4194 | static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol, | ||
4195 | struct snd_ctl_elem_value *ucontrol) | ||
4196 | { | ||
4197 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4198 | |||
4199 | ucontrol->value.enumerated.item[0] = hdspm->tco->input; | ||
4200 | |||
4201 | return 0; | ||
4202 | } | ||
4203 | |||
4204 | static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol, | ||
4205 | struct snd_ctl_elem_value *ucontrol) | ||
4206 | { | ||
4207 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4208 | |||
4209 | if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) { | ||
4210 | hdspm->tco->input = ucontrol->value.enumerated.item[0]; | ||
4211 | |||
4212 | hdspm_tco_write(hdspm); | ||
4213 | |||
4214 | return 1; | ||
4215 | } | ||
4216 | |||
4217 | return 0; | ||
4218 | } | ||
4219 | |||
4220 | |||
4221 | #define HDSPM_TCO_WORD_TERM(xname, xindex) \ | ||
4222 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
4223 | .name = xname, \ | ||
4224 | .index = xindex, \ | ||
4225 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
4226 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
4227 | .info = snd_hdspm_info_tco_word_term, \ | ||
4228 | .get = snd_hdspm_get_tco_word_term, \ | ||
4229 | .put = snd_hdspm_put_tco_word_term \ | ||
4230 | } | ||
4231 | |||
4232 | static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol, | ||
4233 | struct snd_ctl_elem_info *uinfo) | ||
4234 | { | ||
4235 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
4236 | uinfo->count = 1; | ||
4237 | uinfo->value.integer.min = 0; | ||
4238 | uinfo->value.integer.max = 1; | ||
4239 | |||
4240 | return 0; | ||
4241 | } | ||
4242 | |||
4243 | |||
4244 | static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol, | ||
4245 | struct snd_ctl_elem_value *ucontrol) | ||
4246 | { | ||
4247 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4248 | |||
4249 | ucontrol->value.enumerated.item[0] = hdspm->tco->term; | ||
4250 | |||
4251 | return 0; | ||
4252 | } | ||
4253 | |||
4254 | |||
4255 | static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol, | ||
4256 | struct snd_ctl_elem_value *ucontrol) | ||
4257 | { | ||
4258 | struct hdspm *hdspm = snd_kcontrol_chip(kcontrol); | ||
4259 | |||
4260 | if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) { | ||
4261 | hdspm->tco->term = ucontrol->value.enumerated.item[0]; | ||
4262 | |||
4263 | hdspm_tco_write(hdspm); | ||
4264 | |||
4265 | return 1; | ||
4266 | } | ||
4267 | |||
4268 | return 0; | ||
4269 | } | ||
4270 | |||
4271 | |||
4272 | |||
4273 | |||
4274 | static struct snd_kcontrol_new snd_hdspm_controls_madi[] = { | ||
4275 | HDSPM_MIXER("Mixer", 0), | ||
4276 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
2807 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | 4277 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
2808 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | 4278 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), |
2809 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | 4279 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), |
2810 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | 4280 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), |
2811 | /* 'External Rate' complies with the alsa control naming scheme */ | 4281 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), |
2812 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | 4282 | HDSPM_SYNC_CHECK("MADI SyncCheck", 1), |
2813 | HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0), | 4283 | HDSPM_SYNC_CHECK("TCO SyncCHeck", 2), |
2814 | HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0), | 4284 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3), |
2815 | HDSPM_LINE_OUT("Line Out", 0), | 4285 | HDSPM_LINE_OUT("Line Out", 0), |
2816 | HDSPM_TX_64("TX 64 channels mode", 0), | 4286 | HDSPM_TX_64("TX 64 channels mode", 0), |
2817 | HDSPM_C_TMS("Clear Track Marker", 0), | 4287 | HDSPM_C_TMS("Clear Track Marker", 0), |
2818 | HDSPM_SAFE_MODE("Safe Mode", 0), | 4288 | HDSPM_SAFE_MODE("Safe Mode", 0), |
2819 | HDSPM_INPUT_SELECT("Input Select", 0), | 4289 | HDSPM_INPUT_SELECT("Input Select", 0) |
2820 | }; | 4290 | }; |
2821 | 4291 | ||
2822 | static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { | ||
2823 | 4292 | ||
4293 | static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = { | ||
2824 | HDSPM_MIXER("Mixer", 0), | 4294 | HDSPM_MIXER("Mixer", 0), |
2825 | /* 'Sample Clock Source' complies with the alsa control naming scheme */ | 4295 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), |
2826 | HDSPM_CLOCK_SOURCE("Sample Clock Source", 0), | 4296 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
4297 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
4298 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | ||
4299 | HDSPM_SYNC_CHECK("MADI SyncCheck", 0), | ||
4300 | HDSPM_TX_64("TX 64 channels mode", 0), | ||
4301 | HDSPM_C_TMS("Clear Track Marker", 0), | ||
4302 | HDSPM_SAFE_MODE("Safe Mode", 0) | ||
4303 | }; | ||
2827 | 4304 | ||
4305 | static struct snd_kcontrol_new snd_hdspm_controls_aio[] = { | ||
4306 | HDSPM_MIXER("Mixer", 0), | ||
4307 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
2828 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | 4308 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), |
2829 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | 4309 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), |
2830 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | 4310 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), |
2831 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | 4311 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), |
2832 | /* 'External Rate' complies with the alsa control naming scheme */ | ||
2833 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | 4312 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), |
2834 | HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0), | 4313 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), |
2835 | /* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */ | 4314 | HDSPM_SYNC_CHECK("AES SyncCheck", 1), |
4315 | HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2), | ||
4316 | HDSPM_SYNC_CHECK("ADAT SyncCheck", 3), | ||
4317 | HDSPM_SYNC_CHECK("TCO SyncCheck", 4), | ||
4318 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5), | ||
4319 | HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), | ||
4320 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1), | ||
4321 | HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2), | ||
4322 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3), | ||
4323 | HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4), | ||
4324 | HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5) | ||
4325 | |||
4326 | /* | ||
4327 | HDSPM_INPUT_SELECT("Input Select", 0), | ||
4328 | HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0), | ||
4329 | HDSPM_PROFESSIONAL("SPDIF Out Professional", 0); | ||
4330 | HDSPM_SPDIF_IN("SPDIF In", 0); | ||
4331 | HDSPM_BREAKOUT_CABLE("Breakout Cable", 0); | ||
4332 | HDSPM_INPUT_LEVEL("Input Level", 0); | ||
4333 | HDSPM_OUTPUT_LEVEL("Output Level", 0); | ||
4334 | HDSPM_PHONES("Phones", 0); | ||
4335 | */ | ||
4336 | }; | ||
4337 | |||
4338 | static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = { | ||
4339 | HDSPM_MIXER("Mixer", 0), | ||
4340 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
4341 | HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0), | ||
4342 | HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0), | ||
4343 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
4344 | HDSPM_SYNC_CHECK("WC SyncCheck", 0), | ||
4345 | HDSPM_SYNC_CHECK("AES SyncCheck", 1), | ||
4346 | HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2), | ||
4347 | HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3), | ||
4348 | HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4), | ||
4349 | HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5), | ||
4350 | HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6), | ||
4351 | HDSPM_SYNC_CHECK("TCO SyncCheck", 7), | ||
4352 | HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8), | ||
4353 | HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), | ||
4354 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1), | ||
4355 | HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2), | ||
4356 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3), | ||
4357 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4), | ||
4358 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5), | ||
4359 | HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6), | ||
4360 | HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7), | ||
4361 | HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8) | ||
4362 | }; | ||
4363 | |||
4364 | static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { | ||
4365 | HDSPM_MIXER("Mixer", 0), | ||
4366 | HDSPM_INTERNAL_CLOCK("Internal Clock", 0), | ||
4367 | HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0), | ||
4368 | HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0), | ||
4369 | HDSPM_AUTOSYNC_REF("AutoSync Reference", 0), | ||
4370 | HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0), | ||
4371 | HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0), | ||
4372 | HDSPM_SYNC_CHECK("WC Sync Check", 0), | ||
4373 | HDSPM_SYNC_CHECK("AES1 Sync Check", 1), | ||
4374 | HDSPM_SYNC_CHECK("AES2 Sync Check", 2), | ||
4375 | HDSPM_SYNC_CHECK("AES3 Sync Check", 3), | ||
4376 | HDSPM_SYNC_CHECK("AES4 Sync Check", 4), | ||
4377 | HDSPM_SYNC_CHECK("AES5 Sync Check", 5), | ||
4378 | HDSPM_SYNC_CHECK("AES6 Sync Check", 6), | ||
4379 | HDSPM_SYNC_CHECK("AES7 Sync Check", 7), | ||
4380 | HDSPM_SYNC_CHECK("AES8 Sync Check", 8), | ||
4381 | HDSPM_SYNC_CHECK("TCO Sync Check", 9), | ||
4382 | HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10), | ||
4383 | HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0), | ||
4384 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1), | ||
4385 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2), | ||
4386 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3), | ||
4387 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4), | ||
4388 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5), | ||
4389 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6), | ||
4390 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7), | ||
4391 | HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8), | ||
4392 | HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9), | ||
4393 | HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10), | ||
2836 | HDSPM_LINE_OUT("Line Out", 0), | 4394 | HDSPM_LINE_OUT("Line Out", 0), |
2837 | HDSPM_EMPHASIS("Emphasis", 0), | 4395 | HDSPM_EMPHASIS("Emphasis", 0), |
2838 | HDSPM_DOLBY("Non Audio", 0), | 4396 | HDSPM_DOLBY("Non Audio", 0), |
@@ -2842,6 +4400,19 @@ static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = { | |||
2842 | HDSPM_QS_WIRE("Quad Speed Wire Mode", 0), | 4400 | HDSPM_QS_WIRE("Quad Speed Wire Mode", 0), |
2843 | }; | 4401 | }; |
2844 | 4402 | ||
4403 | |||
4404 | |||
4405 | /* Control elements for the optional TCO module */ | ||
4406 | static struct snd_kcontrol_new snd_hdspm_controls_tco[] = { | ||
4407 | HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0), | ||
4408 | HDSPM_TCO_PULL("TCO Pull", 0), | ||
4409 | HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0), | ||
4410 | HDSPM_TCO_FRAME_RATE("TCO Frame Rate", 0), | ||
4411 | HDSPM_TCO_SYNC_SOURCE("TCO Sync Source", 0), | ||
4412 | HDSPM_TCO_WORD_TERM("TCO Word Term", 0) | ||
4413 | }; | ||
4414 | |||
4415 | |||
2845 | static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; | 4416 | static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; |
2846 | 4417 | ||
2847 | 4418 | ||
@@ -2849,78 +4420,76 @@ static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm) | |||
2849 | { | 4420 | { |
2850 | int i; | 4421 | int i; |
2851 | 4422 | ||
2852 | for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) { | 4423 | for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) { |
2853 | if (hdspm->system_sample_rate > 48000) { | 4424 | if (hdspm->system_sample_rate > 48000) { |
2854 | hdspm->playback_mixer_ctls[i]->vd[0].access = | 4425 | hdspm->playback_mixer_ctls[i]->vd[0].access = |
2855 | SNDRV_CTL_ELEM_ACCESS_INACTIVE | | 4426 | SNDRV_CTL_ELEM_ACCESS_INACTIVE | |
2856 | SNDRV_CTL_ELEM_ACCESS_READ | | 4427 | SNDRV_CTL_ELEM_ACCESS_READ | |
2857 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; | 4428 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; |
2858 | } else { | 4429 | } else { |
2859 | hdspm->playback_mixer_ctls[i]->vd[0].access = | 4430 | hdspm->playback_mixer_ctls[i]->vd[0].access = |
2860 | SNDRV_CTL_ELEM_ACCESS_READWRITE | | 4431 | SNDRV_CTL_ELEM_ACCESS_READWRITE | |
2861 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; | 4432 | SNDRV_CTL_ELEM_ACCESS_VOLATILE; |
2862 | } | 4433 | } |
2863 | snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE | | 4434 | snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE | |
2864 | SNDRV_CTL_EVENT_MASK_INFO, | 4435 | SNDRV_CTL_EVENT_MASK_INFO, |
2865 | &hdspm->playback_mixer_ctls[i]->id); | 4436 | &hdspm->playback_mixer_ctls[i]->id); |
2866 | } | 4437 | } |
2867 | 4438 | ||
2868 | return 0; | 4439 | return 0; |
2869 | } | 4440 | } |
2870 | 4441 | ||
2871 | 4442 | ||
2872 | static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm) | 4443 | static int snd_hdspm_create_controls(struct snd_card *card, |
4444 | struct hdspm *hdspm) | ||
2873 | { | 4445 | { |
2874 | unsigned int idx, limit; | 4446 | unsigned int idx, limit; |
2875 | int err; | 4447 | int err; |
2876 | struct snd_kcontrol *kctl; | 4448 | struct snd_kcontrol *kctl; |
4449 | struct snd_kcontrol_new *list = NULL; | ||
2877 | 4450 | ||
2878 | /* add control list first */ | 4451 | switch (hdspm->io_type) { |
2879 | if (hdspm->is_aes32) { | 4452 | case MADI: |
2880 | struct snd_kcontrol_new aes_sync_ctl = | 4453 | list = snd_hdspm_controls_madi; |
2881 | HDSPM_AES_SYNC_CHECK("AES Lock Status", 0); | 4454 | limit = ARRAY_SIZE(snd_hdspm_controls_madi); |
4455 | break; | ||
4456 | case MADIface: | ||
4457 | list = snd_hdspm_controls_madiface; | ||
4458 | limit = ARRAY_SIZE(snd_hdspm_controls_madiface); | ||
4459 | break; | ||
4460 | case AIO: | ||
4461 | list = snd_hdspm_controls_aio; | ||
4462 | limit = ARRAY_SIZE(snd_hdspm_controls_aio); | ||
4463 | break; | ||
4464 | case RayDAT: | ||
4465 | list = snd_hdspm_controls_raydat; | ||
4466 | limit = ARRAY_SIZE(snd_hdspm_controls_raydat); | ||
4467 | break; | ||
4468 | case AES32: | ||
4469 | list = snd_hdspm_controls_aes32; | ||
4470 | limit = ARRAY_SIZE(snd_hdspm_controls_aes32); | ||
4471 | break; | ||
4472 | } | ||
2882 | 4473 | ||
2883 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32); | 4474 | if (NULL != list) { |
2884 | idx++) { | 4475 | for (idx = 0; idx < limit; idx++) { |
2885 | err = snd_ctl_add(card, | ||
2886 | snd_ctl_new1(&snd_hdspm_controls_aes32[idx], | ||
2887 | hdspm)); | ||
2888 | if (err < 0) | ||
2889 | return err; | ||
2890 | } | ||
2891 | for (idx = 1; idx <= 8; idx++) { | ||
2892 | aes_sync_ctl.index = idx; | ||
2893 | err = snd_ctl_add(card, | ||
2894 | snd_ctl_new1(&aes_sync_ctl, hdspm)); | ||
2895 | if (err < 0) | ||
2896 | return err; | ||
2897 | } | ||
2898 | } else { | ||
2899 | for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi); | ||
2900 | idx++) { | ||
2901 | err = snd_ctl_add(card, | 4476 | err = snd_ctl_add(card, |
2902 | snd_ctl_new1(&snd_hdspm_controls_madi[idx], | 4477 | snd_ctl_new1(&list[idx], hdspm)); |
2903 | hdspm)); | ||
2904 | if (err < 0) | 4478 | if (err < 0) |
2905 | return err; | 4479 | return err; |
2906 | } | 4480 | } |
2907 | } | 4481 | } |
2908 | 4482 | ||
2909 | /* Channel playback mixer as default control | ||
2910 | Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, | ||
2911 | thats too * big for any alsamixer they are accessible via special | ||
2912 | IOCTL on hwdep and the mixer 2dimensional mixer control | ||
2913 | */ | ||
2914 | 4483 | ||
4484 | /* create simple 1:1 playback mixer controls */ | ||
2915 | snd_hdspm_playback_mixer.name = "Chn"; | 4485 | snd_hdspm_playback_mixer.name = "Chn"; |
2916 | limit = HDSPM_MAX_CHANNELS; | 4486 | if (hdspm->system_sample_rate >= 128000) { |
2917 | 4487 | limit = hdspm->qs_out_channels; | |
2918 | /* The index values are one greater than the channel ID so that | 4488 | } else if (hdspm->system_sample_rate >= 64000) { |
2919 | * alsamixer will display them correctly. We want to use the index | 4489 | limit = hdspm->ds_out_channels; |
2920 | * for fast lookup of the relevant channel, but if we use it at all, | 4490 | } else { |
2921 | * most ALSA software does the wrong thing with it ... | 4491 | limit = hdspm->ss_out_channels; |
2922 | */ | 4492 | } |
2923 | |||
2924 | for (idx = 0; idx < limit; ++idx) { | 4493 | for (idx = 0; idx < limit; ++idx) { |
2925 | snd_hdspm_playback_mixer.index = idx + 1; | 4494 | snd_hdspm_playback_mixer.index = idx + 1; |
2926 | kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm); | 4495 | kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm); |
@@ -2930,11 +4499,24 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm | |||
2930 | hdspm->playback_mixer_ctls[idx] = kctl; | 4499 | hdspm->playback_mixer_ctls[idx] = kctl; |
2931 | } | 4500 | } |
2932 | 4501 | ||
4502 | |||
4503 | if (hdspm->tco) { | ||
4504 | /* add tco control elements */ | ||
4505 | list = snd_hdspm_controls_tco; | ||
4506 | limit = ARRAY_SIZE(snd_hdspm_controls_tco); | ||
4507 | for (idx = 0; idx < limit; idx++) { | ||
4508 | err = snd_ctl_add(card, | ||
4509 | snd_ctl_new1(&list[idx], hdspm)); | ||
4510 | if (err < 0) | ||
4511 | return err; | ||
4512 | } | ||
4513 | } | ||
4514 | |||
2933 | return 0; | 4515 | return 0; |
2934 | } | 4516 | } |
2935 | 4517 | ||
2936 | /*------------------------------------------------------------ | 4518 | /*------------------------------------------------------------ |
2937 | /proc interface | 4519 | /proc interface |
2938 | ------------------------------------------------------------*/ | 4520 | ------------------------------------------------------------*/ |
2939 | 4521 | ||
2940 | static void | 4522 | static void |
@@ -2942,72 +4524,178 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
2942 | struct snd_info_buffer *buffer) | 4524 | struct snd_info_buffer *buffer) |
2943 | { | 4525 | { |
2944 | struct hdspm *hdspm = entry->private_data; | 4526 | struct hdspm *hdspm = entry->private_data; |
2945 | unsigned int status; | 4527 | unsigned int status, status2, control, freq; |
2946 | unsigned int status2; | 4528 | |
2947 | char *pref_sync_ref; | 4529 | char *pref_sync_ref; |
2948 | char *autosync_ref; | 4530 | char *autosync_ref; |
2949 | char *system_clock_mode; | 4531 | char *system_clock_mode; |
2950 | char *clock_source; | ||
2951 | char *insel; | 4532 | char *insel; |
2952 | char *syncref; | ||
2953 | int x, x2; | 4533 | int x, x2; |
2954 | 4534 | ||
4535 | /* TCO stuff */ | ||
4536 | int a, ltc, frames, seconds, minutes, hours; | ||
4537 | unsigned int period; | ||
4538 | u64 freq_const = 0; | ||
4539 | u32 rate; | ||
4540 | |||
2955 | status = hdspm_read(hdspm, HDSPM_statusRegister); | 4541 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
2956 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | 4542 | status2 = hdspm_read(hdspm, HDSPM_statusRegister2); |
4543 | control = hdspm->control_register; | ||
4544 | freq = hdspm_read(hdspm, HDSPM_timecodeRegister); | ||
2957 | 4545 | ||
2958 | snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n", | 4546 | snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n", |
2959 | hdspm->card_name, hdspm->card->number + 1, | 4547 | hdspm->card_name, hdspm->card->number + 1, |
2960 | hdspm->firmware_rev, | 4548 | hdspm->firmware_rev, |
2961 | (status2 & HDSPM_version0) | | 4549 | (status2 & HDSPM_version0) | |
2962 | (status2 & HDSPM_version1) | (status2 & | 4550 | (status2 & HDSPM_version1) | (status2 & |
2963 | HDSPM_version2)); | 4551 | HDSPM_version2)); |
4552 | |||
4553 | snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n", | ||
4554 | (hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF, | ||
4555 | (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF); | ||
2964 | 4556 | ||
2965 | snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", | 4557 | snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n", |
2966 | hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); | 4558 | hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase); |
2967 | 4559 | ||
2968 | snd_iprintf(buffer, "--- System ---\n"); | 4560 | snd_iprintf(buffer, "--- System ---\n"); |
2969 | 4561 | ||
2970 | snd_iprintf(buffer, | 4562 | snd_iprintf(buffer, |
2971 | "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", | 4563 | "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n", |
2972 | status & HDSPM_audioIRQPending, | 4564 | status & HDSPM_audioIRQPending, |
2973 | (status & HDSPM_midi0IRQPending) ? 1 : 0, | 4565 | (status & HDSPM_midi0IRQPending) ? 1 : 0, |
2974 | (status & HDSPM_midi1IRQPending) ? 1 : 0, | 4566 | (status & HDSPM_midi1IRQPending) ? 1 : 0, |
2975 | hdspm->irq_count); | 4567 | hdspm->irq_count); |
2976 | snd_iprintf(buffer, | 4568 | snd_iprintf(buffer, |
2977 | "HW pointer: id = %d, rawptr = %d (%d->%d) " | 4569 | "HW pointer: id = %d, rawptr = %d (%d->%d) " |
2978 | "estimated= %ld (bytes)\n", | 4570 | "estimated= %ld (bytes)\n", |
2979 | ((status & HDSPM_BufferID) ? 1 : 0), | 4571 | ((status & HDSPM_BufferID) ? 1 : 0), |
2980 | (status & HDSPM_BufferPositionMask), | 4572 | (status & HDSPM_BufferPositionMask), |
2981 | (status & HDSPM_BufferPositionMask) % | 4573 | (status & HDSPM_BufferPositionMask) % |
2982 | (2 * (int)hdspm->period_bytes), | 4574 | (2 * (int)hdspm->period_bytes), |
2983 | ((status & HDSPM_BufferPositionMask) - 64) % | 4575 | ((status & HDSPM_BufferPositionMask) - 64) % |
2984 | (2 * (int)hdspm->period_bytes), | 4576 | (2 * (int)hdspm->period_bytes), |
2985 | (long) hdspm_hw_pointer(hdspm) * 4); | 4577 | (long) hdspm_hw_pointer(hdspm) * 4); |
2986 | 4578 | ||
2987 | snd_iprintf(buffer, | 4579 | snd_iprintf(buffer, |
2988 | "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", | 4580 | "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n", |
2989 | hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, | 4581 | hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF, |
2990 | hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, | 4582 | hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF, |
2991 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 4583 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
2992 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 4584 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
2993 | snd_iprintf(buffer, | 4585 | snd_iprintf(buffer, |
2994 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " | 4586 | "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n", |
2995 | "status2=0x%x\n", | 4587 | hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF, |
2996 | hdspm->control_register, hdspm->control2_register, | 4588 | hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF); |
2997 | status, status2); | 4589 | snd_iprintf(buffer, |
4590 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " | ||
4591 | "status2=0x%x\n", | ||
4592 | hdspm->control_register, hdspm->control2_register, | ||
4593 | status, status2); | ||
4594 | if (status & HDSPM_tco_detect) { | ||
4595 | snd_iprintf(buffer, "TCO module detected.\n"); | ||
4596 | a = hdspm_read(hdspm, HDSPM_RD_TCO+4); | ||
4597 | if (a & HDSPM_TCO1_LTC_Input_valid) { | ||
4598 | snd_iprintf(buffer, " LTC valid, "); | ||
4599 | switch (a & (HDSPM_TCO1_LTC_Format_LSB | | ||
4600 | HDSPM_TCO1_LTC_Format_MSB)) { | ||
4601 | case 0: | ||
4602 | snd_iprintf(buffer, "24 fps, "); | ||
4603 | break; | ||
4604 | case HDSPM_TCO1_LTC_Format_LSB: | ||
4605 | snd_iprintf(buffer, "25 fps, "); | ||
4606 | break; | ||
4607 | case HDSPM_TCO1_LTC_Format_MSB: | ||
4608 | snd_iprintf(buffer, "29.97 fps, "); | ||
4609 | break; | ||
4610 | default: | ||
4611 | snd_iprintf(buffer, "30 fps, "); | ||
4612 | break; | ||
4613 | } | ||
4614 | if (a & HDSPM_TCO1_set_drop_frame_flag) { | ||
4615 | snd_iprintf(buffer, "drop frame\n"); | ||
4616 | } else { | ||
4617 | snd_iprintf(buffer, "full frame\n"); | ||
4618 | } | ||
4619 | } else { | ||
4620 | snd_iprintf(buffer, " no LTC\n"); | ||
4621 | } | ||
4622 | if (a & HDSPM_TCO1_Video_Input_Format_NTSC) { | ||
4623 | snd_iprintf(buffer, " Video: NTSC\n"); | ||
4624 | } else if (a & HDSPM_TCO1_Video_Input_Format_PAL) { | ||
4625 | snd_iprintf(buffer, " Video: PAL\n"); | ||
4626 | } else { | ||
4627 | snd_iprintf(buffer, " No video\n"); | ||
4628 | } | ||
4629 | if (a & HDSPM_TCO1_TCO_lock) { | ||
4630 | snd_iprintf(buffer, " Sync: lock\n"); | ||
4631 | } else { | ||
4632 | snd_iprintf(buffer, " Sync: no lock\n"); | ||
4633 | } | ||
4634 | |||
4635 | switch (hdspm->io_type) { | ||
4636 | case MADI: | ||
4637 | case AES32: | ||
4638 | freq_const = 110069313433624ULL; | ||
4639 | break; | ||
4640 | case RayDAT: | ||
4641 | case AIO: | ||
4642 | freq_const = 104857600000000ULL; | ||
4643 | break; | ||
4644 | case MADIface: | ||
4645 | break; /* no TCO possible */ | ||
4646 | } | ||
4647 | |||
4648 | period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
4649 | snd_iprintf(buffer, " period: %u\n", period); | ||
4650 | |||
4651 | |||
4652 | /* rate = freq_const/period; */ | ||
4653 | rate = div_u64(freq_const, period); | ||
4654 | |||
4655 | if (control & HDSPM_QuadSpeed) { | ||
4656 | rate *= 4; | ||
4657 | } else if (control & HDSPM_DoubleSpeed) { | ||
4658 | rate *= 2; | ||
4659 | } | ||
4660 | |||
4661 | snd_iprintf(buffer, " Frequency: %u Hz\n", | ||
4662 | (unsigned int) rate); | ||
4663 | |||
4664 | ltc = hdspm_read(hdspm, HDSPM_RD_TCO); | ||
4665 | frames = ltc & 0xF; | ||
4666 | ltc >>= 4; | ||
4667 | frames += (ltc & 0x3) * 10; | ||
4668 | ltc >>= 4; | ||
4669 | seconds = ltc & 0xF; | ||
4670 | ltc >>= 4; | ||
4671 | seconds += (ltc & 0x7) * 10; | ||
4672 | ltc >>= 4; | ||
4673 | minutes = ltc & 0xF; | ||
4674 | ltc >>= 4; | ||
4675 | minutes += (ltc & 0x7) * 10; | ||
4676 | ltc >>= 4; | ||
4677 | hours = ltc & 0xF; | ||
4678 | ltc >>= 4; | ||
4679 | hours += (ltc & 0x3) * 10; | ||
4680 | snd_iprintf(buffer, | ||
4681 | " LTC In: %02d:%02d:%02d:%02d\n", | ||
4682 | hours, minutes, seconds, frames); | ||
4683 | |||
4684 | } else { | ||
4685 | snd_iprintf(buffer, "No TCO module detected.\n"); | ||
4686 | } | ||
2998 | 4687 | ||
2999 | snd_iprintf(buffer, "--- Settings ---\n"); | 4688 | snd_iprintf(buffer, "--- Settings ---\n"); |
3000 | 4689 | ||
3001 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & | 4690 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3002 | HDSPM_LatencyMask)); | 4691 | HDSPM_LatencyMask)); |
3003 | 4692 | ||
3004 | snd_iprintf(buffer, | 4693 | snd_iprintf(buffer, |
3005 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 4694 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
3006 | x, (unsigned long) hdspm->period_bytes); | 4695 | x, (unsigned long) hdspm->period_bytes); |
3007 | 4696 | ||
3008 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | 4697 | snd_iprintf(buffer, "Line out: %s\n", |
3009 | (hdspm->control_register & HDSPM_LineOut) ? "on " : "off", | 4698 | (hdspm->control_register & HDSPM_LineOut) ? "on " : "off"); |
3010 | (hdspm->precise_ptr) ? "on" : "off"); | ||
3011 | 4699 | ||
3012 | switch (hdspm->control_register & HDSPM_InputMask) { | 4700 | switch (hdspm->control_register & HDSPM_InputMask) { |
3013 | case HDSPM_InputOptical: | 4701 | case HDSPM_InputOptical: |
@@ -3017,63 +4705,22 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3017 | insel = "Coaxial"; | 4705 | insel = "Coaxial"; |
3018 | break; | 4706 | break; |
3019 | default: | 4707 | default: |
3020 | insel = "Unknown"; | 4708 | insel = "Unkown"; |
3021 | } | ||
3022 | |||
3023 | switch (hdspm->control_register & HDSPM_SyncRefMask) { | ||
3024 | case HDSPM_SyncRef_Word: | ||
3025 | syncref = "WordClock"; | ||
3026 | break; | ||
3027 | case HDSPM_SyncRef_MADI: | ||
3028 | syncref = "MADI"; | ||
3029 | break; | ||
3030 | default: | ||
3031 | syncref = "Unknown"; | ||
3032 | } | 4709 | } |
3033 | snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel, | ||
3034 | syncref); | ||
3035 | 4710 | ||
3036 | snd_iprintf(buffer, | 4711 | snd_iprintf(buffer, |
3037 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, " | 4712 | "ClearTrackMarker = %s, Transmit in %s Channel Mode, " |
3038 | "Auto Input %s\n", | 4713 | "Auto Input %s\n", |
3039 | (hdspm-> | 4714 | (hdspm->control_register & HDSPM_clr_tms) ? "on" : "off", |
3040 | control_register & HDSPM_clr_tms) ? "on" : "off", | 4715 | (hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56", |
3041 | (hdspm-> | 4716 | (hdspm->control_register & HDSPM_AutoInp) ? "on" : "off"); |
3042 | control_register & HDSPM_TX_64ch) ? "64" : "56", | 4717 | |
3043 | (hdspm-> | ||
3044 | control_register & HDSPM_AutoInp) ? "on" : "off"); | ||
3045 | 4718 | ||
3046 | switch (hdspm_clock_source(hdspm)) { | ||
3047 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | ||
3048 | clock_source = "AutoSync"; | ||
3049 | break; | ||
3050 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | ||
3051 | clock_source = "Internal 32 kHz"; | ||
3052 | break; | ||
3053 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | ||
3054 | clock_source = "Internal 44.1 kHz"; | ||
3055 | break; | ||
3056 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | ||
3057 | clock_source = "Internal 48 kHz"; | ||
3058 | break; | ||
3059 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
3060 | clock_source = "Internal 64 kHz"; | ||
3061 | break; | ||
3062 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
3063 | clock_source = "Internal 88.2 kHz"; | ||
3064 | break; | ||
3065 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
3066 | clock_source = "Internal 96 kHz"; | ||
3067 | break; | ||
3068 | default: | ||
3069 | clock_source = "Error"; | ||
3070 | } | ||
3071 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); | ||
3072 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) | 4719 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) |
3073 | system_clock_mode = "Slave"; | 4720 | system_clock_mode = "AutoSync"; |
3074 | else | 4721 | else |
3075 | system_clock_mode = "Master"; | 4722 | system_clock_mode = "Master"; |
3076 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); | 4723 | snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode); |
3077 | 4724 | ||
3078 | switch (hdspm_pref_sync_ref(hdspm)) { | 4725 | switch (hdspm_pref_sync_ref(hdspm)) { |
3079 | case HDSPM_SYNC_FROM_WORD: | 4726 | case HDSPM_SYNC_FROM_WORD: |
@@ -3082,15 +4729,21 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3082 | case HDSPM_SYNC_FROM_MADI: | 4729 | case HDSPM_SYNC_FROM_MADI: |
3083 | pref_sync_ref = "MADI Sync"; | 4730 | pref_sync_ref = "MADI Sync"; |
3084 | break; | 4731 | break; |
4732 | case HDSPM_SYNC_FROM_TCO: | ||
4733 | pref_sync_ref = "TCO"; | ||
4734 | break; | ||
4735 | case HDSPM_SYNC_FROM_SYNC_IN: | ||
4736 | pref_sync_ref = "Sync In"; | ||
4737 | break; | ||
3085 | default: | 4738 | default: |
3086 | pref_sync_ref = "XXXX Clock"; | 4739 | pref_sync_ref = "XXXX Clock"; |
3087 | break; | 4740 | break; |
3088 | } | 4741 | } |
3089 | snd_iprintf(buffer, "Preferred Sync Reference: %s\n", | 4742 | snd_iprintf(buffer, "Preferred Sync Reference: %s\n", |
3090 | pref_sync_ref); | 4743 | pref_sync_ref); |
3091 | 4744 | ||
3092 | snd_iprintf(buffer, "System Clock Frequency: %d\n", | 4745 | snd_iprintf(buffer, "System Clock Frequency: %d\n", |
3093 | hdspm->system_sample_rate); | 4746 | hdspm->system_sample_rate); |
3094 | 4747 | ||
3095 | 4748 | ||
3096 | snd_iprintf(buffer, "--- Status:\n"); | 4749 | snd_iprintf(buffer, "--- Status:\n"); |
@@ -3099,12 +4752,18 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3099 | x2 = status2 & HDSPM_wcSync; | 4752 | x2 = status2 & HDSPM_wcSync; |
3100 | 4753 | ||
3101 | snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n", | 4754 | snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n", |
3102 | (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") : | 4755 | (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") : |
3103 | "NoLock", | 4756 | "NoLock", |
3104 | (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") : | 4757 | (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") : |
3105 | "NoLock"); | 4758 | "NoLock"); |
3106 | 4759 | ||
3107 | switch (hdspm_autosync_ref(hdspm)) { | 4760 | switch (hdspm_autosync_ref(hdspm)) { |
4761 | case HDSPM_AUTOSYNC_FROM_SYNC_IN: | ||
4762 | autosync_ref = "Sync In"; | ||
4763 | break; | ||
4764 | case HDSPM_AUTOSYNC_FROM_TCO: | ||
4765 | autosync_ref = "TCO"; | ||
4766 | break; | ||
3108 | case HDSPM_AUTOSYNC_FROM_WORD: | 4767 | case HDSPM_AUTOSYNC_FROM_WORD: |
3109 | autosync_ref = "Word Clock"; | 4768 | autosync_ref = "Word Clock"; |
3110 | break; | 4769 | break; |
@@ -3119,15 +4778,15 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry, | |||
3119 | break; | 4778 | break; |
3120 | } | 4779 | } |
3121 | snd_iprintf(buffer, | 4780 | snd_iprintf(buffer, |
3122 | "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n", | 4781 | "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n", |
3123 | autosync_ref, hdspm_external_sample_rate(hdspm), | 4782 | autosync_ref, hdspm_external_sample_rate(hdspm), |
3124 | (status & HDSPM_madiFreqMask) >> 22, | 4783 | (status & HDSPM_madiFreqMask) >> 22, |
3125 | (status2 & HDSPM_wcFreqMask) >> 5); | 4784 | (status2 & HDSPM_wcFreqMask) >> 5); |
3126 | 4785 | ||
3127 | snd_iprintf(buffer, "Input: %s, Mode=%s\n", | 4786 | snd_iprintf(buffer, "Input: %s, Mode=%s\n", |
3128 | (status & HDSPM_AB_int) ? "Coax" : "Optical", | 4787 | (status & HDSPM_AB_int) ? "Coax" : "Optical", |
3129 | (status & HDSPM_RX_64ch) ? "64 channels" : | 4788 | (status & HDSPM_RX_64ch) ? "64 channels" : |
3130 | "56 channels"); | 4789 | "56 channels"); |
3131 | 4790 | ||
3132 | snd_iprintf(buffer, "\n"); | 4791 | snd_iprintf(buffer, "\n"); |
3133 | } | 4792 | } |
@@ -3142,8 +4801,6 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3142 | unsigned int timecode; | 4801 | unsigned int timecode; |
3143 | int pref_syncref; | 4802 | int pref_syncref; |
3144 | char *autosync_ref; | 4803 | char *autosync_ref; |
3145 | char *system_clock_mode; | ||
3146 | char *clock_source; | ||
3147 | int x; | 4804 | int x; |
3148 | 4805 | ||
3149 | status = hdspm_read(hdspm, HDSPM_statusRegister); | 4806 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
@@ -3183,24 +4840,27 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3183 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, | 4840 | hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF, |
3184 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); | 4841 | hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF); |
3185 | snd_iprintf(buffer, | 4842 | snd_iprintf(buffer, |
3186 | "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, " | 4843 | "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n", |
3187 | "timecode=0x%x\n", | 4844 | hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF, |
3188 | hdspm->control_register, | 4845 | hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF); |
3189 | status, status2, timecode); | 4846 | snd_iprintf(buffer, |
4847 | "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, " | ||
4848 | "status2=0x%x\n", | ||
4849 | hdspm->control_register, hdspm->control2_register, | ||
4850 | status, status2); | ||
3190 | 4851 | ||
3191 | snd_iprintf(buffer, "--- Settings ---\n"); | 4852 | snd_iprintf(buffer, "--- Settings ---\n"); |
3192 | 4853 | ||
3193 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & | 4854 | x = 1 << (6 + hdspm_decode_latency(hdspm->control_register & |
3194 | HDSPM_LatencyMask)); | 4855 | HDSPM_LatencyMask)); |
3195 | 4856 | ||
3196 | snd_iprintf(buffer, | 4857 | snd_iprintf(buffer, |
3197 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", | 4858 | "Size (Latency): %d samples (2 periods of %lu bytes)\n", |
3198 | x, (unsigned long) hdspm->period_bytes); | 4859 | x, (unsigned long) hdspm->period_bytes); |
3199 | 4860 | ||
3200 | snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n", | 4861 | snd_iprintf(buffer, "Line out: %s\n", |
3201 | (hdspm-> | 4862 | (hdspm-> |
3202 | control_register & HDSPM_LineOut) ? "on " : "off", | 4863 | control_register & HDSPM_LineOut) ? "on " : "off"); |
3203 | (hdspm->precise_ptr) ? "on" : "off"); | ||
3204 | 4864 | ||
3205 | snd_iprintf(buffer, | 4865 | snd_iprintf(buffer, |
3206 | "ClearTrackMarker %s, Emphasis %s, Dolby %s\n", | 4866 | "ClearTrackMarker %s, Emphasis %s, Dolby %s\n", |
@@ -3211,46 +4871,6 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3211 | (hdspm-> | 4871 | (hdspm-> |
3212 | control_register & HDSPM_Dolby) ? "on" : "off"); | 4872 | control_register & HDSPM_Dolby) ? "on" : "off"); |
3213 | 4873 | ||
3214 | switch (hdspm_clock_source(hdspm)) { | ||
3215 | case HDSPM_CLOCK_SOURCE_AUTOSYNC: | ||
3216 | clock_source = "AutoSync"; | ||
3217 | break; | ||
3218 | case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ: | ||
3219 | clock_source = "Internal 32 kHz"; | ||
3220 | break; | ||
3221 | case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ: | ||
3222 | clock_source = "Internal 44.1 kHz"; | ||
3223 | break; | ||
3224 | case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ: | ||
3225 | clock_source = "Internal 48 kHz"; | ||
3226 | break; | ||
3227 | case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ: | ||
3228 | clock_source = "Internal 64 kHz"; | ||
3229 | break; | ||
3230 | case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ: | ||
3231 | clock_source = "Internal 88.2 kHz"; | ||
3232 | break; | ||
3233 | case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ: | ||
3234 | clock_source = "Internal 96 kHz"; | ||
3235 | break; | ||
3236 | case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ: | ||
3237 | clock_source = "Internal 128 kHz"; | ||
3238 | break; | ||
3239 | case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ: | ||
3240 | clock_source = "Internal 176.4 kHz"; | ||
3241 | break; | ||
3242 | case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ: | ||
3243 | clock_source = "Internal 192 kHz"; | ||
3244 | break; | ||
3245 | default: | ||
3246 | clock_source = "Error"; | ||
3247 | } | ||
3248 | snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); | ||
3249 | if (!(hdspm->control_register & HDSPM_ClockModeMaster)) | ||
3250 | system_clock_mode = "Slave"; | ||
3251 | else | ||
3252 | system_clock_mode = "Master"; | ||
3253 | snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); | ||
3254 | 4874 | ||
3255 | pref_syncref = hdspm_pref_sync_ref(hdspm); | 4875 | pref_syncref = hdspm_pref_sync_ref(hdspm); |
3256 | if (pref_syncref == 0) | 4876 | if (pref_syncref == 0) |
@@ -3274,38 +4894,108 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry, | |||
3274 | snd_iprintf(buffer, "--- Status:\n"); | 4894 | snd_iprintf(buffer, "--- Status:\n"); |
3275 | 4895 | ||
3276 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", | 4896 | snd_iprintf(buffer, "Word: %s Frequency: %d\n", |
3277 | (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock", | 4897 | (status & HDSPM_AES32_wcLock) ? "Sync " : "No Lock", |
3278 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); | 4898 | HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF)); |
3279 | 4899 | ||
3280 | for (x = 0; x < 8; x++) { | 4900 | for (x = 0; x < 8; x++) { |
3281 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", | 4901 | snd_iprintf(buffer, "AES%d: %s Frequency: %d\n", |
3282 | x+1, | 4902 | x+1, |
3283 | (status2 & (HDSPM_LockAES >> x)) ? | 4903 | (status2 & (HDSPM_LockAES >> x)) ? |
3284 | "Sync ": "No Lock", | 4904 | "Sync " : "No Lock", |
3285 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); | 4905 | HDSPM_bit2freq((timecode >> (4*x)) & 0xF)); |
3286 | } | 4906 | } |
3287 | 4907 | ||
3288 | switch (hdspm_autosync_ref(hdspm)) { | 4908 | switch (hdspm_autosync_ref(hdspm)) { |
3289 | case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break; | 4909 | case HDSPM_AES32_AUTOSYNC_FROM_NONE: |
3290 | case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break; | 4910 | autosync_ref = "None"; break; |
3291 | case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break; | 4911 | case HDSPM_AES32_AUTOSYNC_FROM_WORD: |
3292 | case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break; | 4912 | autosync_ref = "Word Clock"; break; |
3293 | case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break; | 4913 | case HDSPM_AES32_AUTOSYNC_FROM_AES1: |
3294 | case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break; | 4914 | autosync_ref = "AES1"; break; |
3295 | case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break; | 4915 | case HDSPM_AES32_AUTOSYNC_FROM_AES2: |
3296 | case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break; | 4916 | autosync_ref = "AES2"; break; |
3297 | case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break; | 4917 | case HDSPM_AES32_AUTOSYNC_FROM_AES3: |
3298 | case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break; | 4918 | autosync_ref = "AES3"; break; |
3299 | default: autosync_ref = "---"; break; | 4919 | case HDSPM_AES32_AUTOSYNC_FROM_AES4: |
4920 | autosync_ref = "AES4"; break; | ||
4921 | case HDSPM_AES32_AUTOSYNC_FROM_AES5: | ||
4922 | autosync_ref = "AES5"; break; | ||
4923 | case HDSPM_AES32_AUTOSYNC_FROM_AES6: | ||
4924 | autosync_ref = "AES6"; break; | ||
4925 | case HDSPM_AES32_AUTOSYNC_FROM_AES7: | ||
4926 | autosync_ref = "AES7"; break; | ||
4927 | case HDSPM_AES32_AUTOSYNC_FROM_AES8: | ||
4928 | autosync_ref = "AES8"; break; | ||
4929 | default: | ||
4930 | autosync_ref = "---"; break; | ||
3300 | } | 4931 | } |
3301 | snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref); | 4932 | snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref); |
3302 | 4933 | ||
3303 | snd_iprintf(buffer, "\n"); | 4934 | snd_iprintf(buffer, "\n"); |
3304 | } | 4935 | } |
3305 | 4936 | ||
4937 | static void | ||
4938 | snd_hdspm_proc_read_raydat(struct snd_info_entry *entry, | ||
4939 | struct snd_info_buffer *buffer) | ||
4940 | { | ||
4941 | struct hdspm *hdspm = entry->private_data; | ||
4942 | unsigned int status1, status2, status3, control, i; | ||
4943 | unsigned int lock, sync; | ||
4944 | |||
4945 | status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */ | ||
4946 | status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */ | ||
4947 | status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */ | ||
4948 | |||
4949 | control = hdspm->control_register; | ||
4950 | |||
4951 | snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1); | ||
4952 | snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2); | ||
4953 | snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3); | ||
4954 | |||
4955 | |||
4956 | snd_iprintf(buffer, "\n*** CLOCK MODE\n\n"); | ||
4957 | |||
4958 | snd_iprintf(buffer, "Clock mode : %s\n", | ||
4959 | (hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave"); | ||
4960 | snd_iprintf(buffer, "System frequency: %d Hz\n", | ||
4961 | hdspm_get_system_sample_rate(hdspm)); | ||
4962 | |||
4963 | snd_iprintf(buffer, "\n*** INPUT STATUS\n\n"); | ||
4964 | |||
4965 | lock = 0x1; | ||
4966 | sync = 0x100; | ||
4967 | |||
4968 | for (i = 0; i < 8; i++) { | ||
4969 | snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n", | ||
4970 | i, | ||
4971 | (status1 & lock) ? 1 : 0, | ||
4972 | (status1 & sync) ? 1 : 0, | ||
4973 | texts_freq[(status2 >> (i * 4)) & 0xF]); | ||
4974 | |||
4975 | lock = lock<<1; | ||
4976 | sync = sync<<1; | ||
4977 | } | ||
4978 | |||
4979 | snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n", | ||
4980 | (status1 & 0x1000000) ? 1 : 0, | ||
4981 | (status1 & 0x2000000) ? 1 : 0, | ||
4982 | texts_freq[(status1 >> 16) & 0xF]); | ||
4983 | |||
4984 | snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n", | ||
4985 | (status1 & 0x4000000) ? 1 : 0, | ||
4986 | (status1 & 0x8000000) ? 1 : 0, | ||
4987 | texts_freq[(status1 >> 20) & 0xF]); | ||
4988 | |||
4989 | snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n", | ||
4990 | (status3 & 0x400) ? 1 : 0, | ||
4991 | (status3 & 0x800) ? 1 : 0, | ||
4992 | texts_freq[(status2 >> 12) & 0xF]); | ||
4993 | |||
4994 | } | ||
4995 | |||
3306 | #ifdef CONFIG_SND_DEBUG | 4996 | #ifdef CONFIG_SND_DEBUG |
3307 | static void | 4997 | static void |
3308 | snd_hdspm_proc_read_debug(struct snd_info_entry * entry, | 4998 | snd_hdspm_proc_read_debug(struct snd_info_entry *entry, |
3309 | struct snd_info_buffer *buffer) | 4999 | struct snd_info_buffer *buffer) |
3310 | { | 5000 | { |
3311 | struct hdspm *hdspm = entry->private_data; | 5001 | struct hdspm *hdspm = entry->private_data; |
@@ -3322,16 +5012,68 @@ snd_hdspm_proc_read_debug(struct snd_info_entry * entry, | |||
3322 | #endif | 5012 | #endif |
3323 | 5013 | ||
3324 | 5014 | ||
5015 | static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry, | ||
5016 | struct snd_info_buffer *buffer) | ||
5017 | { | ||
5018 | struct hdspm *hdspm = entry->private_data; | ||
5019 | int i; | ||
5020 | |||
5021 | snd_iprintf(buffer, "# generated by hdspm\n"); | ||
5022 | |||
5023 | for (i = 0; i < hdspm->max_channels_in; i++) { | ||
5024 | snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]); | ||
5025 | } | ||
5026 | } | ||
3325 | 5027 | ||
3326 | static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) | 5028 | static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry, |
5029 | struct snd_info_buffer *buffer) | ||
5030 | { | ||
5031 | struct hdspm *hdspm = entry->private_data; | ||
5032 | int i; | ||
5033 | |||
5034 | snd_iprintf(buffer, "# generated by hdspm\n"); | ||
5035 | |||
5036 | for (i = 0; i < hdspm->max_channels_out; i++) { | ||
5037 | snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]); | ||
5038 | } | ||
5039 | } | ||
5040 | |||
5041 | |||
5042 | static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm) | ||
3327 | { | 5043 | { |
3328 | struct snd_info_entry *entry; | 5044 | struct snd_info_entry *entry; |
3329 | 5045 | ||
3330 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) | 5046 | if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) { |
3331 | snd_info_set_text_ops(entry, hdspm, | 5047 | switch (hdspm->io_type) { |
3332 | hdspm->is_aes32 ? | 5048 | case AES32: |
3333 | snd_hdspm_proc_read_aes32 : | 5049 | snd_info_set_text_ops(entry, hdspm, |
3334 | snd_hdspm_proc_read_madi); | 5050 | snd_hdspm_proc_read_aes32); |
5051 | break; | ||
5052 | case MADI: | ||
5053 | snd_info_set_text_ops(entry, hdspm, | ||
5054 | snd_hdspm_proc_read_madi); | ||
5055 | break; | ||
5056 | case MADIface: | ||
5057 | /* snd_info_set_text_ops(entry, hdspm, | ||
5058 | snd_hdspm_proc_read_madiface); */ | ||
5059 | break; | ||
5060 | case RayDAT: | ||
5061 | snd_info_set_text_ops(entry, hdspm, | ||
5062 | snd_hdspm_proc_read_raydat); | ||
5063 | break; | ||
5064 | case AIO: | ||
5065 | break; | ||
5066 | } | ||
5067 | } | ||
5068 | |||
5069 | if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) { | ||
5070 | snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in); | ||
5071 | } | ||
5072 | |||
5073 | if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) { | ||
5074 | snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out); | ||
5075 | } | ||
5076 | |||
3335 | #ifdef CONFIG_SND_DEBUG | 5077 | #ifdef CONFIG_SND_DEBUG |
3336 | /* debug file to read all hdspm registers */ | 5078 | /* debug file to read all hdspm registers */ |
3337 | if (!snd_card_proc_new(hdspm->card, "debug", &entry)) | 5079 | if (!snd_card_proc_new(hdspm->card, "debug", &entry)) |
@@ -3341,47 +5083,48 @@ static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) | |||
3341 | } | 5083 | } |
3342 | 5084 | ||
3343 | /*------------------------------------------------------------ | 5085 | /*------------------------------------------------------------ |
3344 | hdspm intitialize | 5086 | hdspm intitialize |
3345 | ------------------------------------------------------------*/ | 5087 | ------------------------------------------------------------*/ |
3346 | 5088 | ||
3347 | static int snd_hdspm_set_defaults(struct hdspm * hdspm) | 5089 | static int snd_hdspm_set_defaults(struct hdspm * hdspm) |
3348 | { | 5090 | { |
3349 | unsigned int i; | ||
3350 | |||
3351 | /* ASSUMPTION: hdspm->lock is either held, or there is no need to | 5091 | /* ASSUMPTION: hdspm->lock is either held, or there is no need to |
3352 | hold it (e.g. during module initialization). | 5092 | hold it (e.g. during module initialization). |
3353 | */ | 5093 | */ |
3354 | 5094 | ||
3355 | /* set defaults: */ | 5095 | /* set defaults: */ |
3356 | 5096 | ||
3357 | if (hdspm->is_aes32) | 5097 | hdspm->settings_register = 0; |
5098 | |||
5099 | switch (hdspm->io_type) { | ||
5100 | case MADI: | ||
5101 | case MADIface: | ||
5102 | hdspm->control_register = | ||
5103 | 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000; | ||
5104 | break; | ||
5105 | |||
5106 | case RayDAT: | ||
5107 | case AIO: | ||
5108 | hdspm->settings_register = 0x1 + 0x1000; | ||
5109 | /* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0, | ||
5110 | * line_out */ | ||
5111 | hdspm->control_register = | ||
5112 | 0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000; | ||
5113 | break; | ||
5114 | |||
5115 | case AES32: | ||
3358 | hdspm->control_register = | 5116 | hdspm->control_register = |
3359 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | 5117 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ |
3360 | hdspm_encode_latency(7) | /* latency maximum = | 5118 | hdspm_encode_latency(7) | /* latency max=8192samples */ |
3361 | * 8192 samples | ||
3362 | */ | ||
3363 | HDSPM_SyncRef0 | /* AES1 is syncclock */ | 5119 | HDSPM_SyncRef0 | /* AES1 is syncclock */ |
3364 | HDSPM_LineOut | /* Analog output in */ | 5120 | HDSPM_LineOut | /* Analog output in */ |
3365 | HDSPM_Professional; /* Professional mode */ | 5121 | HDSPM_Professional; /* Professional mode */ |
3366 | else | 5122 | break; |
3367 | hdspm->control_register = | 5123 | } |
3368 | HDSPM_ClockModeMaster | /* Master Cloack Mode on */ | ||
3369 | hdspm_encode_latency(7) | /* latency maximum = | ||
3370 | * 8192 samples | ||
3371 | */ | ||
3372 | HDSPM_InputCoaxial | /* Input Coax not Optical */ | ||
3373 | HDSPM_SyncRef_MADI | /* Madi is syncclock */ | ||
3374 | HDSPM_LineOut | /* Analog output in */ | ||
3375 | HDSPM_TX_64ch | /* transmit in 64ch mode */ | ||
3376 | HDSPM_AutoInp; /* AutoInput chossing (takeover) */ | ||
3377 | |||
3378 | /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */ | ||
3379 | /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */ | ||
3380 | /* ! HDSPM_clr_tms = do not clear bits in track marks */ | ||
3381 | 5124 | ||
3382 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | 5125 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); |
3383 | 5126 | ||
3384 | if (!hdspm->is_aes32) { | 5127 | if (AES32 == hdspm->io_type) { |
3385 | /* No control2 register for AES32 */ | 5128 | /* No control2 register for AES32 */ |
3386 | #ifdef SNDRV_BIG_ENDIAN | 5129 | #ifdef SNDRV_BIG_ENDIAN |
3387 | hdspm->control2_register = HDSPM_BIGENDIAN_MODE; | 5130 | hdspm->control2_register = HDSPM_BIGENDIAN_MODE; |
@@ -3397,57 +5140,59 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm) | |||
3397 | 5140 | ||
3398 | all_in_all_mixer(hdspm, 0 * UNITY_GAIN); | 5141 | all_in_all_mixer(hdspm, 0 * UNITY_GAIN); |
3399 | 5142 | ||
3400 | if (line_outs_monitor[hdspm->dev]) { | 5143 | if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) { |
3401 | 5144 | hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register); | |
3402 | snd_printk(KERN_INFO "HDSPM: " | ||
3403 | "sending all playback streams to line outs.\n"); | ||
3404 | |||
3405 | for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) { | ||
3406 | if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN)) | ||
3407 | return -EIO; | ||
3408 | } | ||
3409 | } | 5145 | } |
3410 | 5146 | ||
3411 | /* set a default rate so that the channel map is set up. */ | 5147 | /* set a default rate so that the channel map is set up. */ |
3412 | hdspm->channel_map = channel_map_madi_ss; | 5148 | hdspm_set_rate(hdspm, 48000, 1); |
3413 | hdspm_set_rate(hdspm, 44100, 1); | ||
3414 | 5149 | ||
3415 | return 0; | 5150 | return 0; |
3416 | } | 5151 | } |
3417 | 5152 | ||
3418 | 5153 | ||
3419 | /*------------------------------------------------------------ | 5154 | /*------------------------------------------------------------ |
3420 | interrupt | 5155 | interrupt |
3421 | ------------------------------------------------------------*/ | 5156 | ------------------------------------------------------------*/ |
3422 | 5157 | ||
3423 | static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | 5158 | static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) |
3424 | { | 5159 | { |
3425 | struct hdspm *hdspm = (struct hdspm *) dev_id; | 5160 | struct hdspm *hdspm = (struct hdspm *) dev_id; |
3426 | unsigned int status; | 5161 | unsigned int status; |
3427 | int audio; | 5162 | int i, audio, midi, schedule = 0; |
3428 | int midi0; | 5163 | /* cycles_t now; */ |
3429 | int midi1; | ||
3430 | unsigned int midi0status; | ||
3431 | unsigned int midi1status; | ||
3432 | int schedule = 0; | ||
3433 | 5164 | ||
3434 | status = hdspm_read(hdspm, HDSPM_statusRegister); | 5165 | status = hdspm_read(hdspm, HDSPM_statusRegister); |
3435 | 5166 | ||
3436 | audio = status & HDSPM_audioIRQPending; | 5167 | audio = status & HDSPM_audioIRQPending; |
3437 | midi0 = status & HDSPM_midi0IRQPending; | 5168 | midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending | |
3438 | midi1 = status & HDSPM_midi1IRQPending; | 5169 | HDSPM_midi2IRQPending | HDSPM_midi3IRQPending); |
5170 | |||
5171 | /* now = get_cycles(); */ | ||
5172 | /** | ||
5173 | * LAT_2..LAT_0 period counter (win) counter (mac) | ||
5174 | * 6 4096 ~256053425 ~514672358 | ||
5175 | * 5 2048 ~128024983 ~257373821 | ||
5176 | * 4 1024 ~64023706 ~128718089 | ||
5177 | * 3 512 ~32005945 ~64385999 | ||
5178 | * 2 256 ~16003039 ~32260176 | ||
5179 | * 1 128 ~7998738 ~16194507 | ||
5180 | * 0 64 ~3998231 ~8191558 | ||
5181 | **/ | ||
5182 | /* | ||
5183 | snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n", | ||
5184 | now-hdspm->last_interrupt, status & 0xFFC0); | ||
5185 | hdspm->last_interrupt = now; | ||
5186 | */ | ||
3439 | 5187 | ||
3440 | if (!audio && !midi0 && !midi1) | 5188 | if (!audio && !midi) |
3441 | return IRQ_NONE; | 5189 | return IRQ_NONE; |
3442 | 5190 | ||
3443 | hdspm_write(hdspm, HDSPM_interruptConfirmation, 0); | 5191 | hdspm_write(hdspm, HDSPM_interruptConfirmation, 0); |
3444 | hdspm->irq_count++; | 5192 | hdspm->irq_count++; |
3445 | 5193 | ||
3446 | midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff; | ||
3447 | midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff; | ||
3448 | 5194 | ||
3449 | if (audio) { | 5195 | if (audio) { |
3450 | |||
3451 | if (hdspm->capture_substream) | 5196 | if (hdspm->capture_substream) |
3452 | snd_pcm_period_elapsed(hdspm->capture_substream); | 5197 | snd_pcm_period_elapsed(hdspm->capture_substream); |
3453 | 5198 | ||
@@ -3455,118 +5200,44 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id) | |||
3455 | snd_pcm_period_elapsed(hdspm->playback_substream); | 5200 | snd_pcm_period_elapsed(hdspm->playback_substream); |
3456 | } | 5201 | } |
3457 | 5202 | ||
3458 | if (midi0 && midi0status) { | 5203 | if (midi) { |
3459 | /* we disable interrupts for this input until processing | 5204 | i = 0; |
3460 | * is done | 5205 | while (i < hdspm->midiPorts) { |
3461 | */ | 5206 | if ((hdspm_read(hdspm, |
3462 | hdspm->control_register &= ~HDSPM_Midi0InterruptEnable; | 5207 | hdspm->midi[i].statusIn) & 0xff) && |
3463 | hdspm_write(hdspm, HDSPM_controlRegister, | 5208 | (status & hdspm->midi[i].irq)) { |
3464 | hdspm->control_register); | 5209 | /* we disable interrupts for this input until |
3465 | hdspm->midi[0].pending = 1; | 5210 | * processing is done |
3466 | schedule = 1; | 5211 | */ |
3467 | } | 5212 | hdspm->control_register &= ~hdspm->midi[i].ie; |
3468 | if (midi1 && midi1status) { | 5213 | hdspm_write(hdspm, HDSPM_controlRegister, |
3469 | /* we disable interrupts for this input until processing | 5214 | hdspm->control_register); |
3470 | * is done | 5215 | hdspm->midi[i].pending = 1; |
3471 | */ | 5216 | schedule = 1; |
3472 | hdspm->control_register &= ~HDSPM_Midi1InterruptEnable; | 5217 | } |
3473 | hdspm_write(hdspm, HDSPM_controlRegister, | 5218 | |
3474 | hdspm->control_register); | 5219 | i++; |
3475 | hdspm->midi[1].pending = 1; | 5220 | } |
3476 | schedule = 1; | 5221 | |
5222 | if (schedule) | ||
5223 | tasklet_hi_schedule(&hdspm->midi_tasklet); | ||
3477 | } | 5224 | } |
3478 | if (schedule) | 5225 | |
3479 | tasklet_schedule(&hdspm->midi_tasklet); | ||
3480 | return IRQ_HANDLED; | 5226 | return IRQ_HANDLED; |
3481 | } | 5227 | } |
3482 | 5228 | ||
3483 | /*------------------------------------------------------------ | 5229 | /*------------------------------------------------------------ |
3484 | pcm interface | 5230 | pcm interface |
3485 | ------------------------------------------------------------*/ | 5231 | ------------------------------------------------------------*/ |
3486 | 5232 | ||
3487 | 5233 | ||
3488 | static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream * | 5234 | static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream |
3489 | substream) | 5235 | *substream) |
3490 | { | 5236 | { |
3491 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | 5237 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); |
3492 | return hdspm_hw_pointer(hdspm); | 5238 | return hdspm_hw_pointer(hdspm); |
3493 | } | 5239 | } |
3494 | 5240 | ||
3495 | static char *hdspm_channel_buffer_location(struct hdspm * hdspm, | ||
3496 | int stream, int channel) | ||
3497 | { | ||
3498 | int mapped_channel; | ||
3499 | |||
3500 | if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS)) | ||
3501 | return NULL; | ||
3502 | |||
3503 | mapped_channel = hdspm->channel_map[channel]; | ||
3504 | if (mapped_channel < 0) | ||
3505 | return NULL; | ||
3506 | |||
3507 | if (stream == SNDRV_PCM_STREAM_CAPTURE) | ||
3508 | return hdspm->capture_buffer + | ||
3509 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
3510 | else | ||
3511 | return hdspm->playback_buffer + | ||
3512 | mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
3513 | } | ||
3514 | |||
3515 | |||
3516 | /* dont know why need it ??? */ | ||
3517 | static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream, | ||
3518 | int channel, snd_pcm_uframes_t pos, | ||
3519 | void __user *src, snd_pcm_uframes_t count) | ||
3520 | { | ||
3521 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | ||
3522 | char *channel_buf; | ||
3523 | |||
3524 | if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4)) | ||
3525 | return -EINVAL; | ||
3526 | |||
3527 | channel_buf = | ||
3528 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | ||
3529 | channel); | ||
3530 | |||
3531 | if (snd_BUG_ON(!channel_buf)) | ||
3532 | return -EIO; | ||
3533 | |||
3534 | return copy_from_user(channel_buf + pos * 4, src, count * 4); | ||
3535 | } | ||
3536 | |||
3537 | static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream, | ||
3538 | int channel, snd_pcm_uframes_t pos, | ||
3539 | void __user *dst, snd_pcm_uframes_t count) | ||
3540 | { | ||
3541 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | ||
3542 | char *channel_buf; | ||
3543 | |||
3544 | if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4)) | ||
3545 | return -EINVAL; | ||
3546 | |||
3547 | channel_buf = | ||
3548 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | ||
3549 | channel); | ||
3550 | if (snd_BUG_ON(!channel_buf)) | ||
3551 | return -EIO; | ||
3552 | return copy_to_user(dst, channel_buf + pos * 4, count * 4); | ||
3553 | } | ||
3554 | |||
3555 | static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream, | ||
3556 | int channel, snd_pcm_uframes_t pos, | ||
3557 | snd_pcm_uframes_t count) | ||
3558 | { | ||
3559 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | ||
3560 | char *channel_buf; | ||
3561 | |||
3562 | channel_buf = | ||
3563 | hdspm_channel_buffer_location(hdspm, substream->pstr->stream, | ||
3564 | channel); | ||
3565 | if (snd_BUG_ON(!channel_buf)) | ||
3566 | return -EIO; | ||
3567 | memset(channel_buf + pos * 4, 0, count * 4); | ||
3568 | return 0; | ||
3569 | } | ||
3570 | 5241 | ||
3571 | static int snd_hdspm_reset(struct snd_pcm_substream *substream) | 5242 | static int snd_hdspm_reset(struct snd_pcm_substream *substream) |
3572 | { | 5243 | { |
@@ -3589,7 +5260,7 @@ static int snd_hdspm_reset(struct snd_pcm_substream *substream) | |||
3589 | snd_pcm_group_for_each_entry(s, substream) { | 5260 | snd_pcm_group_for_each_entry(s, substream) { |
3590 | if (s == other) { | 5261 | if (s == other) { |
3591 | oruntime->status->hw_ptr = | 5262 | oruntime->status->hw_ptr = |
3592 | runtime->status->hw_ptr; | 5263 | runtime->status->hw_ptr; |
3593 | break; | 5264 | break; |
3594 | } | 5265 | } |
3595 | } | 5266 | } |
@@ -3621,19 +5292,19 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3621 | /* The other stream is open, and not by the same | 5292 | /* The other stream is open, and not by the same |
3622 | task as this one. Make sure that the parameters | 5293 | task as this one. Make sure that the parameters |
3623 | that matter are the same. | 5294 | that matter are the same. |
3624 | */ | 5295 | */ |
3625 | 5296 | ||
3626 | if (params_rate(params) != hdspm->system_sample_rate) { | 5297 | if (params_rate(params) != hdspm->system_sample_rate) { |
3627 | spin_unlock_irq(&hdspm->lock); | 5298 | spin_unlock_irq(&hdspm->lock); |
3628 | _snd_pcm_hw_param_setempty(params, | 5299 | _snd_pcm_hw_param_setempty(params, |
3629 | SNDRV_PCM_HW_PARAM_RATE); | 5300 | SNDRV_PCM_HW_PARAM_RATE); |
3630 | return -EBUSY; | 5301 | return -EBUSY; |
3631 | } | 5302 | } |
3632 | 5303 | ||
3633 | if (params_period_size(params) != hdspm->period_bytes / 4) { | 5304 | if (params_period_size(params) != hdspm->period_bytes / 4) { |
3634 | spin_unlock_irq(&hdspm->lock); | 5305 | spin_unlock_irq(&hdspm->lock); |
3635 | _snd_pcm_hw_param_setempty(params, | 5306 | _snd_pcm_hw_param_setempty(params, |
3636 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 5307 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3637 | return -EBUSY; | 5308 | return -EBUSY; |
3638 | } | 5309 | } |
3639 | 5310 | ||
@@ -3646,18 +5317,20 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3646 | spin_lock_irq(&hdspm->lock); | 5317 | spin_lock_irq(&hdspm->lock); |
3647 | err = hdspm_set_rate(hdspm, params_rate(params), 0); | 5318 | err = hdspm_set_rate(hdspm, params_rate(params), 0); |
3648 | if (err < 0) { | 5319 | if (err < 0) { |
5320 | snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err); | ||
3649 | spin_unlock_irq(&hdspm->lock); | 5321 | spin_unlock_irq(&hdspm->lock); |
3650 | _snd_pcm_hw_param_setempty(params, | 5322 | _snd_pcm_hw_param_setempty(params, |
3651 | SNDRV_PCM_HW_PARAM_RATE); | 5323 | SNDRV_PCM_HW_PARAM_RATE); |
3652 | return err; | 5324 | return err; |
3653 | } | 5325 | } |
3654 | spin_unlock_irq(&hdspm->lock); | 5326 | spin_unlock_irq(&hdspm->lock); |
3655 | 5327 | ||
3656 | err = hdspm_set_interrupt_interval(hdspm, | 5328 | err = hdspm_set_interrupt_interval(hdspm, |
3657 | params_period_size(params)); | 5329 | params_period_size(params)); |
3658 | if (err < 0) { | 5330 | if (err < 0) { |
5331 | snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err); | ||
3659 | _snd_pcm_hw_param_setempty(params, | 5332 | _snd_pcm_hw_param_setempty(params, |
3660 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); | 5333 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE); |
3661 | return err; | 5334 | return err; |
3662 | } | 5335 | } |
3663 | 5336 | ||
@@ -3667,10 +5340,13 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3667 | /* malloc all buffer even if not enabled to get sure */ | 5340 | /* malloc all buffer even if not enabled to get sure */ |
3668 | /* Update for MADI rev 204: we need to allocate for all channels, | 5341 | /* Update for MADI rev 204: we need to allocate for all channels, |
3669 | * otherwise it doesn't work at 96kHz */ | 5342 | * otherwise it doesn't work at 96kHz */ |
5343 | |||
3670 | err = | 5344 | err = |
3671 | snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES); | 5345 | snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES); |
3672 | if (err < 0) | 5346 | if (err < 0) { |
5347 | snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err); | ||
3673 | return err; | 5348 | return err; |
5349 | } | ||
3674 | 5350 | ||
3675 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 5351 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3676 | 5352 | ||
@@ -3681,7 +5357,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3681 | snd_hdspm_enable_out(hdspm, i, 1); | 5357 | snd_hdspm_enable_out(hdspm, i, 1); |
3682 | 5358 | ||
3683 | hdspm->playback_buffer = | 5359 | hdspm->playback_buffer = |
3684 | (unsigned char *) substream->runtime->dma_area; | 5360 | (unsigned char *) substream->runtime->dma_area; |
3685 | snd_printdd("Allocated sample buffer for playback at %p\n", | 5361 | snd_printdd("Allocated sample buffer for playback at %p\n", |
3686 | hdspm->playback_buffer); | 5362 | hdspm->playback_buffer); |
3687 | } else { | 5363 | } else { |
@@ -3692,23 +5368,40 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream, | |||
3692 | snd_hdspm_enable_in(hdspm, i, 1); | 5368 | snd_hdspm_enable_in(hdspm, i, 1); |
3693 | 5369 | ||
3694 | hdspm->capture_buffer = | 5370 | hdspm->capture_buffer = |
3695 | (unsigned char *) substream->runtime->dma_area; | 5371 | (unsigned char *) substream->runtime->dma_area; |
3696 | snd_printdd("Allocated sample buffer for capture at %p\n", | 5372 | snd_printdd("Allocated sample buffer for capture at %p\n", |
3697 | hdspm->capture_buffer); | 5373 | hdspm->capture_buffer); |
3698 | } | 5374 | } |
5375 | |||
3699 | /* | 5376 | /* |
3700 | snd_printdd("Allocated sample buffer for %s at 0x%08X\n", | 5377 | snd_printdd("Allocated sample buffer for %s at 0x%08X\n", |
3701 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 5378 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
3702 | "playback" : "capture", | 5379 | "playback" : "capture", |
3703 | snd_pcm_sgbuf_get_addr(substream, 0)); | 5380 | snd_pcm_sgbuf_get_addr(substream, 0)); |
3704 | */ | 5381 | */ |
3705 | /* | 5382 | /* |
3706 | snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n", | 5383 | snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n", |
3707 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 5384 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
3708 | "playback" : "capture", | 5385 | "playback" : "capture", |
3709 | params_rate(params), params_channels(params), | 5386 | params_rate(params), params_channels(params), |
3710 | params_buffer_size(params)); | 5387 | params_buffer_size(params)); |
3711 | */ | 5388 | */ |
5389 | |||
5390 | |||
5391 | /* Switch to native float format if requested */ | ||
5392 | if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) { | ||
5393 | if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT)) | ||
5394 | snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n"); | ||
5395 | |||
5396 | hdspm->control_register |= HDSPe_FLOAT_FORMAT; | ||
5397 | } else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) { | ||
5398 | if (hdspm->control_register & HDSPe_FLOAT_FORMAT) | ||
5399 | snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n"); | ||
5400 | |||
5401 | hdspm->control_register &= ~HDSPe_FLOAT_FORMAT; | ||
5402 | } | ||
5403 | hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); | ||
5404 | |||
3712 | return 0; | 5405 | return 0; |
3713 | } | 5406 | } |
3714 | 5407 | ||
@@ -3719,14 +5412,14 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream) | |||
3719 | 5412 | ||
3720 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 5413 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3721 | 5414 | ||
3722 | /* params_channels(params) should be enough, | 5415 | /* params_channels(params) should be enough, |
3723 | but to get sure in case of error */ | 5416 | but to get sure in case of error */ |
3724 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | 5417 | for (i = 0; i < hdspm->max_channels_out; ++i) |
3725 | snd_hdspm_enable_out(hdspm, i, 0); | 5418 | snd_hdspm_enable_out(hdspm, i, 0); |
3726 | 5419 | ||
3727 | hdspm->playback_buffer = NULL; | 5420 | hdspm->playback_buffer = NULL; |
3728 | } else { | 5421 | } else { |
3729 | for (i = 0; i < HDSPM_MAX_CHANNELS; ++i) | 5422 | for (i = 0; i < hdspm->max_channels_in; ++i) |
3730 | snd_hdspm_enable_in(hdspm, i, 0); | 5423 | snd_hdspm_enable_in(hdspm, i, 0); |
3731 | 5424 | ||
3732 | hdspm->capture_buffer = NULL; | 5425 | hdspm->capture_buffer = NULL; |
@@ -3738,37 +5431,58 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream) | |||
3738 | return 0; | 5431 | return 0; |
3739 | } | 5432 | } |
3740 | 5433 | ||
5434 | |||
3741 | static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, | 5435 | static int snd_hdspm_channel_info(struct snd_pcm_substream *substream, |
3742 | struct snd_pcm_channel_info * info) | 5436 | struct snd_pcm_channel_info *info) |
3743 | { | 5437 | { |
3744 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); | 5438 | struct hdspm *hdspm = snd_pcm_substream_chip(substream); |
3745 | int mapped_channel; | ||
3746 | 5439 | ||
3747 | if (snd_BUG_ON(info->channel >= HDSPM_MAX_CHANNELS)) | 5440 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
3748 | return -EINVAL; | 5441 | if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) { |
5442 | snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel); | ||
5443 | return -EINVAL; | ||
5444 | } | ||
3749 | 5445 | ||
3750 | mapped_channel = hdspm->channel_map[info->channel]; | 5446 | if (hdspm->channel_map_out[info->channel] < 0) { |
3751 | if (mapped_channel < 0) | 5447 | snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel); |
3752 | return -EINVAL; | 5448 | return -EINVAL; |
5449 | } | ||
5450 | |||
5451 | info->offset = hdspm->channel_map_out[info->channel] * | ||
5452 | HDSPM_CHANNEL_BUFFER_BYTES; | ||
5453 | } else { | ||
5454 | if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) { | ||
5455 | snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel); | ||
5456 | return -EINVAL; | ||
5457 | } | ||
5458 | |||
5459 | if (hdspm->channel_map_in[info->channel] < 0) { | ||
5460 | snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel); | ||
5461 | return -EINVAL; | ||
5462 | } | ||
5463 | |||
5464 | info->offset = hdspm->channel_map_in[info->channel] * | ||
5465 | HDSPM_CHANNEL_BUFFER_BYTES; | ||
5466 | } | ||
3753 | 5467 | ||
3754 | info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES; | ||
3755 | info->first = 0; | 5468 | info->first = 0; |
3756 | info->step = 32; | 5469 | info->step = 32; |
3757 | return 0; | 5470 | return 0; |
3758 | } | 5471 | } |
3759 | 5472 | ||
5473 | |||
3760 | static int snd_hdspm_ioctl(struct snd_pcm_substream *substream, | 5474 | static int snd_hdspm_ioctl(struct snd_pcm_substream *substream, |
3761 | unsigned int cmd, void *arg) | 5475 | unsigned int cmd, void *arg) |
3762 | { | 5476 | { |
3763 | switch (cmd) { | 5477 | switch (cmd) { |
3764 | case SNDRV_PCM_IOCTL1_RESET: | 5478 | case SNDRV_PCM_IOCTL1_RESET: |
3765 | return snd_hdspm_reset(substream); | 5479 | return snd_hdspm_reset(substream); |
3766 | 5480 | ||
3767 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: | 5481 | case SNDRV_PCM_IOCTL1_CHANNEL_INFO: |
3768 | { | 5482 | { |
3769 | struct snd_pcm_channel_info *info = arg; | 5483 | struct snd_pcm_channel_info *info = arg; |
3770 | return snd_hdspm_channel_info(substream, info); | 5484 | return snd_hdspm_channel_info(substream, info); |
3771 | } | 5485 | } |
3772 | default: | 5486 | default: |
3773 | break; | 5487 | break; |
3774 | } | 5488 | } |
@@ -3815,19 +5529,19 @@ static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
3815 | } | 5529 | } |
3816 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 5530 | if (cmd == SNDRV_PCM_TRIGGER_START) { |
3817 | if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) | 5531 | if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) |
3818 | && substream->stream == | 5532 | && substream->stream == |
3819 | SNDRV_PCM_STREAM_CAPTURE) | 5533 | SNDRV_PCM_STREAM_CAPTURE) |
3820 | hdspm_silence_playback(hdspm); | 5534 | hdspm_silence_playback(hdspm); |
3821 | } else { | 5535 | } else { |
3822 | if (running && | 5536 | if (running && |
3823 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 5537 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
3824 | hdspm_silence_playback(hdspm); | 5538 | hdspm_silence_playback(hdspm); |
3825 | } | 5539 | } |
3826 | } else { | 5540 | } else { |
3827 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 5541 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) |
3828 | hdspm_silence_playback(hdspm); | 5542 | hdspm_silence_playback(hdspm); |
3829 | } | 5543 | } |
3830 | _ok: | 5544 | _ok: |
3831 | snd_pcm_trigger_done(substream, substream); | 5545 | snd_pcm_trigger_done(substream, substream); |
3832 | if (!hdspm->running && running) | 5546 | if (!hdspm->running && running) |
3833 | hdspm_start_audio(hdspm); | 5547 | hdspm_start_audio(hdspm); |
@@ -3844,8 +5558,18 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream) | |||
3844 | return 0; | 5558 | return 0; |
3845 | } | 5559 | } |
3846 | 5560 | ||
3847 | static unsigned int period_sizes[] = | 5561 | static unsigned int period_sizes_old[] = { |
3848 | { 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; | 5562 | 64, 128, 256, 512, 1024, 2048, 4096 |
5563 | }; | ||
5564 | |||
5565 | static unsigned int period_sizes_new[] = { | ||
5566 | 32, 64, 128, 256, 512, 1024, 2048, 4096 | ||
5567 | }; | ||
5568 | |||
5569 | /* RayDAT and AIO always have a buffer of 16384 samples per channel */ | ||
5570 | static unsigned int raydat_aio_buffer_sizes[] = { | ||
5571 | 16384 | ||
5572 | }; | ||
3849 | 5573 | ||
3850 | static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { | 5574 | static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { |
3851 | .info = (SNDRV_PCM_INFO_MMAP | | 5575 | .info = (SNDRV_PCM_INFO_MMAP | |
@@ -3866,9 +5590,9 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = { | |||
3866 | .buffer_bytes_max = | 5590 | .buffer_bytes_max = |
3867 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, | 5591 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, |
3868 | .period_bytes_min = (64 * 4), | 5592 | .period_bytes_min = (64 * 4), |
3869 | .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, | 5593 | .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS, |
3870 | .periods_min = 2, | 5594 | .periods_min = 2, |
3871 | .periods_max = 2, | 5595 | .periods_max = 512, |
3872 | .fifo_size = 0 | 5596 | .fifo_size = 0 |
3873 | }; | 5597 | }; |
3874 | 5598 | ||
@@ -3891,20 +5615,66 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = { | |||
3891 | .buffer_bytes_max = | 5615 | .buffer_bytes_max = |
3892 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, | 5616 | HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS, |
3893 | .period_bytes_min = (64 * 4), | 5617 | .period_bytes_min = (64 * 4), |
3894 | .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS, | 5618 | .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS, |
3895 | .periods_min = 2, | 5619 | .periods_min = 2, |
3896 | .periods_max = 2, | 5620 | .periods_max = 512, |
3897 | .fifo_size = 0 | 5621 | .fifo_size = 0 |
3898 | }; | 5622 | }; |
3899 | 5623 | ||
3900 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = { | 5624 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = { |
3901 | .count = ARRAY_SIZE(period_sizes), | 5625 | .count = ARRAY_SIZE(period_sizes_old), |
3902 | .list = period_sizes, | 5626 | .list = period_sizes_old, |
3903 | .mask = 0 | 5627 | .mask = 0 |
3904 | }; | 5628 | }; |
3905 | 5629 | ||
5630 | static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = { | ||
5631 | .count = ARRAY_SIZE(period_sizes_new), | ||
5632 | .list = period_sizes_new, | ||
5633 | .mask = 0 | ||
5634 | }; | ||
3906 | 5635 | ||
3907 | static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params, | 5636 | static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = { |
5637 | .count = ARRAY_SIZE(raydat_aio_buffer_sizes), | ||
5638 | .list = raydat_aio_buffer_sizes, | ||
5639 | .mask = 0 | ||
5640 | }; | ||
5641 | |||
5642 | static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params, | ||
5643 | struct snd_pcm_hw_rule *rule) | ||
5644 | { | ||
5645 | struct hdspm *hdspm = rule->private; | ||
5646 | struct snd_interval *c = | ||
5647 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
5648 | struct snd_interval *r = | ||
5649 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
5650 | |||
5651 | if (r->min > 96000 && r->max <= 192000) { | ||
5652 | struct snd_interval t = { | ||
5653 | .min = hdspm->qs_in_channels, | ||
5654 | .max = hdspm->qs_in_channels, | ||
5655 | .integer = 1, | ||
5656 | }; | ||
5657 | return snd_interval_refine(c, &t); | ||
5658 | } else if (r->min > 48000 && r->max <= 96000) { | ||
5659 | struct snd_interval t = { | ||
5660 | .min = hdspm->ds_in_channels, | ||
5661 | .max = hdspm->ds_in_channels, | ||
5662 | .integer = 1, | ||
5663 | }; | ||
5664 | return snd_interval_refine(c, &t); | ||
5665 | } else if (r->max < 64000) { | ||
5666 | struct snd_interval t = { | ||
5667 | .min = hdspm->ss_in_channels, | ||
5668 | .max = hdspm->ss_in_channels, | ||
5669 | .integer = 1, | ||
5670 | }; | ||
5671 | return snd_interval_refine(c, &t); | ||
5672 | } | ||
5673 | |||
5674 | return 0; | ||
5675 | } | ||
5676 | |||
5677 | static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params, | ||
3908 | struct snd_pcm_hw_rule * rule) | 5678 | struct snd_pcm_hw_rule * rule) |
3909 | { | 5679 | { |
3910 | struct hdspm *hdspm = rule->private; | 5680 | struct hdspm *hdspm = rule->private; |
@@ -3913,25 +5683,33 @@ static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params, | |||
3913 | struct snd_interval *r = | 5683 | struct snd_interval *r = |
3914 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 5684 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
3915 | 5685 | ||
3916 | if (r->min > 48000 && r->max <= 96000) { | 5686 | if (r->min > 96000 && r->max <= 192000) { |
3917 | struct snd_interval t = { | 5687 | struct snd_interval t = { |
3918 | .min = hdspm->ds_channels, | 5688 | .min = hdspm->qs_out_channels, |
3919 | .max = hdspm->ds_channels, | 5689 | .max = hdspm->qs_out_channels, |
5690 | .integer = 1, | ||
5691 | }; | ||
5692 | return snd_interval_refine(c, &t); | ||
5693 | } else if (r->min > 48000 && r->max <= 96000) { | ||
5694 | struct snd_interval t = { | ||
5695 | .min = hdspm->ds_out_channels, | ||
5696 | .max = hdspm->ds_out_channels, | ||
3920 | .integer = 1, | 5697 | .integer = 1, |
3921 | }; | 5698 | }; |
3922 | return snd_interval_refine(c, &t); | 5699 | return snd_interval_refine(c, &t); |
3923 | } else if (r->max < 64000) { | 5700 | } else if (r->max < 64000) { |
3924 | struct snd_interval t = { | 5701 | struct snd_interval t = { |
3925 | .min = hdspm->ss_channels, | 5702 | .min = hdspm->ss_out_channels, |
3926 | .max = hdspm->ss_channels, | 5703 | .max = hdspm->ss_out_channels, |
3927 | .integer = 1, | 5704 | .integer = 1, |
3928 | }; | 5705 | }; |
3929 | return snd_interval_refine(c, &t); | 5706 | return snd_interval_refine(c, &t); |
5707 | } else { | ||
3930 | } | 5708 | } |
3931 | return 0; | 5709 | return 0; |
3932 | } | 5710 | } |
3933 | 5711 | ||
3934 | static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params, | 5712 | static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params, |
3935 | struct snd_pcm_hw_rule * rule) | 5713 | struct snd_pcm_hw_rule * rule) |
3936 | { | 5714 | { |
3937 | struct hdspm *hdspm = rule->private; | 5715 | struct hdspm *hdspm = rule->private; |
@@ -3940,42 +5718,92 @@ static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params, | |||
3940 | struct snd_interval *r = | 5718 | struct snd_interval *r = |
3941 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | 5719 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); |
3942 | 5720 | ||
3943 | if (c->min >= hdspm->ss_channels) { | 5721 | if (c->min >= hdspm->ss_in_channels) { |
3944 | struct snd_interval t = { | 5722 | struct snd_interval t = { |
3945 | .min = 32000, | 5723 | .min = 32000, |
3946 | .max = 48000, | 5724 | .max = 48000, |
3947 | .integer = 1, | 5725 | .integer = 1, |
3948 | }; | 5726 | }; |
3949 | return snd_interval_refine(r, &t); | 5727 | return snd_interval_refine(r, &t); |
3950 | } else if (c->max <= hdspm->ds_channels) { | 5728 | } else if (c->max <= hdspm->qs_in_channels) { |
5729 | struct snd_interval t = { | ||
5730 | .min = 128000, | ||
5731 | .max = 192000, | ||
5732 | .integer = 1, | ||
5733 | }; | ||
5734 | return snd_interval_refine(r, &t); | ||
5735 | } else if (c->max <= hdspm->ds_in_channels) { | ||
3951 | struct snd_interval t = { | 5736 | struct snd_interval t = { |
3952 | .min = 64000, | 5737 | .min = 64000, |
3953 | .max = 96000, | 5738 | .max = 96000, |
3954 | .integer = 1, | 5739 | .integer = 1, |
3955 | }; | 5740 | }; |
5741 | return snd_interval_refine(r, &t); | ||
5742 | } | ||
3956 | 5743 | ||
5744 | return 0; | ||
5745 | } | ||
5746 | static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params, | ||
5747 | struct snd_pcm_hw_rule *rule) | ||
5748 | { | ||
5749 | struct hdspm *hdspm = rule->private; | ||
5750 | struct snd_interval *c = | ||
5751 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); | ||
5752 | struct snd_interval *r = | ||
5753 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
5754 | |||
5755 | if (c->min >= hdspm->ss_out_channels) { | ||
5756 | struct snd_interval t = { | ||
5757 | .min = 32000, | ||
5758 | .max = 48000, | ||
5759 | .integer = 1, | ||
5760 | }; | ||
5761 | return snd_interval_refine(r, &t); | ||
5762 | } else if (c->max <= hdspm->qs_out_channels) { | ||
5763 | struct snd_interval t = { | ||
5764 | .min = 128000, | ||
5765 | .max = 192000, | ||
5766 | .integer = 1, | ||
5767 | }; | ||
5768 | return snd_interval_refine(r, &t); | ||
5769 | } else if (c->max <= hdspm->ds_out_channels) { | ||
5770 | struct snd_interval t = { | ||
5771 | .min = 64000, | ||
5772 | .max = 96000, | ||
5773 | .integer = 1, | ||
5774 | }; | ||
3957 | return snd_interval_refine(r, &t); | 5775 | return snd_interval_refine(r, &t); |
3958 | } | 5776 | } |
5777 | |||
3959 | return 0; | 5778 | return 0; |
3960 | } | 5779 | } |
3961 | 5780 | ||
3962 | static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params, | 5781 | static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params, |
3963 | struct snd_pcm_hw_rule *rule) | 5782 | struct snd_pcm_hw_rule *rule) |
3964 | { | 5783 | { |
3965 | unsigned int list[3]; | 5784 | unsigned int list[3]; |
3966 | struct hdspm *hdspm = rule->private; | 5785 | struct hdspm *hdspm = rule->private; |
3967 | struct snd_interval *c = hw_param_interval(params, | 5786 | struct snd_interval *c = hw_param_interval(params, |
3968 | SNDRV_PCM_HW_PARAM_CHANNELS); | 5787 | SNDRV_PCM_HW_PARAM_CHANNELS); |
3969 | if (hdspm->is_aes32) { | 5788 | |
3970 | list[0] = hdspm->qs_channels; | 5789 | list[0] = hdspm->qs_in_channels; |
3971 | list[1] = hdspm->ds_channels; | 5790 | list[1] = hdspm->ds_in_channels; |
3972 | list[2] = hdspm->ss_channels; | 5791 | list[2] = hdspm->ss_in_channels; |
3973 | return snd_interval_list(c, 3, list, 0); | 5792 | return snd_interval_list(c, 3, list, 0); |
3974 | } else { | 5793 | } |
3975 | list[0] = hdspm->ds_channels; | 5794 | |
3976 | list[1] = hdspm->ss_channels; | 5795 | static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params, |
3977 | return snd_interval_list(c, 2, list, 0); | 5796 | struct snd_pcm_hw_rule *rule) |
3978 | } | 5797 | { |
5798 | unsigned int list[3]; | ||
5799 | struct hdspm *hdspm = rule->private; | ||
5800 | struct snd_interval *c = hw_param_interval(params, | ||
5801 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
5802 | |||
5803 | list[0] = hdspm->qs_out_channels; | ||
5804 | list[1] = hdspm->ds_out_channels; | ||
5805 | list[2] = hdspm->ss_out_channels; | ||
5806 | return snd_interval_list(c, 3, list, 0); | ||
3979 | } | 5807 | } |
3980 | 5808 | ||
3981 | 5809 | ||
@@ -3999,6 +5827,7 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) | |||
3999 | 5827 | ||
4000 | snd_pcm_set_sync(substream); | 5828 | snd_pcm_set_sync(substream); |
4001 | 5829 | ||
5830 | |||
4002 | runtime->hw = snd_hdspm_playback_subinfo; | 5831 | runtime->hw = snd_hdspm_playback_subinfo; |
4003 | 5832 | ||
4004 | if (hdspm->capture_substream == NULL) | 5833 | if (hdspm->capture_substream == NULL) |
@@ -4011,25 +5840,41 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream) | |||
4011 | 5840 | ||
4012 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 5841 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
4013 | 5842 | ||
4014 | snd_pcm_hw_constraint_list(runtime, 0, | 5843 | switch (hdspm->io_type) { |
4015 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 5844 | case AIO: |
4016 | &hw_constraints_period_sizes); | 5845 | case RayDAT: |
5846 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5847 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5848 | &hw_constraints_period_sizes_new); | ||
5849 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5850 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
5851 | &hw_constraints_raydat_io_buffer); | ||
4017 | 5852 | ||
4018 | if (hdspm->is_aes32) { | 5853 | break; |
5854 | |||
5855 | default: | ||
5856 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5857 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5858 | &hw_constraints_period_sizes_old); | ||
5859 | } | ||
5860 | |||
5861 | if (AES32 == hdspm->io_type) { | ||
4019 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5862 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4020 | &hdspm_hw_constraints_aes32_sample_rates); | 5863 | &hdspm_hw_constraints_aes32_sample_rates); |
4021 | } else { | 5864 | } else { |
4022 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
4023 | snd_hdspm_hw_rule_channels, hdspm, | ||
4024 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
4025 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
4026 | snd_hdspm_hw_rule_channels_rate, hdspm, | ||
4027 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
4028 | |||
4029 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5865 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4030 | snd_hdspm_hw_rule_rate_channels, hdspm, | 5866 | snd_hdspm_hw_rule_rate_out_channels, hdspm, |
4031 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 5867 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
4032 | } | 5868 | } |
5869 | |||
5870 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
5871 | snd_hdspm_hw_rule_out_channels, hdspm, | ||
5872 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
5873 | |||
5874 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
5875 | snd_hdspm_hw_rule_out_channels_rate, hdspm, | ||
5876 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
5877 | |||
4033 | return 0; | 5878 | return 0; |
4034 | } | 5879 | } |
4035 | 5880 | ||
@@ -4066,24 +5911,40 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream) | |||
4066 | spin_unlock_irq(&hdspm->lock); | 5911 | spin_unlock_irq(&hdspm->lock); |
4067 | 5912 | ||
4068 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); | 5913 | snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24); |
4069 | snd_pcm_hw_constraint_list(runtime, 0, | 5914 | switch (hdspm->io_type) { |
4070 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 5915 | case AIO: |
4071 | &hw_constraints_period_sizes); | 5916 | case RayDAT: |
4072 | if (hdspm->is_aes32) { | 5917 | snd_pcm_hw_constraint_list(runtime, 0, |
5918 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5919 | &hw_constraints_period_sizes_new); | ||
5920 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5921 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
5922 | &hw_constraints_raydat_io_buffer); | ||
5923 | break; | ||
5924 | |||
5925 | default: | ||
5926 | snd_pcm_hw_constraint_list(runtime, 0, | ||
5927 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
5928 | &hw_constraints_period_sizes_old); | ||
5929 | } | ||
5930 | |||
5931 | if (AES32 == hdspm->io_type) { | ||
4073 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5932 | snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4074 | &hdspm_hw_constraints_aes32_sample_rates); | 5933 | &hdspm_hw_constraints_aes32_sample_rates); |
4075 | } else { | 5934 | } else { |
4076 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
4077 | snd_hdspm_hw_rule_channels, hdspm, | ||
4078 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
4079 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
4080 | snd_hdspm_hw_rule_channels_rate, hdspm, | ||
4081 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
4082 | |||
4083 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | 5935 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, |
4084 | snd_hdspm_hw_rule_rate_channels, hdspm, | 5936 | snd_hdspm_hw_rule_rate_in_channels, hdspm, |
4085 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | 5937 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); |
4086 | } | 5938 | } |
5939 | |||
5940 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
5941 | snd_hdspm_hw_rule_in_channels, hdspm, | ||
5942 | SNDRV_PCM_HW_PARAM_CHANNELS, -1); | ||
5943 | |||
5944 | snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | ||
5945 | snd_hdspm_hw_rule_in_channels_rate, hdspm, | ||
5946 | SNDRV_PCM_HW_PARAM_RATE, -1); | ||
5947 | |||
4087 | return 0; | 5948 | return 0; |
4088 | } | 5949 | } |
4089 | 5950 | ||
@@ -4100,32 +5961,129 @@ static int snd_hdspm_capture_release(struct snd_pcm_substream *substream) | |||
4100 | return 0; | 5961 | return 0; |
4101 | } | 5962 | } |
4102 | 5963 | ||
4103 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | 5964 | static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file) |
4104 | unsigned int cmd, unsigned long arg) | ||
4105 | { | 5965 | { |
5966 | /* we have nothing to initialize but the call is required */ | ||
5967 | return 0; | ||
5968 | } | ||
5969 | |||
5970 | static inline int copy_u32_le(void __user *dest, void __iomem *src) | ||
5971 | { | ||
5972 | u32 val = readl(src); | ||
5973 | return copy_to_user(dest, &val, 4); | ||
5974 | } | ||
5975 | |||
5976 | static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, | ||
5977 | unsigned int cmd, unsigned long __user arg) | ||
5978 | { | ||
5979 | void __user *argp = (void __user *)arg; | ||
4106 | struct hdspm *hdspm = hw->private_data; | 5980 | struct hdspm *hdspm = hw->private_data; |
4107 | struct hdspm_mixer_ioctl mixer; | 5981 | struct hdspm_mixer_ioctl mixer; |
4108 | struct hdspm_config_info info; | 5982 | struct hdspm_config info; |
5983 | struct hdspm_status status; | ||
4109 | struct hdspm_version hdspm_version; | 5984 | struct hdspm_version hdspm_version; |
4110 | struct hdspm_peak_rms_ioctl rms; | 5985 | struct hdspm_peak_rms *levels; |
5986 | struct hdspm_ltc ltc; | ||
5987 | unsigned int statusregister; | ||
5988 | long unsigned int s; | ||
5989 | int i = 0; | ||
4111 | 5990 | ||
4112 | switch (cmd) { | 5991 | switch (cmd) { |
4113 | 5992 | ||
4114 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: | 5993 | case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS: |
4115 | if (copy_from_user(&rms, (void __user *)arg, sizeof(rms))) | 5994 | levels = &hdspm->peak_rms; |
5995 | for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { | ||
5996 | levels->input_peaks[i] = | ||
5997 | readl(hdspm->iobase + | ||
5998 | HDSPM_MADI_INPUT_PEAK + i*4); | ||
5999 | levels->playback_peaks[i] = | ||
6000 | readl(hdspm->iobase + | ||
6001 | HDSPM_MADI_PLAYBACK_PEAK + i*4); | ||
6002 | levels->output_peaks[i] = | ||
6003 | readl(hdspm->iobase + | ||
6004 | HDSPM_MADI_OUTPUT_PEAK + i*4); | ||
6005 | |||
6006 | levels->input_rms[i] = | ||
6007 | ((uint64_t) readl(hdspm->iobase + | ||
6008 | HDSPM_MADI_INPUT_RMS_H + i*4) << 32) | | ||
6009 | (uint64_t) readl(hdspm->iobase + | ||
6010 | HDSPM_MADI_INPUT_RMS_L + i*4); | ||
6011 | levels->playback_rms[i] = | ||
6012 | ((uint64_t)readl(hdspm->iobase + | ||
6013 | HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) | | ||
6014 | (uint64_t)readl(hdspm->iobase + | ||
6015 | HDSPM_MADI_PLAYBACK_RMS_L + i*4); | ||
6016 | levels->output_rms[i] = | ||
6017 | ((uint64_t)readl(hdspm->iobase + | ||
6018 | HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) | | ||
6019 | (uint64_t)readl(hdspm->iobase + | ||
6020 | HDSPM_MADI_OUTPUT_RMS_L + i*4); | ||
6021 | } | ||
6022 | |||
6023 | if (hdspm->system_sample_rate > 96000) { | ||
6024 | levels->speed = qs; | ||
6025 | } else if (hdspm->system_sample_rate > 48000) { | ||
6026 | levels->speed = ds; | ||
6027 | } else { | ||
6028 | levels->speed = ss; | ||
6029 | } | ||
6030 | levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2); | ||
6031 | |||
6032 | s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms)); | ||
6033 | if (0 != s) { | ||
6034 | /* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu | ||
6035 | [Levels]\n", sizeof(struct hdspm_peak_rms), s); | ||
6036 | */ | ||
4116 | return -EFAULT; | 6037 | return -EFAULT; |
4117 | /* maybe there is a chance to memorymap in future | 6038 | } |
4118 | * so dont touch just copy | 6039 | break; |
4119 | */ | 6040 | |
4120 | if(copy_to_user_fromio((void __user *)rms.peak, | 6041 | case SNDRV_HDSPM_IOCTL_GET_LTC: |
4121 | hdspm->iobase+HDSPM_MADI_peakrmsbase, | 6042 | ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO); |
4122 | sizeof(struct hdspm_peak_rms)) != 0 ) | 6043 | i = hdspm_read(hdspm, HDSPM_RD_TCO + 4); |
6044 | if (i & HDSPM_TCO1_LTC_Input_valid) { | ||
6045 | switch (i & (HDSPM_TCO1_LTC_Format_LSB | | ||
6046 | HDSPM_TCO1_LTC_Format_MSB)) { | ||
6047 | case 0: | ||
6048 | ltc.format = fps_24; | ||
6049 | break; | ||
6050 | case HDSPM_TCO1_LTC_Format_LSB: | ||
6051 | ltc.format = fps_25; | ||
6052 | break; | ||
6053 | case HDSPM_TCO1_LTC_Format_MSB: | ||
6054 | ltc.format = fps_2997; | ||
6055 | break; | ||
6056 | default: | ||
6057 | ltc.format = 30; | ||
6058 | break; | ||
6059 | } | ||
6060 | if (i & HDSPM_TCO1_set_drop_frame_flag) { | ||
6061 | ltc.frame = drop_frame; | ||
6062 | } else { | ||
6063 | ltc.frame = full_frame; | ||
6064 | } | ||
6065 | } else { | ||
6066 | ltc.format = format_invalid; | ||
6067 | ltc.frame = frame_invalid; | ||
6068 | } | ||
6069 | if (i & HDSPM_TCO1_Video_Input_Format_NTSC) { | ||
6070 | ltc.input_format = ntsc; | ||
6071 | } else if (i & HDSPM_TCO1_Video_Input_Format_PAL) { | ||
6072 | ltc.input_format = pal; | ||
6073 | } else { | ||
6074 | ltc.input_format = no_video; | ||
6075 | } | ||
6076 | |||
6077 | s = copy_to_user(argp, <c, sizeof(struct hdspm_ltc)); | ||
6078 | if (0 != s) { | ||
6079 | /* | ||
6080 | snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */ | ||
4123 | return -EFAULT; | 6081 | return -EFAULT; |
6082 | } | ||
4124 | 6083 | ||
4125 | break; | 6084 | break; |
4126 | |||
4127 | 6085 | ||
4128 | case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO: | 6086 | case SNDRV_HDSPM_IOCTL_GET_CONFIG: |
4129 | 6087 | ||
4130 | memset(&info, 0, sizeof(info)); | 6088 | memset(&info, 0, sizeof(info)); |
4131 | spin_lock_irq(&hdspm->lock); | 6089 | spin_lock_irq(&hdspm->lock); |
@@ -4134,7 +6092,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4134 | 6092 | ||
4135 | info.system_sample_rate = hdspm->system_sample_rate; | 6093 | info.system_sample_rate = hdspm->system_sample_rate; |
4136 | info.autosync_sample_rate = | 6094 | info.autosync_sample_rate = |
4137 | hdspm_external_sample_rate(hdspm); | 6095 | hdspm_external_sample_rate(hdspm); |
4138 | info.system_clock_mode = hdspm_system_clock_mode(hdspm); | 6096 | info.system_clock_mode = hdspm_system_clock_mode(hdspm); |
4139 | info.clock_source = hdspm_clock_source(hdspm); | 6097 | info.clock_source = hdspm_clock_source(hdspm); |
4140 | info.autosync_ref = hdspm_autosync_ref(hdspm); | 6098 | info.autosync_ref = hdspm_autosync_ref(hdspm); |
@@ -4145,10 +6103,58 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4145 | return -EFAULT; | 6103 | return -EFAULT; |
4146 | break; | 6104 | break; |
4147 | 6105 | ||
6106 | case SNDRV_HDSPM_IOCTL_GET_STATUS: | ||
6107 | status.card_type = hdspm->io_type; | ||
6108 | |||
6109 | status.autosync_source = hdspm_autosync_ref(hdspm); | ||
6110 | |||
6111 | status.card_clock = 110069313433624ULL; | ||
6112 | status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ); | ||
6113 | |||
6114 | switch (hdspm->io_type) { | ||
6115 | case MADI: | ||
6116 | case MADIface: | ||
6117 | status.card_specific.madi.sync_wc = | ||
6118 | hdspm_wc_sync_check(hdspm); | ||
6119 | status.card_specific.madi.sync_madi = | ||
6120 | hdspm_madi_sync_check(hdspm); | ||
6121 | status.card_specific.madi.sync_tco = | ||
6122 | hdspm_tco_sync_check(hdspm); | ||
6123 | status.card_specific.madi.sync_in = | ||
6124 | hdspm_sync_in_sync_check(hdspm); | ||
6125 | |||
6126 | statusregister = | ||
6127 | hdspm_read(hdspm, HDSPM_statusRegister); | ||
6128 | status.card_specific.madi.madi_input = | ||
6129 | (statusregister & HDSPM_AB_int) ? 1 : 0; | ||
6130 | status.card_specific.madi.channel_format = | ||
6131 | (statusregister & HDSPM_TX_64ch) ? 1 : 0; | ||
6132 | /* TODO: Mac driver sets it when f_s>48kHz */ | ||
6133 | status.card_specific.madi.frame_format = 0; | ||
6134 | |||
6135 | default: | ||
6136 | break; | ||
6137 | } | ||
6138 | |||
6139 | if (copy_to_user((void __user *) arg, &status, sizeof(status))) | ||
6140 | return -EFAULT; | ||
6141 | |||
6142 | |||
6143 | break; | ||
6144 | |||
4148 | case SNDRV_HDSPM_IOCTL_GET_VERSION: | 6145 | case SNDRV_HDSPM_IOCTL_GET_VERSION: |
6146 | hdspm_version.card_type = hdspm->io_type; | ||
6147 | strncpy(hdspm_version.cardname, hdspm->card_name, | ||
6148 | sizeof(hdspm_version.cardname)); | ||
6149 | hdspm_version.serial = (hdspm_read(hdspm, | ||
6150 | HDSPM_midiStatusIn0)>>8) & 0xFFFFFF; | ||
4149 | hdspm_version.firmware_rev = hdspm->firmware_rev; | 6151 | hdspm_version.firmware_rev = hdspm->firmware_rev; |
6152 | hdspm_version.addons = 0; | ||
6153 | if (hdspm->tco) | ||
6154 | hdspm_version.addons |= HDSPM_ADDON_TCO; | ||
6155 | |||
4150 | if (copy_to_user((void __user *) arg, &hdspm_version, | 6156 | if (copy_to_user((void __user *) arg, &hdspm_version, |
4151 | sizeof(hdspm_version))) | 6157 | sizeof(hdspm_version))) |
4152 | return -EFAULT; | 6158 | return -EFAULT; |
4153 | break; | 6159 | break; |
4154 | 6160 | ||
@@ -4156,7 +6162,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file, | |||
4156 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) | 6162 | if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer))) |
4157 | return -EFAULT; | 6163 | return -EFAULT; |
4158 | if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer, | 6164 | if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer, |
4159 | sizeof(struct hdspm_mixer))) | 6165 | sizeof(struct hdspm_mixer))) |
4160 | return -EFAULT; | 6166 | return -EFAULT; |
4161 | break; | 6167 | break; |
4162 | 6168 | ||
@@ -4175,8 +6181,6 @@ static struct snd_pcm_ops snd_hdspm_playback_ops = { | |||
4175 | .prepare = snd_hdspm_prepare, | 6181 | .prepare = snd_hdspm_prepare, |
4176 | .trigger = snd_hdspm_trigger, | 6182 | .trigger = snd_hdspm_trigger, |
4177 | .pointer = snd_hdspm_hw_pointer, | 6183 | .pointer = snd_hdspm_hw_pointer, |
4178 | .copy = snd_hdspm_playback_copy, | ||
4179 | .silence = snd_hdspm_hw_silence, | ||
4180 | .page = snd_pcm_sgbuf_ops_page, | 6184 | .page = snd_pcm_sgbuf_ops_page, |
4181 | }; | 6185 | }; |
4182 | 6186 | ||
@@ -4189,7 +6193,6 @@ static struct snd_pcm_ops snd_hdspm_capture_ops = { | |||
4189 | .prepare = snd_hdspm_prepare, | 6193 | .prepare = snd_hdspm_prepare, |
4190 | .trigger = snd_hdspm_trigger, | 6194 | .trigger = snd_hdspm_trigger, |
4191 | .pointer = snd_hdspm_hw_pointer, | 6195 | .pointer = snd_hdspm_hw_pointer, |
4192 | .copy = snd_hdspm_capture_copy, | ||
4193 | .page = snd_pcm_sgbuf_ops_page, | 6196 | .page = snd_pcm_sgbuf_ops_page, |
4194 | }; | 6197 | }; |
4195 | 6198 | ||
@@ -4207,16 +6210,18 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card, | |||
4207 | hw->private_data = hdspm; | 6210 | hw->private_data = hdspm; |
4208 | strcpy(hw->name, "HDSPM hwdep interface"); | 6211 | strcpy(hw->name, "HDSPM hwdep interface"); |
4209 | 6212 | ||
6213 | hw->ops.open = snd_hdspm_hwdep_dummy_op; | ||
4210 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; | 6214 | hw->ops.ioctl = snd_hdspm_hwdep_ioctl; |
6215 | hw->ops.release = snd_hdspm_hwdep_dummy_op; | ||
4211 | 6216 | ||
4212 | return 0; | 6217 | return 0; |
4213 | } | 6218 | } |
4214 | 6219 | ||
4215 | 6220 | ||
4216 | /*------------------------------------------------------------ | 6221 | /*------------------------------------------------------------ |
4217 | memory interface | 6222 | memory interface |
4218 | ------------------------------------------------------------*/ | 6223 | ------------------------------------------------------------*/ |
4219 | static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | 6224 | static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm) |
4220 | { | 6225 | { |
4221 | int err; | 6226 | int err; |
4222 | struct snd_pcm *pcm; | 6227 | struct snd_pcm *pcm; |
@@ -4228,7 +6233,7 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | |||
4228 | 6233 | ||
4229 | err = | 6234 | err = |
4230 | snd_pcm_lib_preallocate_pages_for_all(pcm, | 6235 | snd_pcm_lib_preallocate_pages_for_all(pcm, |
4231 | SNDRV_DMA_TYPE_DEV_SG, | 6236 | SNDRV_DMA_TYPE_DEV_SG, |
4232 | snd_dma_pci_data(hdspm->pci), | 6237 | snd_dma_pci_data(hdspm->pci), |
4233 | wanted, | 6238 | wanted, |
4234 | wanted); | 6239 | wanted); |
@@ -4242,19 +6247,23 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm) | |||
4242 | return 0; | 6247 | return 0; |
4243 | } | 6248 | } |
4244 | 6249 | ||
4245 | static void hdspm_set_sgbuf(struct hdspm * hdspm, | 6250 | |
6251 | static void hdspm_set_sgbuf(struct hdspm *hdspm, | ||
4246 | struct snd_pcm_substream *substream, | 6252 | struct snd_pcm_substream *substream, |
4247 | unsigned int reg, int channels) | 6253 | unsigned int reg, int channels) |
4248 | { | 6254 | { |
4249 | int i; | 6255 | int i; |
6256 | |||
6257 | /* continuous memory segment */ | ||
4250 | for (i = 0; i < (channels * 16); i++) | 6258 | for (i = 0; i < (channels * 16); i++) |
4251 | hdspm_write(hdspm, reg + 4 * i, | 6259 | hdspm_write(hdspm, reg + 4 * i, |
4252 | snd_pcm_sgbuf_get_addr(substream, 4096 * i)); | 6260 | snd_pcm_sgbuf_get_addr(substream, 4096 * i)); |
4253 | } | 6261 | } |
4254 | 6262 | ||
6263 | |||
4255 | /* ------------- ALSA Devices ---------------------------- */ | 6264 | /* ------------- ALSA Devices ---------------------------- */ |
4256 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | 6265 | static int __devinit snd_hdspm_create_pcm(struct snd_card *card, |
4257 | struct hdspm * hdspm) | 6266 | struct hdspm *hdspm) |
4258 | { | 6267 | { |
4259 | struct snd_pcm *pcm; | 6268 | struct snd_pcm *pcm; |
4260 | int err; | 6269 | int err; |
@@ -4283,27 +6292,30 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card, | |||
4283 | 6292 | ||
4284 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm) | 6293 | static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm) |
4285 | { | 6294 | { |
4286 | snd_hdspm_flush_midi_input(hdspm, 0); | 6295 | int i; |
4287 | snd_hdspm_flush_midi_input(hdspm, 1); | 6296 | |
6297 | for (i = 0; i < hdspm->midiPorts; i++) | ||
6298 | snd_hdspm_flush_midi_input(hdspm, i); | ||
4288 | } | 6299 | } |
4289 | 6300 | ||
4290 | static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | 6301 | static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, |
4291 | struct hdspm * hdspm) | 6302 | struct hdspm * hdspm) |
4292 | { | 6303 | { |
4293 | int err; | 6304 | int err, i; |
4294 | 6305 | ||
4295 | snd_printdd("Create card...\n"); | 6306 | snd_printdd("Create card...\n"); |
4296 | err = snd_hdspm_create_pcm(card, hdspm); | 6307 | err = snd_hdspm_create_pcm(card, hdspm); |
4297 | if (err < 0) | 6308 | if (err < 0) |
4298 | return err; | 6309 | return err; |
4299 | 6310 | ||
4300 | err = snd_hdspm_create_midi(card, hdspm, 0); | 6311 | i = 0; |
4301 | if (err < 0) | 6312 | while (i < hdspm->midiPorts) { |
4302 | return err; | 6313 | err = snd_hdspm_create_midi(card, hdspm, i); |
4303 | 6314 | if (err < 0) { | |
4304 | err = snd_hdspm_create_midi(card, hdspm, 1); | 6315 | return err; |
4305 | if (err < 0) | 6316 | } |
4306 | return err; | 6317 | i++; |
6318 | } | ||
4307 | 6319 | ||
4308 | err = snd_hdspm_create_controls(card, hdspm); | 6320 | err = snd_hdspm_create_controls(card, hdspm); |
4309 | if (err < 0) | 6321 | if (err < 0) |
@@ -4346,37 +6358,55 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card, | |||
4346 | } | 6358 | } |
4347 | 6359 | ||
4348 | static int __devinit snd_hdspm_create(struct snd_card *card, | 6360 | static int __devinit snd_hdspm_create(struct snd_card *card, |
4349 | struct hdspm *hdspm, | 6361 | struct hdspm *hdspm) { |
4350 | int precise_ptr, int enable_monitor) | 6362 | |
4351 | { | ||
4352 | struct pci_dev *pci = hdspm->pci; | 6363 | struct pci_dev *pci = hdspm->pci; |
4353 | int err; | 6364 | int err; |
4354 | unsigned long io_extent; | 6365 | unsigned long io_extent; |
4355 | 6366 | ||
4356 | hdspm->irq = -1; | 6367 | hdspm->irq = -1; |
4357 | |||
4358 | spin_lock_init(&hdspm->midi[0].lock); | ||
4359 | spin_lock_init(&hdspm->midi[1].lock); | ||
4360 | |||
4361 | hdspm->card = card; | 6368 | hdspm->card = card; |
4362 | 6369 | ||
4363 | spin_lock_init(&hdspm->lock); | 6370 | spin_lock_init(&hdspm->lock); |
4364 | 6371 | ||
4365 | tasklet_init(&hdspm->midi_tasklet, | ||
4366 | hdspm_midi_tasklet, (unsigned long) hdspm); | ||
4367 | |||
4368 | pci_read_config_word(hdspm->pci, | 6372 | pci_read_config_word(hdspm->pci, |
4369 | PCI_CLASS_REVISION, &hdspm->firmware_rev); | 6373 | PCI_CLASS_REVISION, &hdspm->firmware_rev); |
4370 | |||
4371 | hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION); | ||
4372 | 6374 | ||
4373 | strcpy(card->mixername, "Xilinx FPGA"); | 6375 | strcpy(card->mixername, "Xilinx FPGA"); |
4374 | if (hdspm->is_aes32) { | 6376 | strcpy(card->driver, "HDSPM"); |
4375 | strcpy(card->driver, "HDSPAES32"); | 6377 | |
4376 | hdspm->card_name = "RME HDSPM AES32"; | 6378 | switch (hdspm->firmware_rev) { |
4377 | } else { | 6379 | case HDSPM_MADI_REV: |
4378 | strcpy(card->driver, "HDSPM"); | 6380 | hdspm->io_type = MADI; |
4379 | hdspm->card_name = "RME HDSPM MADI"; | 6381 | hdspm->card_name = "RME MADI"; |
6382 | hdspm->midiPorts = 3; | ||
6383 | break; | ||
6384 | case HDSPM_RAYDAT_REV: | ||
6385 | hdspm->io_type = RayDAT; | ||
6386 | hdspm->card_name = "RME RayDAT"; | ||
6387 | hdspm->midiPorts = 2; | ||
6388 | break; | ||
6389 | case HDSPM_AIO_REV: | ||
6390 | hdspm->io_type = AIO; | ||
6391 | hdspm->card_name = "RME AIO"; | ||
6392 | hdspm->midiPorts = 1; | ||
6393 | break; | ||
6394 | case HDSPM_MADIFACE_REV: | ||
6395 | hdspm->io_type = MADIface; | ||
6396 | hdspm->card_name = "RME MADIface"; | ||
6397 | hdspm->midiPorts = 1; | ||
6398 | break; | ||
6399 | case HDSPM_AES_REV: | ||
6400 | case HDSPM_AES32_REV: | ||
6401 | case HDSPM_AES32_OLD_REV: | ||
6402 | hdspm->io_type = AES32; | ||
6403 | hdspm->card_name = "RME AES32"; | ||
6404 | hdspm->midiPorts = 2; | ||
6405 | break; | ||
6406 | default: | ||
6407 | snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n", | ||
6408 | hdspm->firmware_rev); | ||
6409 | return -ENODEV; | ||
4380 | } | 6410 | } |
4381 | 6411 | ||
4382 | err = pci_enable_device(pci); | 6412 | err = pci_enable_device(pci); |
@@ -4393,22 +6423,21 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
4393 | io_extent = pci_resource_len(pci, 0); | 6423 | io_extent = pci_resource_len(pci, 0); |
4394 | 6424 | ||
4395 | snd_printdd("grabbed memory region 0x%lx-0x%lx\n", | 6425 | snd_printdd("grabbed memory region 0x%lx-0x%lx\n", |
4396 | hdspm->port, hdspm->port + io_extent - 1); | 6426 | hdspm->port, hdspm->port + io_extent - 1); |
4397 | |||
4398 | 6427 | ||
4399 | hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); | 6428 | hdspm->iobase = ioremap_nocache(hdspm->port, io_extent); |
4400 | if (!hdspm->iobase) { | 6429 | if (!hdspm->iobase) { |
4401 | snd_printk(KERN_ERR "HDSPM: " | 6430 | snd_printk(KERN_ERR "HDSPM: " |
4402 | "unable to remap region 0x%lx-0x%lx\n", | 6431 | "unable to remap region 0x%lx-0x%lx\n", |
4403 | hdspm->port, hdspm->port + io_extent - 1); | 6432 | hdspm->port, hdspm->port + io_extent - 1); |
4404 | return -EBUSY; | 6433 | return -EBUSY; |
4405 | } | 6434 | } |
4406 | snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", | 6435 | snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n", |
4407 | (unsigned long)hdspm->iobase, hdspm->port, | 6436 | (unsigned long)hdspm->iobase, hdspm->port, |
4408 | hdspm->port + io_extent - 1); | 6437 | hdspm->port + io_extent - 1); |
4409 | 6438 | ||
4410 | if (request_irq(pci->irq, snd_hdspm_interrupt, | 6439 | if (request_irq(pci->irq, snd_hdspm_interrupt, |
4411 | IRQF_SHARED, "hdspm", hdspm)) { | 6440 | IRQF_SHARED, "hdspm", hdspm)) { |
4412 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); | 6441 | snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq); |
4413 | return -EBUSY; | 6442 | return -EBUSY; |
4414 | } | 6443 | } |
@@ -4416,23 +6445,219 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
4416 | snd_printdd("use IRQ %d\n", pci->irq); | 6445 | snd_printdd("use IRQ %d\n", pci->irq); |
4417 | 6446 | ||
4418 | hdspm->irq = pci->irq; | 6447 | hdspm->irq = pci->irq; |
4419 | hdspm->precise_ptr = precise_ptr; | ||
4420 | |||
4421 | hdspm->monitor_outs = enable_monitor; | ||
4422 | 6448 | ||
4423 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", | 6449 | snd_printdd("kmalloc Mixer memory of %zd Bytes\n", |
4424 | sizeof(struct hdspm_mixer)); | 6450 | sizeof(struct hdspm_mixer)); |
4425 | hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); | 6451 | hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL); |
4426 | if (!hdspm->mixer) { | 6452 | if (!hdspm->mixer) { |
4427 | snd_printk(KERN_ERR "HDSPM: " | 6453 | snd_printk(KERN_ERR "HDSPM: " |
4428 | "unable to kmalloc Mixer memory of %d Bytes\n", | 6454 | "unable to kmalloc Mixer memory of %d Bytes\n", |
4429 | (int)sizeof(struct hdspm_mixer)); | 6455 | (int)sizeof(struct hdspm_mixer)); |
4430 | return err; | 6456 | return err; |
4431 | } | 6457 | } |
4432 | 6458 | ||
4433 | hdspm->ss_channels = MADI_SS_CHANNELS; | 6459 | hdspm->port_names_in = NULL; |
4434 | hdspm->ds_channels = MADI_DS_CHANNELS; | 6460 | hdspm->port_names_out = NULL; |
4435 | hdspm->qs_channels = MADI_QS_CHANNELS; | 6461 | |
6462 | switch (hdspm->io_type) { | ||
6463 | case AES32: | ||
6464 | hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS; | ||
6465 | hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS; | ||
6466 | hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS; | ||
6467 | |||
6468 | hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = | ||
6469 | channel_map_aes32; | ||
6470 | hdspm->channel_map_in_ds = hdspm->channel_map_out_ds = | ||
6471 | channel_map_aes32; | ||
6472 | hdspm->channel_map_in_qs = hdspm->channel_map_out_qs = | ||
6473 | channel_map_aes32; | ||
6474 | hdspm->port_names_in_ss = hdspm->port_names_out_ss = | ||
6475 | texts_ports_aes32; | ||
6476 | hdspm->port_names_in_ds = hdspm->port_names_out_ds = | ||
6477 | texts_ports_aes32; | ||
6478 | hdspm->port_names_in_qs = hdspm->port_names_out_qs = | ||
6479 | texts_ports_aes32; | ||
6480 | |||
6481 | hdspm->max_channels_out = hdspm->max_channels_in = | ||
6482 | AES32_CHANNELS; | ||
6483 | hdspm->port_names_in = hdspm->port_names_out = | ||
6484 | texts_ports_aes32; | ||
6485 | hdspm->channel_map_in = hdspm->channel_map_out = | ||
6486 | channel_map_aes32; | ||
6487 | |||
6488 | break; | ||
6489 | |||
6490 | case MADI: | ||
6491 | case MADIface: | ||
6492 | hdspm->ss_in_channels = hdspm->ss_out_channels = | ||
6493 | MADI_SS_CHANNELS; | ||
6494 | hdspm->ds_in_channels = hdspm->ds_out_channels = | ||
6495 | MADI_DS_CHANNELS; | ||
6496 | hdspm->qs_in_channels = hdspm->qs_out_channels = | ||
6497 | MADI_QS_CHANNELS; | ||
6498 | |||
6499 | hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = | ||
6500 | channel_map_unity_ss; | ||
6501 | hdspm->channel_map_in_ds = hdspm->channel_map_out_ds = | ||
6502 | channel_map_unity_ss; | ||
6503 | hdspm->channel_map_in_qs = hdspm->channel_map_out_qs = | ||
6504 | channel_map_unity_ss; | ||
6505 | |||
6506 | hdspm->port_names_in_ss = hdspm->port_names_out_ss = | ||
6507 | texts_ports_madi; | ||
6508 | hdspm->port_names_in_ds = hdspm->port_names_out_ds = | ||
6509 | texts_ports_madi; | ||
6510 | hdspm->port_names_in_qs = hdspm->port_names_out_qs = | ||
6511 | texts_ports_madi; | ||
6512 | break; | ||
6513 | |||
6514 | case AIO: | ||
6515 | if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) { | ||
6516 | snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n"); | ||
6517 | } | ||
6518 | |||
6519 | hdspm->ss_in_channels = AIO_IN_SS_CHANNELS; | ||
6520 | hdspm->ds_in_channels = AIO_IN_DS_CHANNELS; | ||
6521 | hdspm->qs_in_channels = AIO_IN_QS_CHANNELS; | ||
6522 | hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS; | ||
6523 | hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS; | ||
6524 | hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS; | ||
6525 | |||
6526 | hdspm->channel_map_out_ss = channel_map_aio_out_ss; | ||
6527 | hdspm->channel_map_out_ds = channel_map_aio_out_ds; | ||
6528 | hdspm->channel_map_out_qs = channel_map_aio_out_qs; | ||
6529 | |||
6530 | hdspm->channel_map_in_ss = channel_map_aio_in_ss; | ||
6531 | hdspm->channel_map_in_ds = channel_map_aio_in_ds; | ||
6532 | hdspm->channel_map_in_qs = channel_map_aio_in_qs; | ||
6533 | |||
6534 | hdspm->port_names_in_ss = texts_ports_aio_in_ss; | ||
6535 | hdspm->port_names_out_ss = texts_ports_aio_out_ss; | ||
6536 | hdspm->port_names_in_ds = texts_ports_aio_in_ds; | ||
6537 | hdspm->port_names_out_ds = texts_ports_aio_out_ds; | ||
6538 | hdspm->port_names_in_qs = texts_ports_aio_in_qs; | ||
6539 | hdspm->port_names_out_qs = texts_ports_aio_out_qs; | ||
6540 | |||
6541 | break; | ||
6542 | |||
6543 | case RayDAT: | ||
6544 | hdspm->ss_in_channels = hdspm->ss_out_channels = | ||
6545 | RAYDAT_SS_CHANNELS; | ||
6546 | hdspm->ds_in_channels = hdspm->ds_out_channels = | ||
6547 | RAYDAT_DS_CHANNELS; | ||
6548 | hdspm->qs_in_channels = hdspm->qs_out_channels = | ||
6549 | RAYDAT_QS_CHANNELS; | ||
6550 | |||
6551 | hdspm->max_channels_in = RAYDAT_SS_CHANNELS; | ||
6552 | hdspm->max_channels_out = RAYDAT_SS_CHANNELS; | ||
6553 | |||
6554 | hdspm->channel_map_in_ss = hdspm->channel_map_out_ss = | ||
6555 | channel_map_raydat_ss; | ||
6556 | hdspm->channel_map_in_ds = hdspm->channel_map_out_ds = | ||
6557 | channel_map_raydat_ds; | ||
6558 | hdspm->channel_map_in_qs = hdspm->channel_map_out_qs = | ||
6559 | channel_map_raydat_qs; | ||
6560 | hdspm->channel_map_in = hdspm->channel_map_out = | ||
6561 | channel_map_raydat_ss; | ||
6562 | |||
6563 | hdspm->port_names_in_ss = hdspm->port_names_out_ss = | ||
6564 | texts_ports_raydat_ss; | ||
6565 | hdspm->port_names_in_ds = hdspm->port_names_out_ds = | ||
6566 | texts_ports_raydat_ds; | ||
6567 | hdspm->port_names_in_qs = hdspm->port_names_out_qs = | ||
6568 | texts_ports_raydat_qs; | ||
6569 | |||
6570 | |||
6571 | break; | ||
6572 | |||
6573 | } | ||
6574 | |||
6575 | /* TCO detection */ | ||
6576 | switch (hdspm->io_type) { | ||
6577 | case AIO: | ||
6578 | case RayDAT: | ||
6579 | if (hdspm_read(hdspm, HDSPM_statusRegister2) & | ||
6580 | HDSPM_s2_tco_detect) { | ||
6581 | hdspm->midiPorts++; | ||
6582 | hdspm->tco = kzalloc(sizeof(struct hdspm_tco), | ||
6583 | GFP_KERNEL); | ||
6584 | if (NULL != hdspm->tco) { | ||
6585 | hdspm_tco_write(hdspm); | ||
6586 | } | ||
6587 | snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n"); | ||
6588 | } else { | ||
6589 | hdspm->tco = NULL; | ||
6590 | } | ||
6591 | break; | ||
6592 | |||
6593 | case MADI: | ||
6594 | if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) { | ||
6595 | hdspm->midiPorts++; | ||
6596 | hdspm->tco = kzalloc(sizeof(struct hdspm_tco), | ||
6597 | GFP_KERNEL); | ||
6598 | if (NULL != hdspm->tco) { | ||
6599 | hdspm_tco_write(hdspm); | ||
6600 | } | ||
6601 | snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n"); | ||
6602 | } else { | ||
6603 | hdspm->tco = NULL; | ||
6604 | } | ||
6605 | break; | ||
6606 | |||
6607 | default: | ||
6608 | hdspm->tco = NULL; | ||
6609 | } | ||
6610 | |||
6611 | /* texts */ | ||
6612 | switch (hdspm->io_type) { | ||
6613 | case AES32: | ||
6614 | if (hdspm->tco) { | ||
6615 | hdspm->texts_autosync = texts_autosync_aes_tco; | ||
6616 | hdspm->texts_autosync_items = 10; | ||
6617 | } else { | ||
6618 | hdspm->texts_autosync = texts_autosync_aes; | ||
6619 | hdspm->texts_autosync_items = 9; | ||
6620 | } | ||
6621 | break; | ||
6622 | |||
6623 | case MADI: | ||
6624 | if (hdspm->tco) { | ||
6625 | hdspm->texts_autosync = texts_autosync_madi_tco; | ||
6626 | hdspm->texts_autosync_items = 4; | ||
6627 | } else { | ||
6628 | hdspm->texts_autosync = texts_autosync_madi; | ||
6629 | hdspm->texts_autosync_items = 3; | ||
6630 | } | ||
6631 | break; | ||
6632 | |||
6633 | case MADIface: | ||
6634 | |||
6635 | break; | ||
6636 | |||
6637 | case RayDAT: | ||
6638 | if (hdspm->tco) { | ||
6639 | hdspm->texts_autosync = texts_autosync_raydat_tco; | ||
6640 | hdspm->texts_autosync_items = 9; | ||
6641 | } else { | ||
6642 | hdspm->texts_autosync = texts_autosync_raydat; | ||
6643 | hdspm->texts_autosync_items = 8; | ||
6644 | } | ||
6645 | break; | ||
6646 | |||
6647 | case AIO: | ||
6648 | if (hdspm->tco) { | ||
6649 | hdspm->texts_autosync = texts_autosync_aio_tco; | ||
6650 | hdspm->texts_autosync_items = 6; | ||
6651 | } else { | ||
6652 | hdspm->texts_autosync = texts_autosync_aio; | ||
6653 | hdspm->texts_autosync_items = 5; | ||
6654 | } | ||
6655 | break; | ||
6656 | |||
6657 | } | ||
6658 | |||
6659 | tasklet_init(&hdspm->midi_tasklet, | ||
6660 | hdspm_midi_tasklet, (unsigned long) hdspm); | ||
4436 | 6661 | ||
4437 | snd_printdd("create alsa devices.\n"); | 6662 | snd_printdd("create alsa devices.\n"); |
4438 | err = snd_hdspm_create_alsa_devices(card, hdspm); | 6663 | err = snd_hdspm_create_alsa_devices(card, hdspm); |
@@ -4444,6 +6669,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card, | |||
4444 | return 0; | 6669 | return 0; |
4445 | } | 6670 | } |
4446 | 6671 | ||
6672 | |||
4447 | static int snd_hdspm_free(struct hdspm * hdspm) | 6673 | static int snd_hdspm_free(struct hdspm * hdspm) |
4448 | { | 6674 | { |
4449 | 6675 | ||
@@ -4452,7 +6678,8 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4452 | /* stop th audio, and cancel all interrupts */ | 6678 | /* stop th audio, and cancel all interrupts */ |
4453 | hdspm->control_register &= | 6679 | hdspm->control_register &= |
4454 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | | 6680 | ~(HDSPM_Start | HDSPM_AudioInterruptEnable | |
4455 | HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable); | 6681 | HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable | |
6682 | HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable); | ||
4456 | hdspm_write(hdspm, HDSPM_controlRegister, | 6683 | hdspm_write(hdspm, HDSPM_controlRegister, |
4457 | hdspm->control_register); | 6684 | hdspm->control_register); |
4458 | } | 6685 | } |
@@ -4472,6 +6699,7 @@ static int snd_hdspm_free(struct hdspm * hdspm) | |||
4472 | return 0; | 6699 | return 0; |
4473 | } | 6700 | } |
4474 | 6701 | ||
6702 | |||
4475 | static void snd_hdspm_card_free(struct snd_card *card) | 6703 | static void snd_hdspm_card_free(struct snd_card *card) |
4476 | { | 6704 | { |
4477 | struct hdspm *hdspm = card->private_data; | 6705 | struct hdspm *hdspm = card->private_data; |
@@ -4480,6 +6708,7 @@ static void snd_hdspm_card_free(struct snd_card *card) | |||
4480 | snd_hdspm_free(hdspm); | 6708 | snd_hdspm_free(hdspm); |
4481 | } | 6709 | } |
4482 | 6710 | ||
6711 | |||
4483 | static int __devinit snd_hdspm_probe(struct pci_dev *pci, | 6712 | static int __devinit snd_hdspm_probe(struct pci_dev *pci, |
4484 | const struct pci_device_id *pci_id) | 6713 | const struct pci_device_id *pci_id) |
4485 | { | 6714 | { |
@@ -4496,7 +6725,7 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4496 | } | 6725 | } |
4497 | 6726 | ||
4498 | err = snd_card_create(index[dev], id[dev], | 6727 | err = snd_card_create(index[dev], id[dev], |
4499 | THIS_MODULE, sizeof(struct hdspm), &card); | 6728 | THIS_MODULE, sizeof(struct hdspm), &card); |
4500 | if (err < 0) | 6729 | if (err < 0) |
4501 | return err; | 6730 | return err; |
4502 | 6731 | ||
@@ -4507,16 +6736,25 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci, | |||
4507 | 6736 | ||
4508 | snd_card_set_dev(card, &pci->dev); | 6737 | snd_card_set_dev(card, &pci->dev); |
4509 | 6738 | ||
4510 | err = snd_hdspm_create(card, hdspm, precise_ptr[dev], | 6739 | err = snd_hdspm_create(card, hdspm); |
4511 | enable_monitor[dev]); | ||
4512 | if (err < 0) { | 6740 | if (err < 0) { |
4513 | snd_card_free(card); | 6741 | snd_card_free(card); |
4514 | return err; | 6742 | return err; |
4515 | } | 6743 | } |
4516 | 6744 | ||
4517 | strcpy(card->shortname, "HDSPM MADI"); | 6745 | if (hdspm->io_type != MADIface) { |
4518 | sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name, | 6746 | sprintf(card->shortname, "%s_%x", |
4519 | hdspm->port, hdspm->irq); | 6747 | hdspm->card_name, |
6748 | (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF); | ||
6749 | sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d", | ||
6750 | hdspm->card_name, | ||
6751 | (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF, | ||
6752 | hdspm->port, hdspm->irq); | ||
6753 | } else { | ||
6754 | sprintf(card->shortname, "%s", hdspm->card_name); | ||
6755 | sprintf(card->longname, "%s at 0x%lx, irq %d", | ||
6756 | hdspm->card_name, hdspm->port, hdspm->irq); | ||
6757 | } | ||
4520 | 6758 | ||
4521 | err = snd_card_register(card); | 6759 | err = snd_card_register(card); |
4522 | if (err < 0) { | 6760 | if (err < 0) { |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index b47cfd45b3b9..3ecbd67f88c9 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -1034,7 +1034,11 @@ static int __devinit snd_pmac_detect(struct snd_pmac *chip) | |||
1034 | if (of_device_is_compatible(sound, "tumbler")) { | 1034 | if (of_device_is_compatible(sound, "tumbler")) { |
1035 | chip->model = PMAC_TUMBLER; | 1035 | chip->model = PMAC_TUMBLER; |
1036 | chip->can_capture = of_machine_is_compatible("PowerMac4,2") | 1036 | chip->can_capture = of_machine_is_compatible("PowerMac4,2") |
1037 | || of_machine_is_compatible("PowerBook4,1"); | 1037 | || of_machine_is_compatible("PowerBook3,2") |
1038 | || of_machine_is_compatible("PowerBook3,3") | ||
1039 | || of_machine_is_compatible("PowerBook4,1") | ||
1040 | || of_machine_is_compatible("PowerBook4,2") | ||
1041 | || of_machine_is_compatible("PowerBook4,3"); | ||
1038 | chip->can_duplex = 0; | 1042 | chip->can_duplex = 0; |
1039 | // chip->can_byte_swap = 0; /* FIXME: check this */ | 1043 | // chip->can_byte_swap = 0; /* FIXME: check this */ |
1040 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); | 1044 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index a3efc52a34da..8224db5f0434 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -50,10 +50,12 @@ source "sound/soc/jz4740/Kconfig" | |||
50 | source "sound/soc/nuc900/Kconfig" | 50 | source "sound/soc/nuc900/Kconfig" |
51 | source "sound/soc/omap/Kconfig" | 51 | source "sound/soc/omap/Kconfig" |
52 | source "sound/soc/kirkwood/Kconfig" | 52 | source "sound/soc/kirkwood/Kconfig" |
53 | source "sound/soc/mid-x86/Kconfig" | ||
53 | source "sound/soc/pxa/Kconfig" | 54 | source "sound/soc/pxa/Kconfig" |
54 | source "sound/soc/samsung/Kconfig" | 55 | source "sound/soc/samsung/Kconfig" |
55 | source "sound/soc/s6000/Kconfig" | 56 | source "sound/soc/s6000/Kconfig" |
56 | source "sound/soc/sh/Kconfig" | 57 | source "sound/soc/sh/Kconfig" |
58 | source "sound/soc/tegra/Kconfig" | ||
57 | source "sound/soc/txx9/Kconfig" | 59 | source "sound/soc/txx9/Kconfig" |
58 | 60 | ||
59 | # Supported codecs | 61 | # Supported codecs |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index ce913bf5213c..1ed61c5df2c5 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_SND_SOC) += ep93xx/ | |||
10 | obj-$(CONFIG_SND_SOC) += fsl/ | 10 | obj-$(CONFIG_SND_SOC) += fsl/ |
11 | obj-$(CONFIG_SND_SOC) += imx/ | 11 | obj-$(CONFIG_SND_SOC) += imx/ |
12 | obj-$(CONFIG_SND_SOC) += jz4740/ | 12 | obj-$(CONFIG_SND_SOC) += jz4740/ |
13 | obj-$(CONFIG_SND_SOC) += mid-x86/ | ||
13 | obj-$(CONFIG_SND_SOC) += nuc900/ | 14 | obj-$(CONFIG_SND_SOC) += nuc900/ |
14 | obj-$(CONFIG_SND_SOC) += omap/ | 15 | obj-$(CONFIG_SND_SOC) += omap/ |
15 | obj-$(CONFIG_SND_SOC) += kirkwood/ | 16 | obj-$(CONFIG_SND_SOC) += kirkwood/ |
@@ -17,4 +18,5 @@ obj-$(CONFIG_SND_SOC) += pxa/ | |||
17 | obj-$(CONFIG_SND_SOC) += samsung/ | 18 | obj-$(CONFIG_SND_SOC) += samsung/ |
18 | obj-$(CONFIG_SND_SOC) += s6000/ | 19 | obj-$(CONFIG_SND_SOC) += s6000/ |
19 | obj-$(CONFIG_SND_SOC) += sh/ | 20 | obj-$(CONFIG_SND_SOC) += sh/ |
21 | obj-$(CONFIG_SND_SOC) += tegra/ | ||
20 | obj-$(CONFIG_SND_SOC) += txx9/ | 22 | obj-$(CONFIG_SND_SOC) += txx9/ |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index c48b23c1d4fc..d63c1754e05f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -26,17 +26,24 @@ config SND_SOC_ALL_CODECS | |||
26 | select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC | 26 | select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC |
27 | select SND_SOC_CS42L51 if I2C | 27 | select SND_SOC_CS42L51 if I2C |
28 | select SND_SOC_CS4270 if I2C | 28 | select SND_SOC_CS4270 if I2C |
29 | select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI | ||
29 | select SND_SOC_CX20442 | 30 | select SND_SOC_CX20442 |
30 | select SND_SOC_DA7210 if I2C | 31 | select SND_SOC_DA7210 if I2C |
32 | select SND_SOC_DFBMCS320 | ||
31 | select SND_SOC_JZ4740_CODEC if SOC_JZ4740 | 33 | select SND_SOC_JZ4740_CODEC if SOC_JZ4740 |
34 | select SND_SOC_LM4857 if I2C | ||
32 | select SND_SOC_MAX98088 if I2C | 35 | select SND_SOC_MAX98088 if I2C |
36 | select SND_SOC_MAX9850 if I2C | ||
33 | select SND_SOC_MAX9877 if I2C | 37 | select SND_SOC_MAX9877 if I2C |
34 | select SND_SOC_PCM3008 | 38 | select SND_SOC_PCM3008 |
39 | select SND_SOC_SGTL5000 if I2C | ||
40 | select SND_SOC_SN95031 if INTEL_SCU_IPC | ||
35 | select SND_SOC_SPDIF | 41 | select SND_SOC_SPDIF |
36 | select SND_SOC_SSM2602 if I2C | 42 | select SND_SOC_SSM2602 if I2C |
37 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS | 43 | select SND_SOC_STAC9766 if SND_SOC_AC97_BUS |
38 | select SND_SOC_TLV320AIC23 if I2C | 44 | select SND_SOC_TLV320AIC23 if I2C |
39 | select SND_SOC_TLV320AIC26 if SPI_MASTER | 45 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
46 | select SND_SOC_TVL320AIC32X4 if I2C | ||
40 | select SND_SOC_TLV320AIC3X if I2C | 47 | select SND_SOC_TLV320AIC3X if I2C |
41 | select SND_SOC_TPA6130A2 if I2C | 48 | select SND_SOC_TPA6130A2 if I2C |
42 | select SND_SOC_TLV320DAC33 if I2C | 49 | select SND_SOC_TLV320DAC33 if I2C |
@@ -76,6 +83,7 @@ config SND_SOC_ALL_CODECS | |||
76 | select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI | 83 | select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI |
77 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI | 84 | select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI |
78 | select SND_SOC_WM8990 if I2C | 85 | select SND_SOC_WM8990 if I2C |
86 | select SND_SOC_WM8991 if I2C | ||
79 | select SND_SOC_WM8993 if I2C | 87 | select SND_SOC_WM8993 if I2C |
80 | select SND_SOC_WM8994 if MFD_WM8994 | 88 | select SND_SOC_WM8994 if MFD_WM8994 |
81 | select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI | 89 | select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI |
@@ -155,6 +163,9 @@ config SND_SOC_CS4270_VD33_ERRATA | |||
155 | bool | 163 | bool |
156 | depends on SND_SOC_CS4270 | 164 | depends on SND_SOC_CS4270 |
157 | 165 | ||
166 | config SND_SOC_CS4271 | ||
167 | tristate | ||
168 | |||
158 | config SND_SOC_CX20442 | 169 | config SND_SOC_CX20442 |
159 | tristate | 170 | tristate |
160 | 171 | ||
@@ -167,15 +178,28 @@ config SND_SOC_L3 | |||
167 | config SND_SOC_DA7210 | 178 | config SND_SOC_DA7210 |
168 | tristate | 179 | tristate |
169 | 180 | ||
181 | config SND_SOC_DFBMCS320 | ||
182 | tristate | ||
183 | |||
170 | config SND_SOC_DMIC | 184 | config SND_SOC_DMIC |
171 | tristate | 185 | tristate |
172 | 186 | ||
173 | config SND_SOC_MAX98088 | 187 | config SND_SOC_MAX98088 |
174 | tristate | 188 | tristate |
175 | 189 | ||
190 | config SND_SOC_MAX9850 | ||
191 | tristate | ||
192 | |||
176 | config SND_SOC_PCM3008 | 193 | config SND_SOC_PCM3008 |
177 | tristate | 194 | tristate |
178 | 195 | ||
196 | #Freescale sgtl5000 codec | ||
197 | config SND_SOC_SGTL5000 | ||
198 | tristate | ||
199 | |||
200 | config SND_SOC_SN95031 | ||
201 | tristate | ||
202 | |||
179 | config SND_SOC_SPDIF | 203 | config SND_SOC_SPDIF |
180 | tristate | 204 | tristate |
181 | 205 | ||
@@ -192,6 +216,9 @@ config SND_SOC_TLV320AIC26 | |||
192 | tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE | 216 | tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE |
193 | depends on SPI | 217 | depends on SPI |
194 | 218 | ||
219 | config SND_SOC_TVL320AIC32X4 | ||
220 | tristate | ||
221 | |||
195 | config SND_SOC_TLV320AIC3X | 222 | config SND_SOC_TLV320AIC3X |
196 | tristate | 223 | tristate |
197 | 224 | ||
@@ -304,6 +331,9 @@ config SND_SOC_WM8988 | |||
304 | config SND_SOC_WM8990 | 331 | config SND_SOC_WM8990 |
305 | tristate | 332 | tristate |
306 | 333 | ||
334 | config SND_SOC_WM8991 | ||
335 | tristate | ||
336 | |||
307 | config SND_SOC_WM8993 | 337 | config SND_SOC_WM8993 |
308 | tristate | 338 | tristate |
309 | 339 | ||
@@ -326,6 +356,9 @@ config SND_SOC_WM9713 | |||
326 | tristate | 356 | tristate |
327 | 357 | ||
328 | # Amp | 358 | # Amp |
359 | config SND_SOC_LM4857 | ||
360 | tristate | ||
361 | |||
329 | config SND_SOC_MAX9877 | 362 | config SND_SOC_MAX9877 |
330 | tristate | 363 | tristate |
331 | 364 | ||
@@ -337,4 +370,3 @@ config SND_SOC_WM2000 | |||
337 | 370 | ||
338 | config SND_SOC_WM9090 | 371 | config SND_SOC_WM9090 |
339 | tristate | 372 | tristate |
340 | |||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 579af9c4f128..379bc55f0723 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -12,19 +12,25 @@ snd-soc-ak4671-objs := ak4671.o | |||
12 | snd-soc-cq93vc-objs := cq93vc.o | 12 | snd-soc-cq93vc-objs := cq93vc.o |
13 | snd-soc-cs42l51-objs := cs42l51.o | 13 | snd-soc-cs42l51-objs := cs42l51.o |
14 | snd-soc-cs4270-objs := cs4270.o | 14 | snd-soc-cs4270-objs := cs4270.o |
15 | snd-soc-cs4271-objs := cs4271.o | ||
15 | snd-soc-cx20442-objs := cx20442.o | 16 | snd-soc-cx20442-objs := cx20442.o |
16 | snd-soc-da7210-objs := da7210.o | 17 | snd-soc-da7210-objs := da7210.o |
18 | snd-soc-dfbmcs320-objs := dfbmcs320.o | ||
17 | snd-soc-dmic-objs := dmic.o | 19 | snd-soc-dmic-objs := dmic.o |
18 | snd-soc-l3-objs := l3.o | 20 | snd-soc-l3-objs := l3.o |
19 | snd-soc-max98088-objs := max98088.o | 21 | snd-soc-max98088-objs := max98088.o |
22 | snd-soc-max9850-objs := max9850.o | ||
20 | snd-soc-pcm3008-objs := pcm3008.o | 23 | snd-soc-pcm3008-objs := pcm3008.o |
24 | snd-soc-sgtl5000-objs := sgtl5000.o | ||
21 | snd-soc-alc5623-objs := alc5623.o | 25 | snd-soc-alc5623-objs := alc5623.o |
26 | snd-soc-sn95031-objs := sn95031.o | ||
22 | snd-soc-spdif-objs := spdif_transciever.o | 27 | snd-soc-spdif-objs := spdif_transciever.o |
23 | snd-soc-ssm2602-objs := ssm2602.o | 28 | snd-soc-ssm2602-objs := ssm2602.o |
24 | snd-soc-stac9766-objs := stac9766.o | 29 | snd-soc-stac9766-objs := stac9766.o |
25 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 30 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
26 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 31 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
27 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | 32 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o |
33 | snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o | ||
28 | snd-soc-tlv320dac33-objs := tlv320dac33.o | 34 | snd-soc-tlv320dac33-objs := tlv320dac33.o |
29 | snd-soc-twl4030-objs := twl4030.o | 35 | snd-soc-twl4030-objs := twl4030.o |
30 | snd-soc-twl6040-objs := twl6040.o | 36 | snd-soc-twl6040-objs := twl6040.o |
@@ -61,6 +67,7 @@ snd-soc-wm8978-objs := wm8978.o | |||
61 | snd-soc-wm8985-objs := wm8985.o | 67 | snd-soc-wm8985-objs := wm8985.o |
62 | snd-soc-wm8988-objs := wm8988.o | 68 | snd-soc-wm8988-objs := wm8988.o |
63 | snd-soc-wm8990-objs := wm8990.o | 69 | snd-soc-wm8990-objs := wm8990.o |
70 | snd-soc-wm8991-objs := wm8991.o | ||
64 | snd-soc-wm8993-objs := wm8993.o | 71 | snd-soc-wm8993-objs := wm8993.o |
65 | snd-soc-wm8994-objs := wm8994.o wm8994-tables.o | 72 | snd-soc-wm8994-objs := wm8994.o wm8994-tables.o |
66 | snd-soc-wm8995-objs := wm8995.o | 73 | snd-soc-wm8995-objs := wm8995.o |
@@ -72,6 +79,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o | |||
72 | snd-soc-jz4740-codec-objs := jz4740.o | 79 | snd-soc-jz4740-codec-objs := jz4740.o |
73 | 80 | ||
74 | # Amp | 81 | # Amp |
82 | snd-soc-lm4857-objs := lm4857.o | ||
75 | snd-soc-max9877-objs := max9877.o | 83 | snd-soc-max9877-objs := max9877.o |
76 | snd-soc-tpa6130a2-objs := tpa6130a2.o | 84 | snd-soc-tpa6130a2-objs := tpa6130a2.o |
77 | snd-soc-wm2000-objs := wm2000.o | 85 | snd-soc-wm2000-objs := wm2000.o |
@@ -88,23 +96,29 @@ obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o | |||
88 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 96 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
89 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o | 97 | obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o |
90 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o | 98 | obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o |
99 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o | ||
91 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o | 100 | obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o |
92 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o | 101 | obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o |
93 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 102 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
103 | obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | ||
94 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 104 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
95 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 105 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
106 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o | ||
96 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 107 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
97 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 108 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
98 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 109 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
99 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o | 110 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o |
111 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | ||
100 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | 112 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o |
101 | obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o | 113 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
114 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | ||
102 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o | 115 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o |
103 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 116 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
104 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o | 117 | obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o |
105 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 118 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
106 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 119 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
107 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | 120 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o |
121 | obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o | ||
108 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o | 122 | obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o |
109 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | 123 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o |
110 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | 124 | obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o |
@@ -141,6 +155,7 @@ obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o | |||
141 | obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o | 155 | obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o |
142 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o | 156 | obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o |
143 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o | 157 | obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o |
158 | obj-$(CONFIG_SND_SOC_WM8991) += snd-soc-wm8991.o | ||
144 | obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o | 159 | obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o |
145 | obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o | 160 | obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o |
146 | obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o | 161 | obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o |
@@ -151,6 +166,7 @@ obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o | |||
151 | obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o | 166 | obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o |
152 | 167 | ||
153 | # Amp | 168 | # Amp |
169 | obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o | ||
154 | obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o | 170 | obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o |
155 | obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o | 171 | obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o |
156 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o | 172 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index c27f8f59dc66..cbf0b6d400b8 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -294,7 +294,6 @@ static struct spi_driver ak4104_spi_driver = { | |||
294 | 294 | ||
295 | static int __init ak4104_init(void) | 295 | static int __init ak4104_init(void) |
296 | { | 296 | { |
297 | pr_info("Asahi Kasei AK4104 ALSA SoC Codec Driver\n"); | ||
298 | return spi_register_driver(&ak4104_spi_driver); | 297 | return spi_register_driver(&ak4104_spi_driver); |
299 | } | 298 | } |
300 | module_init(ak4104_init); | 299 | module_init(ak4104_init); |
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index f00eba313dfd..4be0570e3f1f 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -116,6 +116,12 @@ | |||
116 | #define BCKO_MASK (1 << 3) | 116 | #define BCKO_MASK (1 << 3) |
117 | #define BCKO_64 BCKO_MASK | 117 | #define BCKO_64 BCKO_MASK |
118 | 118 | ||
119 | #define DIF_MASK (3 << 0) | ||
120 | #define DSP (0 << 0) | ||
121 | #define RIGHT_J (1 << 0) | ||
122 | #define LEFT_J (2 << 0) | ||
123 | #define I2S (3 << 0) | ||
124 | |||
119 | /* MD_CTL2 */ | 125 | /* MD_CTL2 */ |
120 | #define FS0 (1 << 0) | 126 | #define FS0 (1 << 0) |
121 | #define FS1 (1 << 1) | 127 | #define FS1 (1 << 1) |
@@ -354,6 +360,24 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | |||
354 | snd_soc_update_bits(codec, PW_MGMT2, MS, data); | 360 | snd_soc_update_bits(codec, PW_MGMT2, MS, data); |
355 | snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); | 361 | snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko); |
356 | 362 | ||
363 | /* format type */ | ||
364 | data = 0; | ||
365 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
366 | case SND_SOC_DAIFMT_LEFT_J: | ||
367 | data = LEFT_J; | ||
368 | break; | ||
369 | case SND_SOC_DAIFMT_I2S: | ||
370 | data = I2S; | ||
371 | break; | ||
372 | /* FIXME | ||
373 | * Please add RIGHT_J / DSP support here | ||
374 | */ | ||
375 | default: | ||
376 | return -EINVAL; | ||
377 | break; | ||
378 | } | ||
379 | snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data); | ||
380 | |||
357 | return 0; | 381 | return 0; |
358 | } | 382 | } |
359 | 383 | ||
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 8b51245f2318..0206a17d7283 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -193,12 +193,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = { | |||
193 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | 193 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ |
194 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) | 194 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) |
195 | 195 | ||
196 | static int cs4270_reg_is_readable(unsigned int reg) | 196 | static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg) |
197 | { | 197 | { |
198 | return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); | 198 | return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); |
199 | } | 199 | } |
200 | 200 | ||
201 | static int cs4270_reg_is_volatile(unsigned int reg) | 201 | static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg) |
202 | { | 202 | { |
203 | /* Unreadable registers are considered volatile */ | 203 | /* Unreadable registers are considered volatile */ |
204 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) | 204 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) |
@@ -719,7 +719,7 @@ static int cs4270_i2c_remove(struct i2c_client *i2c_client) | |||
719 | /* | 719 | /* |
720 | * cs4270_id - I2C device IDs supported by this driver | 720 | * cs4270_id - I2C device IDs supported by this driver |
721 | */ | 721 | */ |
722 | static struct i2c_device_id cs4270_id[] = { | 722 | static const struct i2c_device_id cs4270_id[] = { |
723 | {"cs4270", 0}, | 723 | {"cs4270", 0}, |
724 | {} | 724 | {} |
725 | }; | 725 | }; |
@@ -743,8 +743,6 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
743 | 743 | ||
744 | static int __init cs4270_init(void) | 744 | static int __init cs4270_init(void) |
745 | { | 745 | { |
746 | pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); | ||
747 | |||
748 | return i2c_add_driver(&cs4270_i2c_driver); | 746 | return i2c_add_driver(&cs4270_i2c_driver); |
749 | } | 747 | } |
750 | module_init(cs4270_init); | 748 | module_init(cs4270_init); |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c new file mode 100644 index 000000000000..083aab96ca80 --- /dev/null +++ b/sound/soc/codecs/cs4271.c | |||
@@ -0,0 +1,667 @@ | |||
1 | /* | ||
2 | * CS4271 ASoC codec driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (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 | * This driver support CS4271 codec being master or slave, working | ||
17 | * in control port mode, connected either via SPI or I2C. | ||
18 | * The data format accepted is I2S or left-justified. | ||
19 | * DAPM support not implemented. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/tlv.h> | ||
28 | #include <linux/gpio.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/spi/spi.h> | ||
31 | #include <sound/cs4271.h> | ||
32 | |||
33 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | ||
34 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
35 | SNDRV_PCM_FMTBIT_S32_LE) | ||
36 | #define CS4271_PCM_RATES SNDRV_PCM_RATE_8000_192000 | ||
37 | |||
38 | /* | ||
39 | * CS4271 registers | ||
40 | * High byte represents SPI chip address (0x10) + write command (0) | ||
41 | * Low byte - codec register address | ||
42 | */ | ||
43 | #define CS4271_MODE1 0x2001 /* Mode Control 1 */ | ||
44 | #define CS4271_DACCTL 0x2002 /* DAC Control */ | ||
45 | #define CS4271_DACVOL 0x2003 /* DAC Volume & Mixing Control */ | ||
46 | #define CS4271_VOLA 0x2004 /* DAC Channel A Volume Control */ | ||
47 | #define CS4271_VOLB 0x2005 /* DAC Channel B Volume Control */ | ||
48 | #define CS4271_ADCCTL 0x2006 /* ADC Control */ | ||
49 | #define CS4271_MODE2 0x2007 /* Mode Control 2 */ | ||
50 | #define CS4271_CHIPID 0x2008 /* Chip ID */ | ||
51 | |||
52 | #define CS4271_FIRSTREG CS4271_MODE1 | ||
53 | #define CS4271_LASTREG CS4271_MODE2 | ||
54 | #define CS4271_NR_REGS ((CS4271_LASTREG & 0xFF) + 1) | ||
55 | |||
56 | /* Bit masks for the CS4271 registers */ | ||
57 | #define CS4271_MODE1_MODE_MASK 0xC0 | ||
58 | #define CS4271_MODE1_MODE_1X 0x00 | ||
59 | #define CS4271_MODE1_MODE_2X 0x80 | ||
60 | #define CS4271_MODE1_MODE_4X 0xC0 | ||
61 | |||
62 | #define CS4271_MODE1_DIV_MASK 0x30 | ||
63 | #define CS4271_MODE1_DIV_1 0x00 | ||
64 | #define CS4271_MODE1_DIV_15 0x10 | ||
65 | #define CS4271_MODE1_DIV_2 0x20 | ||
66 | #define CS4271_MODE1_DIV_3 0x30 | ||
67 | |||
68 | #define CS4271_MODE1_MASTER 0x08 | ||
69 | |||
70 | #define CS4271_MODE1_DAC_DIF_MASK 0x07 | ||
71 | #define CS4271_MODE1_DAC_DIF_LJ 0x00 | ||
72 | #define CS4271_MODE1_DAC_DIF_I2S 0x01 | ||
73 | #define CS4271_MODE1_DAC_DIF_RJ16 0x02 | ||
74 | #define CS4271_MODE1_DAC_DIF_RJ24 0x03 | ||
75 | #define CS4271_MODE1_DAC_DIF_RJ20 0x04 | ||
76 | #define CS4271_MODE1_DAC_DIF_RJ18 0x05 | ||
77 | |||
78 | #define CS4271_DACCTL_AMUTE 0x80 | ||
79 | #define CS4271_DACCTL_IF_SLOW 0x40 | ||
80 | |||
81 | #define CS4271_DACCTL_DEM_MASK 0x30 | ||
82 | #define CS4271_DACCTL_DEM_DIS 0x00 | ||
83 | #define CS4271_DACCTL_DEM_441 0x10 | ||
84 | #define CS4271_DACCTL_DEM_48 0x20 | ||
85 | #define CS4271_DACCTL_DEM_32 0x30 | ||
86 | |||
87 | #define CS4271_DACCTL_SVRU 0x08 | ||
88 | #define CS4271_DACCTL_SRD 0x04 | ||
89 | #define CS4271_DACCTL_INVA 0x02 | ||
90 | #define CS4271_DACCTL_INVB 0x01 | ||
91 | |||
92 | #define CS4271_DACVOL_BEQUA 0x40 | ||
93 | #define CS4271_DACVOL_SOFT 0x20 | ||
94 | #define CS4271_DACVOL_ZEROC 0x10 | ||
95 | |||
96 | #define CS4271_DACVOL_ATAPI_MASK 0x0F | ||
97 | #define CS4271_DACVOL_ATAPI_M_M 0x00 | ||
98 | #define CS4271_DACVOL_ATAPI_M_BR 0x01 | ||
99 | #define CS4271_DACVOL_ATAPI_M_BL 0x02 | ||
100 | #define CS4271_DACVOL_ATAPI_M_BLR2 0x03 | ||
101 | #define CS4271_DACVOL_ATAPI_AR_M 0x04 | ||
102 | #define CS4271_DACVOL_ATAPI_AR_BR 0x05 | ||
103 | #define CS4271_DACVOL_ATAPI_AR_BL 0x06 | ||
104 | #define CS4271_DACVOL_ATAPI_AR_BLR2 0x07 | ||
105 | #define CS4271_DACVOL_ATAPI_AL_M 0x08 | ||
106 | #define CS4271_DACVOL_ATAPI_AL_BR 0x09 | ||
107 | #define CS4271_DACVOL_ATAPI_AL_BL 0x0A | ||
108 | #define CS4271_DACVOL_ATAPI_AL_BLR2 0x0B | ||
109 | #define CS4271_DACVOL_ATAPI_ALR2_M 0x0C | ||
110 | #define CS4271_DACVOL_ATAPI_ALR2_BR 0x0D | ||
111 | #define CS4271_DACVOL_ATAPI_ALR2_BL 0x0E | ||
112 | #define CS4271_DACVOL_ATAPI_ALR2_BLR2 0x0F | ||
113 | |||
114 | #define CS4271_VOLA_MUTE 0x80 | ||
115 | #define CS4271_VOLA_VOL_MASK 0x7F | ||
116 | #define CS4271_VOLB_MUTE 0x80 | ||
117 | #define CS4271_VOLB_VOL_MASK 0x7F | ||
118 | |||
119 | #define CS4271_ADCCTL_DITHER16 0x20 | ||
120 | |||
121 | #define CS4271_ADCCTL_ADC_DIF_MASK 0x10 | ||
122 | #define CS4271_ADCCTL_ADC_DIF_LJ 0x00 | ||
123 | #define CS4271_ADCCTL_ADC_DIF_I2S 0x10 | ||
124 | |||
125 | #define CS4271_ADCCTL_MUTEA 0x08 | ||
126 | #define CS4271_ADCCTL_MUTEB 0x04 | ||
127 | #define CS4271_ADCCTL_HPFDA 0x02 | ||
128 | #define CS4271_ADCCTL_HPFDB 0x01 | ||
129 | |||
130 | #define CS4271_MODE2_LOOP 0x10 | ||
131 | #define CS4271_MODE2_MUTECAEQUB 0x08 | ||
132 | #define CS4271_MODE2_FREEZE 0x04 | ||
133 | #define CS4271_MODE2_CPEN 0x02 | ||
134 | #define CS4271_MODE2_PDN 0x01 | ||
135 | |||
136 | #define CS4271_CHIPID_PART_MASK 0xF0 | ||
137 | #define CS4271_CHIPID_REV_MASK 0x0F | ||
138 | |||
139 | /* | ||
140 | * Default CS4271 power-up configuration | ||
141 | * Array contains non-existing in hw register at address 0 | ||
142 | * Array do not include Chip ID, as codec driver does not use | ||
143 | * registers read operations at all | ||
144 | */ | ||
145 | static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = { | ||
146 | 0, | ||
147 | 0, | ||
148 | CS4271_DACCTL_AMUTE, | ||
149 | CS4271_DACVOL_SOFT | CS4271_DACVOL_ATAPI_AL_BR, | ||
150 | 0, | ||
151 | 0, | ||
152 | 0, | ||
153 | 0, | ||
154 | }; | ||
155 | |||
156 | struct cs4271_private { | ||
157 | /* SND_SOC_I2C or SND_SOC_SPI */ | ||
158 | enum snd_soc_control_type bus_type; | ||
159 | void *control_data; | ||
160 | unsigned int mclk; | ||
161 | bool master; | ||
162 | bool deemph; | ||
163 | /* Current sample rate for de-emphasis control */ | ||
164 | int rate; | ||
165 | /* GPIO driving Reset pin, if any */ | ||
166 | int gpio_nreset; | ||
167 | /* GPIO that disable serial bus, if any */ | ||
168 | int gpio_disable; | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * @freq is the desired MCLK rate | ||
173 | * MCLK rate should (c) be the sample rate, multiplied by one of the | ||
174 | * ratios listed in cs4271_mclk_fs_ratios table | ||
175 | */ | ||
176 | static int cs4271_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
177 | int clk_id, unsigned int freq, int dir) | ||
178 | { | ||
179 | struct snd_soc_codec *codec = codec_dai->codec; | ||
180 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
181 | |||
182 | cs4271->mclk = freq; | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
187 | unsigned int format) | ||
188 | { | ||
189 | struct snd_soc_codec *codec = codec_dai->codec; | ||
190 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
191 | unsigned int val = 0; | ||
192 | int ret; | ||
193 | |||
194 | switch (format & SND_SOC_DAIFMT_MASTER_MASK) { | ||
195 | case SND_SOC_DAIFMT_CBS_CFS: | ||
196 | cs4271->master = 0; | ||
197 | break; | ||
198 | case SND_SOC_DAIFMT_CBM_CFM: | ||
199 | cs4271->master = 1; | ||
200 | val |= CS4271_MODE1_MASTER; | ||
201 | break; | ||
202 | default: | ||
203 | dev_err(codec->dev, "Invalid DAI format\n"); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
208 | case SND_SOC_DAIFMT_LEFT_J: | ||
209 | val |= CS4271_MODE1_DAC_DIF_LJ; | ||
210 | ret = snd_soc_update_bits(codec, CS4271_ADCCTL, | ||
211 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_LJ); | ||
212 | if (ret < 0) | ||
213 | return ret; | ||
214 | break; | ||
215 | case SND_SOC_DAIFMT_I2S: | ||
216 | val |= CS4271_MODE1_DAC_DIF_I2S; | ||
217 | ret = snd_soc_update_bits(codec, CS4271_ADCCTL, | ||
218 | CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S); | ||
219 | if (ret < 0) | ||
220 | return ret; | ||
221 | break; | ||
222 | default: | ||
223 | dev_err(codec->dev, "Invalid DAI format\n"); | ||
224 | return -EINVAL; | ||
225 | } | ||
226 | |||
227 | ret = snd_soc_update_bits(codec, CS4271_MODE1, | ||
228 | CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val); | ||
229 | if (ret < 0) | ||
230 | return ret; | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int cs4271_deemph[] = {0, 44100, 48000, 32000}; | ||
235 | |||
236 | static int cs4271_set_deemph(struct snd_soc_codec *codec) | ||
237 | { | ||
238 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
239 | int i, ret; | ||
240 | int val = CS4271_DACCTL_DEM_DIS; | ||
241 | |||
242 | if (cs4271->deemph) { | ||
243 | /* Find closest de-emphasis freq */ | ||
244 | val = 1; | ||
245 | for (i = 2; i < ARRAY_SIZE(cs4271_deemph); i++) | ||
246 | if (abs(cs4271_deemph[i] - cs4271->rate) < | ||
247 | abs(cs4271_deemph[val] - cs4271->rate)) | ||
248 | val = i; | ||
249 | val <<= 4; | ||
250 | } | ||
251 | |||
252 | ret = snd_soc_update_bits(codec, CS4271_DACCTL, | ||
253 | CS4271_DACCTL_DEM_MASK, val); | ||
254 | if (ret < 0) | ||
255 | return ret; | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int cs4271_get_deemph(struct snd_kcontrol *kcontrol, | ||
260 | struct snd_ctl_elem_value *ucontrol) | ||
261 | { | ||
262 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
263 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
264 | |||
265 | ucontrol->value.enumerated.item[0] = cs4271->deemph; | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static int cs4271_put_deemph(struct snd_kcontrol *kcontrol, | ||
270 | struct snd_ctl_elem_value *ucontrol) | ||
271 | { | ||
272 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
273 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
274 | |||
275 | cs4271->deemph = ucontrol->value.enumerated.item[0]; | ||
276 | return cs4271_set_deemph(codec); | ||
277 | } | ||
278 | |||
279 | struct cs4271_clk_cfg { | ||
280 | bool master; /* codec mode */ | ||
281 | u8 speed_mode; /* codec speed mode: 1x, 2x, 4x */ | ||
282 | unsigned short ratio; /* MCLK / sample rate */ | ||
283 | u8 ratio_mask; /* ratio bit mask for Master mode */ | ||
284 | }; | ||
285 | |||
286 | static struct cs4271_clk_cfg cs4271_clk_tab[] = { | ||
287 | {1, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1}, | ||
288 | {1, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_15}, | ||
289 | {1, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_2}, | ||
290 | {1, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_3}, | ||
291 | {1, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1}, | ||
292 | {1, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_15}, | ||
293 | {1, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_2}, | ||
294 | {1, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_3}, | ||
295 | {1, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1}, | ||
296 | {1, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_15}, | ||
297 | {1, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_2}, | ||
298 | {1, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_3}, | ||
299 | {0, CS4271_MODE1_MODE_1X, 256, CS4271_MODE1_DIV_1}, | ||
300 | {0, CS4271_MODE1_MODE_1X, 384, CS4271_MODE1_DIV_1}, | ||
301 | {0, CS4271_MODE1_MODE_1X, 512, CS4271_MODE1_DIV_1}, | ||
302 | {0, CS4271_MODE1_MODE_1X, 768, CS4271_MODE1_DIV_2}, | ||
303 | {0, CS4271_MODE1_MODE_1X, 1024, CS4271_MODE1_DIV_2}, | ||
304 | {0, CS4271_MODE1_MODE_2X, 128, CS4271_MODE1_DIV_1}, | ||
305 | {0, CS4271_MODE1_MODE_2X, 192, CS4271_MODE1_DIV_1}, | ||
306 | {0, CS4271_MODE1_MODE_2X, 256, CS4271_MODE1_DIV_1}, | ||
307 | {0, CS4271_MODE1_MODE_2X, 384, CS4271_MODE1_DIV_2}, | ||
308 | {0, CS4271_MODE1_MODE_2X, 512, CS4271_MODE1_DIV_2}, | ||
309 | {0, CS4271_MODE1_MODE_4X, 64, CS4271_MODE1_DIV_1}, | ||
310 | {0, CS4271_MODE1_MODE_4X, 96, CS4271_MODE1_DIV_1}, | ||
311 | {0, CS4271_MODE1_MODE_4X, 128, CS4271_MODE1_DIV_1}, | ||
312 | {0, CS4271_MODE1_MODE_4X, 192, CS4271_MODE1_DIV_2}, | ||
313 | {0, CS4271_MODE1_MODE_4X, 256, CS4271_MODE1_DIV_2}, | ||
314 | }; | ||
315 | |||
316 | #define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab) | ||
317 | |||
318 | static int cs4271_hw_params(struct snd_pcm_substream *substream, | ||
319 | struct snd_pcm_hw_params *params, | ||
320 | struct snd_soc_dai *dai) | ||
321 | { | ||
322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
323 | struct snd_soc_codec *codec = rtd->codec; | ||
324 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
325 | int i, ret; | ||
326 | unsigned int ratio, val; | ||
327 | |||
328 | cs4271->rate = params_rate(params); | ||
329 | |||
330 | /* Configure DAC */ | ||
331 | if (cs4271->rate < 50000) | ||
332 | val = CS4271_MODE1_MODE_1X; | ||
333 | else if (cs4271->rate < 100000) | ||
334 | val = CS4271_MODE1_MODE_2X; | ||
335 | else | ||
336 | val = CS4271_MODE1_MODE_4X; | ||
337 | |||
338 | ratio = cs4271->mclk / cs4271->rate; | ||
339 | for (i = 0; i < CS4171_NR_RATIOS; i++) | ||
340 | if ((cs4271_clk_tab[i].master == cs4271->master) && | ||
341 | (cs4271_clk_tab[i].speed_mode == val) && | ||
342 | (cs4271_clk_tab[i].ratio == ratio)) | ||
343 | break; | ||
344 | |||
345 | if (i == CS4171_NR_RATIOS) { | ||
346 | dev_err(codec->dev, "Invalid sample rate\n"); | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | |||
350 | val |= cs4271_clk_tab[i].ratio_mask; | ||
351 | |||
352 | ret = snd_soc_update_bits(codec, CS4271_MODE1, | ||
353 | CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val); | ||
354 | if (ret < 0) | ||
355 | return ret; | ||
356 | |||
357 | return cs4271_set_deemph(codec); | ||
358 | } | ||
359 | |||
360 | static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute) | ||
361 | { | ||
362 | struct snd_soc_codec *codec = dai->codec; | ||
363 | int ret; | ||
364 | int val_a = 0; | ||
365 | int val_b = 0; | ||
366 | |||
367 | if (mute) { | ||
368 | val_a = CS4271_VOLA_MUTE; | ||
369 | val_b = CS4271_VOLB_MUTE; | ||
370 | } | ||
371 | |||
372 | ret = snd_soc_update_bits(codec, CS4271_VOLA, CS4271_VOLA_MUTE, val_a); | ||
373 | if (ret < 0) | ||
374 | return ret; | ||
375 | ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b); | ||
376 | if (ret < 0) | ||
377 | return ret; | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | /* CS4271 controls */ | ||
383 | static DECLARE_TLV_DB_SCALE(cs4271_dac_tlv, -12700, 100, 0); | ||
384 | |||
385 | static const struct snd_kcontrol_new cs4271_snd_controls[] = { | ||
386 | SOC_DOUBLE_R_TLV("Master Playback Volume", CS4271_VOLA, CS4271_VOLB, | ||
387 | 0, 0x7F, 1, cs4271_dac_tlv), | ||
388 | SOC_SINGLE("Digital Loopback Switch", CS4271_MODE2, 4, 1, 0), | ||
389 | SOC_SINGLE("Soft Ramp Switch", CS4271_DACVOL, 5, 1, 0), | ||
390 | SOC_SINGLE("Zero Cross Switch", CS4271_DACVOL, 4, 1, 0), | ||
391 | SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0, | ||
392 | cs4271_get_deemph, cs4271_put_deemph), | ||
393 | SOC_SINGLE("Auto-Mute Switch", CS4271_DACCTL, 7, 1, 0), | ||
394 | SOC_SINGLE("Slow Roll Off Filter Switch", CS4271_DACCTL, 6, 1, 0), | ||
395 | SOC_SINGLE("Soft Volume Ramp-Up Switch", CS4271_DACCTL, 3, 1, 0), | ||
396 | SOC_SINGLE("Soft Ramp-Down Switch", CS4271_DACCTL, 2, 1, 0), | ||
397 | SOC_SINGLE("Left Channel Inversion Switch", CS4271_DACCTL, 1, 1, 0), | ||
398 | SOC_SINGLE("Right Channel Inversion Switch", CS4271_DACCTL, 0, 1, 0), | ||
399 | SOC_DOUBLE("Master Capture Switch", CS4271_ADCCTL, 3, 2, 1, 1), | ||
400 | SOC_SINGLE("Dither 16-Bit Data Switch", CS4271_ADCCTL, 5, 1, 0), | ||
401 | SOC_DOUBLE("High Pass Filter Switch", CS4271_ADCCTL, 1, 0, 1, 1), | ||
402 | SOC_DOUBLE_R("Master Playback Switch", CS4271_VOLA, CS4271_VOLB, | ||
403 | 7, 1, 1), | ||
404 | }; | ||
405 | |||
406 | static struct snd_soc_dai_ops cs4271_dai_ops = { | ||
407 | .hw_params = cs4271_hw_params, | ||
408 | .set_sysclk = cs4271_set_dai_sysclk, | ||
409 | .set_fmt = cs4271_set_dai_fmt, | ||
410 | .digital_mute = cs4271_digital_mute, | ||
411 | }; | ||
412 | |||
413 | static struct snd_soc_dai_driver cs4271_dai = { | ||
414 | .name = "cs4271-hifi", | ||
415 | .playback = { | ||
416 | .stream_name = "Playback", | ||
417 | .channels_min = 2, | ||
418 | .channels_max = 2, | ||
419 | .rates = CS4271_PCM_RATES, | ||
420 | .formats = CS4271_PCM_FORMATS, | ||
421 | }, | ||
422 | .capture = { | ||
423 | .stream_name = "Capture", | ||
424 | .channels_min = 2, | ||
425 | .channels_max = 2, | ||
426 | .rates = CS4271_PCM_RATES, | ||
427 | .formats = CS4271_PCM_FORMATS, | ||
428 | }, | ||
429 | .ops = &cs4271_dai_ops, | ||
430 | .symmetric_rates = 1, | ||
431 | }; | ||
432 | |||
433 | #ifdef CONFIG_PM | ||
434 | static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg) | ||
435 | { | ||
436 | int ret; | ||
437 | /* Set power-down bit */ | ||
438 | ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN); | ||
439 | if (ret < 0) | ||
440 | return ret; | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static int cs4271_soc_resume(struct snd_soc_codec *codec) | ||
445 | { | ||
446 | int ret; | ||
447 | /* Restore codec state */ | ||
448 | ret = snd_soc_cache_sync(codec); | ||
449 | if (ret < 0) | ||
450 | return ret; | ||
451 | /* then disable the power-down bit */ | ||
452 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); | ||
453 | if (ret < 0) | ||
454 | return ret; | ||
455 | return 0; | ||
456 | } | ||
457 | #else | ||
458 | #define cs4271_soc_suspend NULL | ||
459 | #define cs4271_soc_resume NULL | ||
460 | #endif /* CONFIG_PM */ | ||
461 | |||
462 | static int cs4271_probe(struct snd_soc_codec *codec) | ||
463 | { | ||
464 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
465 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; | ||
466 | int ret; | ||
467 | int gpio_nreset = -EINVAL; | ||
468 | |||
469 | codec->control_data = cs4271->control_data; | ||
470 | |||
471 | if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) | ||
472 | gpio_nreset = cs4271plat->gpio_nreset; | ||
473 | |||
474 | if (gpio_nreset >= 0) | ||
475 | if (gpio_request(gpio_nreset, "CS4271 Reset")) | ||
476 | gpio_nreset = -EINVAL; | ||
477 | if (gpio_nreset >= 0) { | ||
478 | /* Reset codec */ | ||
479 | gpio_direction_output(gpio_nreset, 0); | ||
480 | udelay(1); | ||
481 | gpio_set_value(gpio_nreset, 1); | ||
482 | /* Give the codec time to wake up */ | ||
483 | udelay(1); | ||
484 | } | ||
485 | |||
486 | cs4271->gpio_nreset = gpio_nreset; | ||
487 | |||
488 | /* | ||
489 | * In case of I2C, chip address specified in board data. | ||
490 | * So cache IO operations use 8 bit codec register address. | ||
491 | * In case of SPI, chip address and register address | ||
492 | * passed together as 16 bit value. | ||
493 | * Anyway, register address is masked with 0xFF inside | ||
494 | * soc-cache code. | ||
495 | */ | ||
496 | if (cs4271->bus_type == SND_SOC_SPI) | ||
497 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, | ||
498 | cs4271->bus_type); | ||
499 | else | ||
500 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, | ||
501 | cs4271->bus_type); | ||
502 | if (ret) { | ||
503 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
504 | return ret; | ||
505 | } | ||
506 | |||
507 | ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, | ||
508 | CS4271_MODE2_PDN | CS4271_MODE2_CPEN); | ||
509 | if (ret < 0) | ||
510 | return ret; | ||
511 | ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0); | ||
512 | if (ret < 0) | ||
513 | return ret; | ||
514 | /* Power-up sequence requires 85 uS */ | ||
515 | udelay(85); | ||
516 | |||
517 | return snd_soc_add_controls(codec, cs4271_snd_controls, | ||
518 | ARRAY_SIZE(cs4271_snd_controls)); | ||
519 | } | ||
520 | |||
521 | static int cs4271_remove(struct snd_soc_codec *codec) | ||
522 | { | ||
523 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | ||
524 | int gpio_nreset; | ||
525 | |||
526 | gpio_nreset = cs4271->gpio_nreset; | ||
527 | |||
528 | if (gpio_is_valid(gpio_nreset)) { | ||
529 | /* Set codec to the reset state */ | ||
530 | gpio_set_value(gpio_nreset, 0); | ||
531 | gpio_free(gpio_nreset); | ||
532 | } | ||
533 | |||
534 | return 0; | ||
535 | }; | ||
536 | |||
537 | static struct snd_soc_codec_driver soc_codec_dev_cs4271 = { | ||
538 | .probe = cs4271_probe, | ||
539 | .remove = cs4271_remove, | ||
540 | .suspend = cs4271_soc_suspend, | ||
541 | .resume = cs4271_soc_resume, | ||
542 | .reg_cache_default = cs4271_dflt_reg, | ||
543 | .reg_cache_size = ARRAY_SIZE(cs4271_dflt_reg), | ||
544 | .reg_word_size = sizeof(cs4271_dflt_reg[0]), | ||
545 | .compress_type = SND_SOC_FLAT_COMPRESSION, | ||
546 | }; | ||
547 | |||
548 | #if defined(CONFIG_SPI_MASTER) | ||
549 | static int __devinit cs4271_spi_probe(struct spi_device *spi) | ||
550 | { | ||
551 | struct cs4271_private *cs4271; | ||
552 | |||
553 | cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL); | ||
554 | if (!cs4271) | ||
555 | return -ENOMEM; | ||
556 | |||
557 | spi_set_drvdata(spi, cs4271); | ||
558 | cs4271->control_data = spi; | ||
559 | cs4271->bus_type = SND_SOC_SPI; | ||
560 | |||
561 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271, | ||
562 | &cs4271_dai, 1); | ||
563 | } | ||
564 | |||
565 | static int __devexit cs4271_spi_remove(struct spi_device *spi) | ||
566 | { | ||
567 | snd_soc_unregister_codec(&spi->dev); | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | static struct spi_driver cs4271_spi_driver = { | ||
572 | .driver = { | ||
573 | .name = "cs4271", | ||
574 | .owner = THIS_MODULE, | ||
575 | }, | ||
576 | .probe = cs4271_spi_probe, | ||
577 | .remove = __devexit_p(cs4271_spi_remove), | ||
578 | }; | ||
579 | #endif /* defined(CONFIG_SPI_MASTER) */ | ||
580 | |||
581 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
582 | static const struct i2c_device_id cs4271_i2c_id[] = { | ||
583 | {"cs4271", 0}, | ||
584 | {} | ||
585 | }; | ||
586 | MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); | ||
587 | |||
588 | static int __devinit cs4271_i2c_probe(struct i2c_client *client, | ||
589 | const struct i2c_device_id *id) | ||
590 | { | ||
591 | struct cs4271_private *cs4271; | ||
592 | |||
593 | cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL); | ||
594 | if (!cs4271) | ||
595 | return -ENOMEM; | ||
596 | |||
597 | i2c_set_clientdata(client, cs4271); | ||
598 | cs4271->control_data = client; | ||
599 | cs4271->bus_type = SND_SOC_I2C; | ||
600 | |||
601 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271, | ||
602 | &cs4271_dai, 1); | ||
603 | } | ||
604 | |||
605 | static int __devexit cs4271_i2c_remove(struct i2c_client *client) | ||
606 | { | ||
607 | snd_soc_unregister_codec(&client->dev); | ||
608 | return 0; | ||
609 | } | ||
610 | |||
611 | static struct i2c_driver cs4271_i2c_driver = { | ||
612 | .driver = { | ||
613 | .name = "cs4271", | ||
614 | .owner = THIS_MODULE, | ||
615 | }, | ||
616 | .id_table = cs4271_i2c_id, | ||
617 | .probe = cs4271_i2c_probe, | ||
618 | .remove = __devexit_p(cs4271_i2c_remove), | ||
619 | }; | ||
620 | #endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */ | ||
621 | |||
622 | /* | ||
623 | * We only register our serial bus driver here without | ||
624 | * assignment to particular chip. So if any of the below | ||
625 | * fails, there is some problem with I2C or SPI subsystem. | ||
626 | * In most cases this module will be compiled with support | ||
627 | * of only one serial bus. | ||
628 | */ | ||
629 | static int __init cs4271_modinit(void) | ||
630 | { | ||
631 | int ret; | ||
632 | |||
633 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
634 | ret = i2c_add_driver(&cs4271_i2c_driver); | ||
635 | if (ret) { | ||
636 | pr_err("Failed to register CS4271 I2C driver: %d\n", ret); | ||
637 | return ret; | ||
638 | } | ||
639 | #endif | ||
640 | |||
641 | #if defined(CONFIG_SPI_MASTER) | ||
642 | ret = spi_register_driver(&cs4271_spi_driver); | ||
643 | if (ret) { | ||
644 | pr_err("Failed to register CS4271 SPI driver: %d\n", ret); | ||
645 | return ret; | ||
646 | } | ||
647 | #endif | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | module_init(cs4271_modinit); | ||
652 | |||
653 | static void __exit cs4271_modexit(void) | ||
654 | { | ||
655 | #if defined(CONFIG_SPI_MASTER) | ||
656 | spi_unregister_driver(&cs4271_spi_driver); | ||
657 | #endif | ||
658 | |||
659 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
660 | i2c_del_driver(&cs4271_i2c_driver); | ||
661 | #endif | ||
662 | } | ||
663 | module_exit(cs4271_modexit); | ||
664 | |||
665 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
666 | MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver"); | ||
667 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/dfbmcs320.c new file mode 100644 index 000000000000..704bbde65737 --- /dev/null +++ b/sound/soc/codecs/dfbmcs320.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Driver for the DFBM-CS320 bluetooth module | ||
3 | * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | #include <sound/soc.h> | ||
17 | |||
18 | static struct snd_soc_dai_driver dfbmcs320_dai = { | ||
19 | .name = "dfbmcs320-pcm", | ||
20 | .playback = { | ||
21 | .channels_min = 1, | ||
22 | .channels_max = 1, | ||
23 | .rates = SNDRV_PCM_RATE_8000, | ||
24 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
25 | }, | ||
26 | .capture = { | ||
27 | .channels_min = 1, | ||
28 | .channels_max = 1, | ||
29 | .rates = SNDRV_PCM_RATE_8000, | ||
30 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
31 | }, | ||
32 | }; | ||
33 | |||
34 | static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320; | ||
35 | |||
36 | static int __devinit dfbmcs320_probe(struct platform_device *pdev) | ||
37 | { | ||
38 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320, | ||
39 | &dfbmcs320_dai, 1); | ||
40 | } | ||
41 | |||
42 | static int __devexit dfbmcs320_remove(struct platform_device *pdev) | ||
43 | { | ||
44 | snd_soc_unregister_codec(&pdev->dev); | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static struct platform_driver dfmcs320_driver = { | ||
50 | .driver = { | ||
51 | .name = "dfbmcs320", | ||
52 | .owner = THIS_MODULE, | ||
53 | }, | ||
54 | .probe = dfbmcs320_probe, | ||
55 | .remove = __devexit_p(dfbmcs320_remove), | ||
56 | }; | ||
57 | |||
58 | static int __init dfbmcs320_init(void) | ||
59 | { | ||
60 | return platform_driver_register(&dfmcs320_driver); | ||
61 | } | ||
62 | module_init(dfbmcs320_init); | ||
63 | |||
64 | static void __exit dfbmcs320_exit(void) | ||
65 | { | ||
66 | platform_driver_unregister(&dfmcs320_driver); | ||
67 | } | ||
68 | module_exit(dfbmcs320_exit); | ||
69 | |||
70 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
71 | MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver"); | ||
72 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c new file mode 100644 index 000000000000..72de47e5d040 --- /dev/null +++ b/sound/soc/codecs/lm4857.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * LM4857 AMP driver | ||
3 | * | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/soc.h> | ||
23 | #include <sound/tlv.h> | ||
24 | |||
25 | struct lm4857 { | ||
26 | struct i2c_client *i2c; | ||
27 | uint8_t mode; | ||
28 | }; | ||
29 | |||
30 | static const uint8_t lm4857_default_regs[] = { | ||
31 | 0x00, 0x00, 0x00, 0x00, | ||
32 | }; | ||
33 | |||
34 | /* The register offsets in the cache array */ | ||
35 | #define LM4857_MVOL 0 | ||
36 | #define LM4857_LVOL 1 | ||
37 | #define LM4857_RVOL 2 | ||
38 | #define LM4857_CTRL 3 | ||
39 | |||
40 | /* the shifts required to set these bits */ | ||
41 | #define LM4857_3D 5 | ||
42 | #define LM4857_WAKEUP 5 | ||
43 | #define LM4857_EPGAIN 4 | ||
44 | |||
45 | static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg, | ||
46 | unsigned int value) | ||
47 | { | ||
48 | uint8_t data; | ||
49 | int ret; | ||
50 | |||
51 | ret = snd_soc_cache_write(codec, reg, value); | ||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | |||
55 | data = (reg << 6) | value; | ||
56 | ret = i2c_master_send(codec->control_data, &data, 1); | ||
57 | if (ret != 1) { | ||
58 | dev_err(codec->dev, "Failed to write register: %d\n", ret); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static unsigned int lm4857_read(struct snd_soc_codec *codec, | ||
66 | unsigned int reg) | ||
67 | { | ||
68 | unsigned int val; | ||
69 | int ret; | ||
70 | |||
71 | ret = snd_soc_cache_read(codec, reg, &val); | ||
72 | if (ret) | ||
73 | return -1; | ||
74 | |||
75 | return val; | ||
76 | } | ||
77 | |||
78 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, | ||
79 | struct snd_ctl_elem_value *ucontrol) | ||
80 | { | ||
81 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
82 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
83 | |||
84 | ucontrol->value.integer.value[0] = lm4857->mode; | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int lm4857_set_mode(struct snd_kcontrol *kcontrol, | ||
90 | struct snd_ctl_elem_value *ucontrol) | ||
91 | { | ||
92 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
93 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
94 | uint8_t value = ucontrol->value.integer.value[0]; | ||
95 | |||
96 | lm4857->mode = value; | ||
97 | |||
98 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | ||
99 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6); | ||
100 | |||
101 | return 1; | ||
102 | } | ||
103 | |||
104 | static int lm4857_set_bias_level(struct snd_soc_codec *codec, | ||
105 | enum snd_soc_bias_level level) | ||
106 | { | ||
107 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
108 | |||
109 | switch (level) { | ||
110 | case SND_SOC_BIAS_ON: | ||
111 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6); | ||
112 | break; | ||
113 | case SND_SOC_BIAS_STANDBY: | ||
114 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0); | ||
115 | break; | ||
116 | default: | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | codec->dapm.bias_level = level; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static const char *lm4857_mode[] = { | ||
126 | "Earpiece", | ||
127 | "Loudspeaker", | ||
128 | "Loudspeaker + Headphone", | ||
129 | "Headphone", | ||
130 | }; | ||
131 | |||
132 | static const struct soc_enum lm4857_mode_enum = | ||
133 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode); | ||
134 | |||
135 | static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = { | ||
136 | SND_SOC_DAPM_INPUT("IN"), | ||
137 | |||
138 | SND_SOC_DAPM_OUTPUT("LS"), | ||
139 | SND_SOC_DAPM_OUTPUT("HP"), | ||
140 | SND_SOC_DAPM_OUTPUT("EP"), | ||
141 | }; | ||
142 | |||
143 | static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0); | ||
144 | static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0); | ||
145 | |||
146 | static const struct snd_kcontrol_new lm4857_controls[] = { | ||
147 | SOC_SINGLE_TLV("Left Playback Volume", LM4857_LVOL, 0, 31, 0, | ||
148 | stereo_tlv), | ||
149 | SOC_SINGLE_TLV("Right Playback Volume", LM4857_RVOL, 0, 31, 0, | ||
150 | stereo_tlv), | ||
151 | SOC_SINGLE_TLV("Mono Playback Volume", LM4857_MVOL, 0, 31, 0, | ||
152 | mono_tlv), | ||
153 | SOC_SINGLE("Spk 3D Playback Switch", LM4857_LVOL, LM4857_3D, 1, 0), | ||
154 | SOC_SINGLE("HP 3D Playback Switch", LM4857_RVOL, LM4857_3D, 1, 0), | ||
155 | SOC_SINGLE("Fast Wakeup Playback Switch", LM4857_CTRL, | ||
156 | LM4857_WAKEUP, 1, 0), | ||
157 | SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL, | ||
158 | LM4857_EPGAIN, 1, 0), | ||
159 | |||
160 | SOC_ENUM_EXT("Mode", lm4857_mode_enum, | ||
161 | lm4857_get_mode, lm4857_set_mode), | ||
162 | }; | ||
163 | |||
164 | /* There is a demux inbetween the the input signal and the output signals. | ||
165 | * Currently there is no easy way to model it in ASoC and since it does not make | ||
166 | * much of a difference in practice simply connect the input direclty to the | ||
167 | * outputs. */ | ||
168 | static const struct snd_soc_dapm_route lm4857_routes[] = { | ||
169 | {"LS", NULL, "IN"}, | ||
170 | {"HP", NULL, "IN"}, | ||
171 | {"EP", NULL, "IN"}, | ||
172 | }; | ||
173 | |||
174 | static int lm4857_probe(struct snd_soc_codec *codec) | ||
175 | { | ||
176 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
177 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
178 | int ret; | ||
179 | |||
180 | codec->control_data = lm4857->i2c; | ||
181 | |||
182 | ret = snd_soc_add_controls(codec, lm4857_controls, | ||
183 | ARRAY_SIZE(lm4857_controls)); | ||
184 | if (ret) | ||
185 | return ret; | ||
186 | |||
187 | ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets, | ||
188 | ARRAY_SIZE(lm4857_dapm_widgets)); | ||
189 | if (ret) | ||
190 | return ret; | ||
191 | |||
192 | ret = snd_soc_dapm_add_routes(dapm, lm4857_routes, | ||
193 | ARRAY_SIZE(lm4857_routes)); | ||
194 | if (ret) | ||
195 | return ret; | ||
196 | |||
197 | snd_soc_dapm_new_widgets(dapm); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { | ||
203 | .write = lm4857_write, | ||
204 | .read = lm4857_read, | ||
205 | .probe = lm4857_probe, | ||
206 | .reg_cache_size = ARRAY_SIZE(lm4857_default_regs), | ||
207 | .reg_word_size = sizeof(uint8_t), | ||
208 | .reg_cache_default = lm4857_default_regs, | ||
209 | .set_bias_level = lm4857_set_bias_level, | ||
210 | }; | ||
211 | |||
212 | static int __devinit lm4857_i2c_probe(struct i2c_client *i2c, | ||
213 | const struct i2c_device_id *id) | ||
214 | { | ||
215 | struct lm4857 *lm4857; | ||
216 | int ret; | ||
217 | |||
218 | lm4857 = kzalloc(sizeof(*lm4857), GFP_KERNEL); | ||
219 | if (!lm4857) | ||
220 | return -ENOMEM; | ||
221 | |||
222 | i2c_set_clientdata(i2c, lm4857); | ||
223 | |||
224 | lm4857->i2c = i2c; | ||
225 | |||
226 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); | ||
227 | |||
228 | if (ret) { | ||
229 | kfree(lm4857); | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int __devexit lm4857_i2c_remove(struct i2c_client *i2c) | ||
237 | { | ||
238 | struct lm4857 *lm4857 = i2c_get_clientdata(i2c); | ||
239 | |||
240 | snd_soc_unregister_codec(&i2c->dev); | ||
241 | kfree(lm4857); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static const struct i2c_device_id lm4857_i2c_id[] = { | ||
247 | { "lm4857", 0 }, | ||
248 | { } | ||
249 | }; | ||
250 | MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id); | ||
251 | |||
252 | static struct i2c_driver lm4857_i2c_driver = { | ||
253 | .driver = { | ||
254 | .name = "lm4857", | ||
255 | .owner = THIS_MODULE, | ||
256 | }, | ||
257 | .probe = lm4857_i2c_probe, | ||
258 | .remove = __devexit_p(lm4857_i2c_remove), | ||
259 | .id_table = lm4857_i2c_id, | ||
260 | }; | ||
261 | |||
262 | static int __init lm4857_init(void) | ||
263 | { | ||
264 | return i2c_add_driver(&lm4857_i2c_driver); | ||
265 | } | ||
266 | module_init(lm4857_init); | ||
267 | |||
268 | static void __exit lm4857_exit(void) | ||
269 | { | ||
270 | i2c_del_driver(&lm4857_i2c_driver); | ||
271 | } | ||
272 | module_exit(lm4857_exit); | ||
273 | |||
274 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
275 | MODULE_DESCRIPTION("LM4857 amplifier driver"); | ||
276 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 89498f9ad2e5..bd0517cb7980 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -608,7 +608,7 @@ static struct { | |||
608 | { 0xFF, 0x00, 1 }, /* FF */ | 608 | { 0xFF, 0x00, 1 }, /* FF */ |
609 | }; | 609 | }; |
610 | 610 | ||
611 | static int max98088_volatile_register(unsigned int reg) | 611 | static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
612 | { | 612 | { |
613 | return max98088_access[reg].vol; | 613 | return max98088_access[reg].vol; |
614 | } | 614 | } |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c new file mode 100644 index 000000000000..208d2ee61855 --- /dev/null +++ b/sound/soc/codecs/max9850.c | |||
@@ -0,0 +1,389 @@ | |||
1 | /* | ||
2 | * max9850.c -- codec driver for max9850 | ||
3 | * | ||
4 | * Copyright (C) 2011 taskit GmbH | ||
5 | * | ||
6 | * Author: Christian Glindkamp <christian.glindkamp@taskit.de> | ||
7 | * | ||
8 | * Initial development of this code was funded by | ||
9 | * MICRONIC Computer Systeme GmbH, http://www.mcsberlin.de/ | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/tlv.h> | ||
26 | |||
27 | #include "max9850.h" | ||
28 | |||
29 | struct max9850_priv { | ||
30 | unsigned int sysclk; | ||
31 | }; | ||
32 | |||
33 | /* max9850 register cache */ | ||
34 | static const u8 max9850_reg[MAX9850_CACHEREGNUM] = { | ||
35 | 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
36 | }; | ||
37 | |||
38 | /* these registers are not used at the moment but provided for the sake of | ||
39 | * completeness */ | ||
40 | static int max9850_volatile_register(struct snd_soc_codec *codec, | ||
41 | unsigned int reg) | ||
42 | { | ||
43 | switch (reg) { | ||
44 | case MAX9850_STATUSA: | ||
45 | case MAX9850_STATUSB: | ||
46 | return 1; | ||
47 | default: | ||
48 | return 0; | ||
49 | } | ||
50 | } | ||
51 | |||
52 | static const unsigned int max9850_tlv[] = { | ||
53 | TLV_DB_RANGE_HEAD(4), | ||
54 | 0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0), | ||
55 | 0x20, 0x33, TLV_DB_SCALE_ITEM(-4150, 200, 0), | ||
56 | 0x34, 0x37, TLV_DB_SCALE_ITEM(-150, 100, 0), | ||
57 | 0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0), | ||
58 | }; | ||
59 | |||
60 | static const struct snd_kcontrol_new max9850_controls[] = { | ||
61 | SOC_SINGLE_TLV("Headphone Volume", MAX9850_VOLUME, 0, 0x3f, 1, max9850_tlv), | ||
62 | SOC_SINGLE("Headphone Switch", MAX9850_VOLUME, 7, 1, 1), | ||
63 | SOC_SINGLE("Mono Switch", MAX9850_GENERAL_PURPOSE, 2, 1, 0), | ||
64 | }; | ||
65 | |||
66 | static const struct snd_kcontrol_new max9850_mixer_controls[] = { | ||
67 | SOC_DAPM_SINGLE("Line In Switch", MAX9850_ENABLE, 1, 1, 0), | ||
68 | }; | ||
69 | |||
70 | static const struct snd_soc_dapm_widget max9850_dapm_widgets[] = { | ||
71 | SND_SOC_DAPM_SUPPLY("Charge Pump 1", MAX9850_ENABLE, 4, 0, NULL, 0), | ||
72 | SND_SOC_DAPM_SUPPLY("Charge Pump 2", MAX9850_ENABLE, 5, 0, NULL, 0), | ||
73 | SND_SOC_DAPM_SUPPLY("MCLK", MAX9850_ENABLE, 6, 0, NULL, 0), | ||
74 | SND_SOC_DAPM_SUPPLY("SHDN", MAX9850_ENABLE, 7, 0, NULL, 0), | ||
75 | SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", MAX9850_ENABLE, 2, 0, | ||
76 | &max9850_mixer_controls[0], | ||
77 | ARRAY_SIZE(max9850_mixer_controls)), | ||
78 | SND_SOC_DAPM_PGA("Headphone Output", MAX9850_ENABLE, 3, 0, NULL, 0), | ||
79 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", MAX9850_ENABLE, 0, 0), | ||
80 | SND_SOC_DAPM_OUTPUT("OUTL"), | ||
81 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
82 | SND_SOC_DAPM_OUTPUT("OUTR"), | ||
83 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
84 | SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
85 | SND_SOC_DAPM_INPUT("INL"), | ||
86 | SND_SOC_DAPM_INPUT("INR"), | ||
87 | }; | ||
88 | |||
89 | static const struct snd_soc_dapm_route intercon[] = { | ||
90 | /* output mixer */ | ||
91 | {"Output Mixer", NULL, "DAC"}, | ||
92 | {"Output Mixer", "Line In Switch", "Line Input"}, | ||
93 | |||
94 | /* outputs */ | ||
95 | {"Headphone Output", NULL, "Output Mixer"}, | ||
96 | {"HPL", NULL, "Headphone Output"}, | ||
97 | {"HPR", NULL, "Headphone Output"}, | ||
98 | {"OUTL", NULL, "Output Mixer"}, | ||
99 | {"OUTR", NULL, "Output Mixer"}, | ||
100 | |||
101 | /* inputs */ | ||
102 | {"Line Input", NULL, "INL"}, | ||
103 | {"Line Input", NULL, "INR"}, | ||
104 | |||
105 | /* supplies */ | ||
106 | {"Output Mixer", NULL, "Charge Pump 1"}, | ||
107 | {"Output Mixer", NULL, "Charge Pump 2"}, | ||
108 | {"Output Mixer", NULL, "SHDN"}, | ||
109 | {"DAC", NULL, "MCLK"}, | ||
110 | }; | ||
111 | |||
112 | static int max9850_hw_params(struct snd_pcm_substream *substream, | ||
113 | struct snd_pcm_hw_params *params, | ||
114 | struct snd_soc_dai *dai) | ||
115 | { | ||
116 | struct snd_soc_codec *codec = dai->codec; | ||
117 | struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec); | ||
118 | u64 lrclk_div; | ||
119 | u8 sf, da; | ||
120 | |||
121 | if (!max9850->sysclk) | ||
122 | return -EINVAL; | ||
123 | |||
124 | /* lrclk_div = 2^22 * rate / iclk with iclk = mclk / sf */ | ||
125 | sf = (snd_soc_read(codec, MAX9850_CLOCK) >> 2) + 1; | ||
126 | lrclk_div = (1 << 22); | ||
127 | lrclk_div *= params_rate(params); | ||
128 | lrclk_div *= sf; | ||
129 | do_div(lrclk_div, max9850->sysclk); | ||
130 | |||
131 | snd_soc_write(codec, MAX9850_LRCLK_MSB, (lrclk_div >> 8) & 0x7f); | ||
132 | snd_soc_write(codec, MAX9850_LRCLK_LSB, lrclk_div & 0xff); | ||
133 | |||
134 | switch (params_format(params)) { | ||
135 | case SNDRV_PCM_FORMAT_S16_LE: | ||
136 | da = 0; | ||
137 | break; | ||
138 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
139 | da = 0x2; | ||
140 | break; | ||
141 | case SNDRV_PCM_FORMAT_S24_LE: | ||
142 | da = 0x3; | ||
143 | break; | ||
144 | default: | ||
145 | return -EINVAL; | ||
146 | } | ||
147 | snd_soc_update_bits(codec, MAX9850_DIGITAL_AUDIO, 0x3, da); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int max9850_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
153 | int clk_id, unsigned int freq, int dir) | ||
154 | { | ||
155 | struct snd_soc_codec *codec = codec_dai->codec; | ||
156 | struct max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec); | ||
157 | |||
158 | /* calculate mclk -> iclk divider */ | ||
159 | if (freq <= 13000000) | ||
160 | snd_soc_write(codec, MAX9850_CLOCK, 0x0); | ||
161 | else if (freq <= 26000000) | ||
162 | snd_soc_write(codec, MAX9850_CLOCK, 0x4); | ||
163 | else if (freq <= 40000000) | ||
164 | snd_soc_write(codec, MAX9850_CLOCK, 0x8); | ||
165 | else | ||
166 | return -EINVAL; | ||
167 | |||
168 | max9850->sysclk = freq; | ||
169 | return 0; | ||
170 | } | ||
171 | |||
172 | static int max9850_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
173 | { | ||
174 | struct snd_soc_codec *codec = codec_dai->codec; | ||
175 | u8 da = 0; | ||
176 | |||
177 | /* set master/slave audio interface */ | ||
178 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
179 | case SND_SOC_DAIFMT_CBM_CFM: | ||
180 | da |= MAX9850_MASTER; | ||
181 | break; | ||
182 | case SND_SOC_DAIFMT_CBS_CFS: | ||
183 | break; | ||
184 | default: | ||
185 | return -EINVAL; | ||
186 | } | ||
187 | |||
188 | /* interface format */ | ||
189 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
190 | case SND_SOC_DAIFMT_I2S: | ||
191 | da |= MAX9850_DLY; | ||
192 | break; | ||
193 | case SND_SOC_DAIFMT_RIGHT_J: | ||
194 | da |= MAX9850_RTJ; | ||
195 | break; | ||
196 | case SND_SOC_DAIFMT_LEFT_J: | ||
197 | break; | ||
198 | default: | ||
199 | return -EINVAL; | ||
200 | } | ||
201 | |||
202 | /* clock inversion */ | ||
203 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
204 | case SND_SOC_DAIFMT_NB_NF: | ||
205 | break; | ||
206 | case SND_SOC_DAIFMT_IB_IF: | ||
207 | da |= MAX9850_BCINV | MAX9850_INV; | ||
208 | break; | ||
209 | case SND_SOC_DAIFMT_IB_NF: | ||
210 | da |= MAX9850_BCINV; | ||
211 | break; | ||
212 | case SND_SOC_DAIFMT_NB_IF: | ||
213 | da |= MAX9850_INV; | ||
214 | break; | ||
215 | default: | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | /* set da */ | ||
220 | snd_soc_write(codec, MAX9850_DIGITAL_AUDIO, da); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static int max9850_set_bias_level(struct snd_soc_codec *codec, | ||
226 | enum snd_soc_bias_level level) | ||
227 | { | ||
228 | int ret; | ||
229 | |||
230 | switch (level) { | ||
231 | case SND_SOC_BIAS_ON: | ||
232 | break; | ||
233 | case SND_SOC_BIAS_PREPARE: | ||
234 | break; | ||
235 | case SND_SOC_BIAS_STANDBY: | ||
236 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
237 | ret = snd_soc_cache_sync(codec); | ||
238 | if (ret) { | ||
239 | dev_err(codec->dev, | ||
240 | "Failed to sync cache: %d\n", ret); | ||
241 | return ret; | ||
242 | } | ||
243 | } | ||
244 | break; | ||
245 | case SND_SOC_BIAS_OFF: | ||
246 | break; | ||
247 | } | ||
248 | codec->dapm.bias_level = level; | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | #define MAX9850_RATES SNDRV_PCM_RATE_8000_48000 | ||
253 | |||
254 | #define MAX9850_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
255 | SNDRV_PCM_FMTBIT_S24_LE) | ||
256 | |||
257 | static struct snd_soc_dai_ops max9850_dai_ops = { | ||
258 | .hw_params = max9850_hw_params, | ||
259 | .set_sysclk = max9850_set_dai_sysclk, | ||
260 | .set_fmt = max9850_set_dai_fmt, | ||
261 | }; | ||
262 | |||
263 | static struct snd_soc_dai_driver max9850_dai = { | ||
264 | .name = "max9850-hifi", | ||
265 | .playback = { | ||
266 | .stream_name = "Playback", | ||
267 | .channels_min = 1, | ||
268 | .channels_max = 2, | ||
269 | .rates = MAX9850_RATES, | ||
270 | .formats = MAX9850_FORMATS | ||
271 | }, | ||
272 | .ops = &max9850_dai_ops, | ||
273 | }; | ||
274 | |||
275 | #ifdef CONFIG_PM | ||
276 | static int max9850_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
277 | { | ||
278 | max9850_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int max9850_resume(struct snd_soc_codec *codec) | ||
284 | { | ||
285 | max9850_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | #else | ||
290 | #define max9850_suspend NULL | ||
291 | #define max9850_resume NULL | ||
292 | #endif | ||
293 | |||
294 | static int max9850_probe(struct snd_soc_codec *codec) | ||
295 | { | ||
296 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
297 | int ret; | ||
298 | |||
299 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
300 | if (ret < 0) { | ||
301 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | /* enable zero-detect */ | ||
306 | snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1); | ||
307 | /* enable slew-rate control */ | ||
308 | snd_soc_update_bits(codec, MAX9850_VOLUME, 0x40, 0x40); | ||
309 | /* set slew-rate 125ms */ | ||
310 | snd_soc_update_bits(codec, MAX9850_CHARGE_PUMP, 0xff, 0xc0); | ||
311 | |||
312 | snd_soc_dapm_new_controls(dapm, max9850_dapm_widgets, | ||
313 | ARRAY_SIZE(max9850_dapm_widgets)); | ||
314 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
315 | |||
316 | snd_soc_add_controls(codec, max9850_controls, | ||
317 | ARRAY_SIZE(max9850_controls)); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static struct snd_soc_codec_driver soc_codec_dev_max9850 = { | ||
323 | .probe = max9850_probe, | ||
324 | .suspend = max9850_suspend, | ||
325 | .resume = max9850_resume, | ||
326 | .set_bias_level = max9850_set_bias_level, | ||
327 | .reg_cache_size = ARRAY_SIZE(max9850_reg), | ||
328 | .reg_word_size = sizeof(u8), | ||
329 | .reg_cache_default = max9850_reg, | ||
330 | .volatile_register = max9850_volatile_register, | ||
331 | }; | ||
332 | |||
333 | static int __devinit max9850_i2c_probe(struct i2c_client *i2c, | ||
334 | const struct i2c_device_id *id) | ||
335 | { | ||
336 | struct max9850_priv *max9850; | ||
337 | int ret; | ||
338 | |||
339 | max9850 = kzalloc(sizeof(struct max9850_priv), GFP_KERNEL); | ||
340 | if (max9850 == NULL) | ||
341 | return -ENOMEM; | ||
342 | |||
343 | i2c_set_clientdata(i2c, max9850); | ||
344 | |||
345 | ret = snd_soc_register_codec(&i2c->dev, | ||
346 | &soc_codec_dev_max9850, &max9850_dai, 1); | ||
347 | if (ret < 0) | ||
348 | kfree(max9850); | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static __devexit int max9850_i2c_remove(struct i2c_client *client) | ||
353 | { | ||
354 | snd_soc_unregister_codec(&client->dev); | ||
355 | kfree(i2c_get_clientdata(client)); | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | static const struct i2c_device_id max9850_i2c_id[] = { | ||
360 | { "max9850", 0 }, | ||
361 | { } | ||
362 | }; | ||
363 | MODULE_DEVICE_TABLE(i2c, max9850_i2c_id); | ||
364 | |||
365 | static struct i2c_driver max9850_i2c_driver = { | ||
366 | .driver = { | ||
367 | .name = "max9850", | ||
368 | .owner = THIS_MODULE, | ||
369 | }, | ||
370 | .probe = max9850_i2c_probe, | ||
371 | .remove = __devexit_p(max9850_i2c_remove), | ||
372 | .id_table = max9850_i2c_id, | ||
373 | }; | ||
374 | |||
375 | static int __init max9850_init(void) | ||
376 | { | ||
377 | return i2c_add_driver(&max9850_i2c_driver); | ||
378 | } | ||
379 | module_init(max9850_init); | ||
380 | |||
381 | static void __exit max9850_exit(void) | ||
382 | { | ||
383 | i2c_del_driver(&max9850_i2c_driver); | ||
384 | } | ||
385 | module_exit(max9850_exit); | ||
386 | |||
387 | MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>"); | ||
388 | MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); | ||
389 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/max9850.h b/sound/soc/codecs/max9850.h new file mode 100644 index 000000000000..72b1ddb04b0d --- /dev/null +++ b/sound/soc/codecs/max9850.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * max9850.h -- codec driver for max9850 | ||
3 | * | ||
4 | * Copyright (C) 2011 taskit GmbH | ||
5 | * Author: Christian Glindkamp <christian.glindkamp@taskit.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef _MAX9850_H | ||
15 | #define _MAX9850_H | ||
16 | |||
17 | #define MAX9850_STATUSA 0x00 | ||
18 | #define MAX9850_STATUSB 0x01 | ||
19 | #define MAX9850_VOLUME 0x02 | ||
20 | #define MAX9850_GENERAL_PURPOSE 0x03 | ||
21 | #define MAX9850_INTERRUPT 0x04 | ||
22 | #define MAX9850_ENABLE 0x05 | ||
23 | #define MAX9850_CLOCK 0x06 | ||
24 | #define MAX9850_CHARGE_PUMP 0x07 | ||
25 | #define MAX9850_LRCLK_MSB 0x08 | ||
26 | #define MAX9850_LRCLK_LSB 0x09 | ||
27 | #define MAX9850_DIGITAL_AUDIO 0x0a | ||
28 | |||
29 | #define MAX9850_CACHEREGNUM 11 | ||
30 | |||
31 | /* MAX9850_DIGITAL_AUDIO */ | ||
32 | #define MAX9850_MASTER (1<<7) | ||
33 | #define MAX9850_INV (1<<6) | ||
34 | #define MAX9850_BCINV (1<<5) | ||
35 | #define MAX9850_DLY (1<<3) | ||
36 | #define MAX9850_RTJ (1<<2) | ||
37 | |||
38 | #endif | ||
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c new file mode 100644 index 000000000000..1f7217f703ee --- /dev/null +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -0,0 +1,1513 @@ | |||
1 | /* | ||
2 | * sgtl5000.c -- SGTL5000 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved. | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/moduleparam.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/regulator/driver.h> | ||
21 | #include <linux/regulator/machine.h> | ||
22 | #include <linux/regulator/consumer.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/tlv.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dapm.h> | ||
29 | #include <sound/initval.h> | ||
30 | |||
31 | #include "sgtl5000.h" | ||
32 | |||
33 | #define SGTL5000_DAP_REG_OFFSET 0x0100 | ||
34 | #define SGTL5000_MAX_REG_OFFSET 0x013A | ||
35 | |||
36 | /* default value of sgtl5000 registers except DAP */ | ||
37 | static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET >> 1] = { | ||
38 | 0xa011, /* 0x0000, CHIP_ID. 11 stand for revison 17 */ | ||
39 | 0x0000, /* 0x0002, CHIP_DIG_POWER. */ | ||
40 | 0x0008, /* 0x0004, CHIP_CKL_CTRL */ | ||
41 | 0x0010, /* 0x0006, CHIP_I2S_CTRL */ | ||
42 | 0x0000, /* 0x0008, reserved */ | ||
43 | 0x0008, /* 0x000A, CHIP_SSS_CTRL */ | ||
44 | 0x0000, /* 0x000C, reserved */ | ||
45 | 0x020c, /* 0x000E, CHIP_ADCDAC_CTRL */ | ||
46 | 0x3c3c, /* 0x0010, CHIP_DAC_VOL */ | ||
47 | 0x0000, /* 0x0012, reserved */ | ||
48 | 0x015f, /* 0x0014, CHIP_PAD_STRENGTH */ | ||
49 | 0x0000, /* 0x0016, reserved */ | ||
50 | 0x0000, /* 0x0018, reserved */ | ||
51 | 0x0000, /* 0x001A, reserved */ | ||
52 | 0x0000, /* 0x001E, reserved */ | ||
53 | 0x0000, /* 0x0020, CHIP_ANA_ADC_CTRL */ | ||
54 | 0x1818, /* 0x0022, CHIP_ANA_HP_CTRL */ | ||
55 | 0x0111, /* 0x0024, CHIP_ANN_CTRL */ | ||
56 | 0x0000, /* 0x0026, CHIP_LINREG_CTRL */ | ||
57 | 0x0000, /* 0x0028, CHIP_REF_CTRL */ | ||
58 | 0x0000, /* 0x002A, CHIP_MIC_CTRL */ | ||
59 | 0x0000, /* 0x002C, CHIP_LINE_OUT_CTRL */ | ||
60 | 0x0404, /* 0x002E, CHIP_LINE_OUT_VOL */ | ||
61 | 0x7060, /* 0x0030, CHIP_ANA_POWER */ | ||
62 | 0x5000, /* 0x0032, CHIP_PLL_CTRL */ | ||
63 | 0x0000, /* 0x0034, CHIP_CLK_TOP_CTRL */ | ||
64 | 0x0000, /* 0x0036, CHIP_ANA_STATUS */ | ||
65 | 0x0000, /* 0x0038, reserved */ | ||
66 | 0x0000, /* 0x003A, CHIP_ANA_TEST2 */ | ||
67 | 0x0000, /* 0x003C, CHIP_SHORT_CTRL */ | ||
68 | 0x0000, /* reserved */ | ||
69 | }; | ||
70 | |||
71 | /* default value of dap registers */ | ||
72 | static const u16 sgtl5000_dap_regs[] = { | ||
73 | 0x0000, /* 0x0100, DAP_CONTROL */ | ||
74 | 0x0000, /* 0x0102, DAP_PEQ */ | ||
75 | 0x0040, /* 0x0104, DAP_BASS_ENHANCE */ | ||
76 | 0x051f, /* 0x0106, DAP_BASS_ENHANCE_CTRL */ | ||
77 | 0x0000, /* 0x0108, DAP_AUDIO_EQ */ | ||
78 | 0x0040, /* 0x010A, DAP_SGTL_SURROUND */ | ||
79 | 0x0000, /* 0x010C, DAP_FILTER_COEF_ACCESS */ | ||
80 | 0x0000, /* 0x010E, DAP_COEF_WR_B0_MSB */ | ||
81 | 0x0000, /* 0x0110, DAP_COEF_WR_B0_LSB */ | ||
82 | 0x0000, /* 0x0112, reserved */ | ||
83 | 0x0000, /* 0x0114, reserved */ | ||
84 | 0x002f, /* 0x0116, DAP_AUDIO_EQ_BASS_BAND0 */ | ||
85 | 0x002f, /* 0x0118, DAP_AUDIO_EQ_BAND0 */ | ||
86 | 0x002f, /* 0x011A, DAP_AUDIO_EQ_BAND2 */ | ||
87 | 0x002f, /* 0x011C, DAP_AUDIO_EQ_BAND3 */ | ||
88 | 0x002f, /* 0x011E, DAP_AUDIO_EQ_TREBLE_BAND4 */ | ||
89 | 0x8000, /* 0x0120, DAP_MAIN_CHAN */ | ||
90 | 0x0000, /* 0x0122, DAP_MIX_CHAN */ | ||
91 | 0x0510, /* 0x0124, DAP_AVC_CTRL */ | ||
92 | 0x1473, /* 0x0126, DAP_AVC_THRESHOLD */ | ||
93 | 0x0028, /* 0x0128, DAP_AVC_ATTACK */ | ||
94 | 0x0050, /* 0x012A, DAP_AVC_DECAY */ | ||
95 | 0x0000, /* 0x012C, DAP_COEF_WR_B1_MSB */ | ||
96 | 0x0000, /* 0x012E, DAP_COEF_WR_B1_LSB */ | ||
97 | 0x0000, /* 0x0130, DAP_COEF_WR_B2_MSB */ | ||
98 | 0x0000, /* 0x0132, DAP_COEF_WR_B2_LSB */ | ||
99 | 0x0000, /* 0x0134, DAP_COEF_WR_A1_MSB */ | ||
100 | 0x0000, /* 0x0136, DAP_COEF_WR_A1_LSB */ | ||
101 | 0x0000, /* 0x0138, DAP_COEF_WR_A2_MSB */ | ||
102 | 0x0000, /* 0x013A, DAP_COEF_WR_A2_LSB */ | ||
103 | }; | ||
104 | |||
105 | /* regulator supplies for sgtl5000, VDDD is an optional external supply */ | ||
106 | enum sgtl5000_regulator_supplies { | ||
107 | VDDA, | ||
108 | VDDIO, | ||
109 | VDDD, | ||
110 | SGTL5000_SUPPLY_NUM | ||
111 | }; | ||
112 | |||
113 | /* vddd is optional supply */ | ||
114 | static const char *supply_names[SGTL5000_SUPPLY_NUM] = { | ||
115 | "VDDA", | ||
116 | "VDDIO", | ||
117 | "VDDD" | ||
118 | }; | ||
119 | |||
120 | #define LDO_CONSUMER_NAME "VDDD_LDO" | ||
121 | #define LDO_VOLTAGE 1200000 | ||
122 | |||
123 | static struct regulator_consumer_supply ldo_consumer[] = { | ||
124 | REGULATOR_SUPPLY(LDO_CONSUMER_NAME, NULL), | ||
125 | }; | ||
126 | |||
127 | static struct regulator_init_data ldo_init_data = { | ||
128 | .constraints = { | ||
129 | .min_uV = 850000, | ||
130 | .max_uV = 1600000, | ||
131 | .valid_modes_mask = REGULATOR_MODE_NORMAL, | ||
132 | .valid_ops_mask = REGULATOR_CHANGE_STATUS, | ||
133 | }, | ||
134 | .num_consumer_supplies = 1, | ||
135 | .consumer_supplies = &ldo_consumer[0], | ||
136 | }; | ||
137 | |||
138 | /* | ||
139 | * sgtl5000 internal ldo regulator, | ||
140 | * enabled when VDDD not provided | ||
141 | */ | ||
142 | struct ldo_regulator { | ||
143 | struct regulator_desc desc; | ||
144 | struct regulator_dev *dev; | ||
145 | int voltage; | ||
146 | void *codec_data; | ||
147 | bool enabled; | ||
148 | }; | ||
149 | |||
150 | /* sgtl5000 private structure in codec */ | ||
151 | struct sgtl5000_priv { | ||
152 | int sysclk; /* sysclk rate */ | ||
153 | int master; /* i2s master or not */ | ||
154 | int fmt; /* i2s data format */ | ||
155 | struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM]; | ||
156 | struct ldo_regulator *ldo; | ||
157 | }; | ||
158 | |||
159 | /* | ||
160 | * mic_bias power on/off share the same register bits with | ||
161 | * output impedance of mic bias, when power on mic bias, we | ||
162 | * need reclaim it to impedance value. | ||
163 | * 0x0 = Powered off | ||
164 | * 0x1 = 2Kohm | ||
165 | * 0x2 = 4Kohm | ||
166 | * 0x3 = 8Kohm | ||
167 | */ | ||
168 | static int mic_bias_event(struct snd_soc_dapm_widget *w, | ||
169 | struct snd_kcontrol *kcontrol, int event) | ||
170 | { | ||
171 | switch (event) { | ||
172 | case SND_SOC_DAPM_POST_PMU: | ||
173 | /* change mic bias resistor to 4Kohm */ | ||
174 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, | ||
175 | SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k); | ||
176 | break; | ||
177 | |||
178 | case SND_SOC_DAPM_PRE_PMD: | ||
179 | /* | ||
180 | * SGTL5000_BIAS_R_8k as mask to clean the two bits | ||
181 | * of mic bias and output impedance | ||
182 | */ | ||
183 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL, | ||
184 | SGTL5000_BIAS_R_8k, 0); | ||
185 | break; | ||
186 | } | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * using codec assist to small pop, hp_powerup or lineout_powerup | ||
192 | * should stay setting until vag_powerup is fully ramped down, | ||
193 | * vag fully ramped down require 400ms. | ||
194 | */ | ||
195 | static int small_pop_event(struct snd_soc_dapm_widget *w, | ||
196 | struct snd_kcontrol *kcontrol, int event) | ||
197 | { | ||
198 | switch (event) { | ||
199 | case SND_SOC_DAPM_PRE_PMU: | ||
200 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | ||
201 | SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP); | ||
202 | break; | ||
203 | |||
204 | case SND_SOC_DAPM_PRE_PMD: | ||
205 | snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER, | ||
206 | SGTL5000_VAG_POWERUP, 0); | ||
207 | msleep(400); | ||
208 | break; | ||
209 | default: | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | /* input sources for ADC */ | ||
217 | static const char *adc_mux_text[] = { | ||
218 | "MIC_IN", "LINE_IN" | ||
219 | }; | ||
220 | |||
221 | static const struct soc_enum adc_enum = | ||
222 | SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text); | ||
223 | |||
224 | static const struct snd_kcontrol_new adc_mux = | ||
225 | SOC_DAPM_ENUM("Capture Mux", adc_enum); | ||
226 | |||
227 | /* input sources for DAC */ | ||
228 | static const char *dac_mux_text[] = { | ||
229 | "DAC", "LINE_IN" | ||
230 | }; | ||
231 | |||
232 | static const struct soc_enum dac_enum = | ||
233 | SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text); | ||
234 | |||
235 | static const struct snd_kcontrol_new dac_mux = | ||
236 | SOC_DAPM_ENUM("Headphone Mux", dac_enum); | ||
237 | |||
238 | static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = { | ||
239 | SND_SOC_DAPM_INPUT("LINE_IN"), | ||
240 | SND_SOC_DAPM_INPUT("MIC_IN"), | ||
241 | |||
242 | SND_SOC_DAPM_OUTPUT("HP_OUT"), | ||
243 | SND_SOC_DAPM_OUTPUT("LINE_OUT"), | ||
244 | |||
245 | SND_SOC_DAPM_MICBIAS_E("Mic Bias", SGTL5000_CHIP_MIC_CTRL, 8, 0, | ||
246 | mic_bias_event, | ||
247 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
248 | |||
249 | SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0, | ||
250 | small_pop_event, | ||
251 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
252 | SND_SOC_DAPM_PGA_E("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0, | ||
253 | small_pop_event, | ||
254 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
255 | |||
256 | SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux), | ||
257 | SND_SOC_DAPM_MUX("Headphone Mux", SND_SOC_NOPM, 0, 0, &dac_mux), | ||
258 | |||
259 | /* aif for i2s input */ | ||
260 | SND_SOC_DAPM_AIF_IN("AIFIN", "Playback", | ||
261 | 0, SGTL5000_CHIP_DIG_POWER, | ||
262 | 0, 0), | ||
263 | |||
264 | /* aif for i2s output */ | ||
265 | SND_SOC_DAPM_AIF_OUT("AIFOUT", "Capture", | ||
266 | 0, SGTL5000_CHIP_DIG_POWER, | ||
267 | 1, 0), | ||
268 | |||
269 | SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0), | ||
270 | |||
271 | SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0), | ||
272 | }; | ||
273 | |||
274 | /* routes for sgtl5000 */ | ||
275 | static const struct snd_soc_dapm_route audio_map[] = { | ||
276 | {"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */ | ||
277 | {"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */ | ||
278 | |||
279 | {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */ | ||
280 | {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */ | ||
281 | |||
282 | {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */ | ||
283 | {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */ | ||
284 | {"LO", NULL, "DAC"}, /* dac --> line_out */ | ||
285 | |||
286 | {"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */ | ||
287 | {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */ | ||
288 | |||
289 | {"LINE_OUT", NULL, "LO"}, | ||
290 | {"HP_OUT", NULL, "HP"}, | ||
291 | }; | ||
292 | |||
293 | /* custom function to fetch info of PCM playback volume */ | ||
294 | static int dac_info_volsw(struct snd_kcontrol *kcontrol, | ||
295 | struct snd_ctl_elem_info *uinfo) | ||
296 | { | ||
297 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
298 | uinfo->count = 2; | ||
299 | uinfo->value.integer.min = 0; | ||
300 | uinfo->value.integer.max = 0xfc - 0x3c; | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * custom function to get of PCM playback volume | ||
306 | * | ||
307 | * dac volume register | ||
308 | * 15-------------8-7--------------0 | ||
309 | * | R channel vol | L channel vol | | ||
310 | * ------------------------------- | ||
311 | * | ||
312 | * PCM volume with 0.5017 dB steps from 0 to -90 dB | ||
313 | * | ||
314 | * register values map to dB | ||
315 | * 0x3B and less = Reserved | ||
316 | * 0x3C = 0 dB | ||
317 | * 0x3D = -0.5 dB | ||
318 | * 0xF0 = -90 dB | ||
319 | * 0xFC and greater = Muted | ||
320 | * | ||
321 | * register value map to userspace value | ||
322 | * | ||
323 | * register value 0x3c(0dB) 0xf0(-90dB)0xfc | ||
324 | * ------------------------------ | ||
325 | * userspace value 0xc0 0 | ||
326 | */ | ||
327 | static int dac_get_volsw(struct snd_kcontrol *kcontrol, | ||
328 | struct snd_ctl_elem_value *ucontrol) | ||
329 | { | ||
330 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
331 | int reg; | ||
332 | int l; | ||
333 | int r; | ||
334 | |||
335 | reg = snd_soc_read(codec, SGTL5000_CHIP_DAC_VOL); | ||
336 | |||
337 | /* get left channel volume */ | ||
338 | l = (reg & SGTL5000_DAC_VOL_LEFT_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT; | ||
339 | |||
340 | /* get right channel volume */ | ||
341 | r = (reg & SGTL5000_DAC_VOL_RIGHT_MASK) >> SGTL5000_DAC_VOL_RIGHT_SHIFT; | ||
342 | |||
343 | /* make sure value fall in (0x3c,0xfc) */ | ||
344 | l = clamp(l, 0x3c, 0xfc); | ||
345 | r = clamp(r, 0x3c, 0xfc); | ||
346 | |||
347 | /* invert it and map to userspace value */ | ||
348 | l = 0xfc - l; | ||
349 | r = 0xfc - r; | ||
350 | |||
351 | ucontrol->value.integer.value[0] = l; | ||
352 | ucontrol->value.integer.value[1] = r; | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | * custom function to put of PCM playback volume | ||
359 | * | ||
360 | * dac volume register | ||
361 | * 15-------------8-7--------------0 | ||
362 | * | R channel vol | L channel vol | | ||
363 | * ------------------------------- | ||
364 | * | ||
365 | * PCM volume with 0.5017 dB steps from 0 to -90 dB | ||
366 | * | ||
367 | * register values map to dB | ||
368 | * 0x3B and less = Reserved | ||
369 | * 0x3C = 0 dB | ||
370 | * 0x3D = -0.5 dB | ||
371 | * 0xF0 = -90 dB | ||
372 | * 0xFC and greater = Muted | ||
373 | * | ||
374 | * userspace value map to register value | ||
375 | * | ||
376 | * userspace value 0xc0 0 | ||
377 | * ------------------------------ | ||
378 | * register value 0x3c(0dB) 0xf0(-90dB)0xfc | ||
379 | */ | ||
380 | static int dac_put_volsw(struct snd_kcontrol *kcontrol, | ||
381 | struct snd_ctl_elem_value *ucontrol) | ||
382 | { | ||
383 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
384 | int reg; | ||
385 | int l; | ||
386 | int r; | ||
387 | |||
388 | l = ucontrol->value.integer.value[0]; | ||
389 | r = ucontrol->value.integer.value[1]; | ||
390 | |||
391 | /* make sure userspace volume fall in (0, 0xfc-0x3c) */ | ||
392 | l = clamp(l, 0, 0xfc - 0x3c); | ||
393 | r = clamp(r, 0, 0xfc - 0x3c); | ||
394 | |||
395 | /* invert it, get the value can be set to register */ | ||
396 | l = 0xfc - l; | ||
397 | r = 0xfc - r; | ||
398 | |||
399 | /* shift to get the register value */ | ||
400 | reg = l << SGTL5000_DAC_VOL_LEFT_SHIFT | | ||
401 | r << SGTL5000_DAC_VOL_RIGHT_SHIFT; | ||
402 | |||
403 | snd_soc_write(codec, SGTL5000_CHIP_DAC_VOL, reg); | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0); | ||
409 | |||
410 | /* tlv for mic gain, 0db 20db 30db 40db */ | ||
411 | static const unsigned int mic_gain_tlv[] = { | ||
412 | TLV_DB_RANGE_HEAD(4), | ||
413 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
414 | 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0), | ||
415 | }; | ||
416 | |||
417 | /* tlv for hp volume, -51.5db to 12.0db, step .5db */ | ||
418 | static const DECLARE_TLV_DB_SCALE(headphone_volume, -5150, 50, 0); | ||
419 | |||
420 | static const struct snd_kcontrol_new sgtl5000_snd_controls[] = { | ||
421 | /* SOC_DOUBLE_S8_TLV with invert */ | ||
422 | { | ||
423 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
424 | .name = "PCM Playback Volume", | ||
425 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
426 | SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
427 | .info = dac_info_volsw, | ||
428 | .get = dac_get_volsw, | ||
429 | .put = dac_put_volsw, | ||
430 | }, | ||
431 | |||
432 | SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0), | ||
433 | SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)", | ||
434 | SGTL5000_CHIP_ANA_ADC_CTRL, | ||
435 | 8, 2, 0, capture_6db_attenuate), | ||
436 | SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0), | ||
437 | |||
438 | SOC_DOUBLE_TLV("Headphone Playback Volume", | ||
439 | SGTL5000_CHIP_ANA_HP_CTRL, | ||
440 | 0, 8, | ||
441 | 0x7f, 1, | ||
442 | headphone_volume), | ||
443 | SOC_SINGLE("Headphone Playback ZC Switch", SGTL5000_CHIP_ANA_CTRL, | ||
444 | 5, 1, 0), | ||
445 | |||
446 | SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL, | ||
447 | 0, 4, 0, mic_gain_tlv), | ||
448 | }; | ||
449 | |||
450 | /* mute the codec used by alsa core */ | ||
451 | static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute) | ||
452 | { | ||
453 | struct snd_soc_codec *codec = codec_dai->codec; | ||
454 | u16 adcdac_ctrl = SGTL5000_DAC_MUTE_LEFT | SGTL5000_DAC_MUTE_RIGHT; | ||
455 | |||
456 | snd_soc_update_bits(codec, SGTL5000_CHIP_ADCDAC_CTRL, | ||
457 | adcdac_ctrl, mute ? adcdac_ctrl : 0); | ||
458 | |||
459 | return 0; | ||
460 | } | ||
461 | |||
462 | /* set codec format */ | ||
463 | static int sgtl5000_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
464 | { | ||
465 | struct snd_soc_codec *codec = codec_dai->codec; | ||
466 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
467 | u16 i2sctl = 0; | ||
468 | |||
469 | sgtl5000->master = 0; | ||
470 | /* | ||
471 | * i2s clock and frame master setting. | ||
472 | * ONLY support: | ||
473 | * - clock and frame slave, | ||
474 | * - clock and frame master | ||
475 | */ | ||
476 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
477 | case SND_SOC_DAIFMT_CBS_CFS: | ||
478 | break; | ||
479 | case SND_SOC_DAIFMT_CBM_CFM: | ||
480 | i2sctl |= SGTL5000_I2S_MASTER; | ||
481 | sgtl5000->master = 1; | ||
482 | break; | ||
483 | default: | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | /* setting i2s data format */ | ||
488 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
489 | case SND_SOC_DAIFMT_DSP_A: | ||
490 | i2sctl |= SGTL5000_I2S_MODE_PCM; | ||
491 | break; | ||
492 | case SND_SOC_DAIFMT_DSP_B: | ||
493 | i2sctl |= SGTL5000_I2S_MODE_PCM; | ||
494 | i2sctl |= SGTL5000_I2S_LRALIGN; | ||
495 | break; | ||
496 | case SND_SOC_DAIFMT_I2S: | ||
497 | i2sctl |= SGTL5000_I2S_MODE_I2S_LJ; | ||
498 | break; | ||
499 | case SND_SOC_DAIFMT_RIGHT_J: | ||
500 | i2sctl |= SGTL5000_I2S_MODE_RJ; | ||
501 | i2sctl |= SGTL5000_I2S_LRPOL; | ||
502 | break; | ||
503 | case SND_SOC_DAIFMT_LEFT_J: | ||
504 | i2sctl |= SGTL5000_I2S_MODE_I2S_LJ; | ||
505 | i2sctl |= SGTL5000_I2S_LRALIGN; | ||
506 | break; | ||
507 | default: | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | |||
511 | sgtl5000->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | ||
512 | |||
513 | /* Clock inversion */ | ||
514 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
515 | case SND_SOC_DAIFMT_NB_NF: | ||
516 | break; | ||
517 | case SND_SOC_DAIFMT_IB_NF: | ||
518 | i2sctl |= SGTL5000_I2S_SCLK_INV; | ||
519 | break; | ||
520 | default: | ||
521 | return -EINVAL; | ||
522 | } | ||
523 | |||
524 | snd_soc_write(codec, SGTL5000_CHIP_I2S_CTRL, i2sctl); | ||
525 | |||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /* set codec sysclk */ | ||
530 | static int sgtl5000_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
531 | int clk_id, unsigned int freq, int dir) | ||
532 | { | ||
533 | struct snd_soc_codec *codec = codec_dai->codec; | ||
534 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
535 | |||
536 | switch (clk_id) { | ||
537 | case SGTL5000_SYSCLK: | ||
538 | sgtl5000->sysclk = freq; | ||
539 | break; | ||
540 | default: | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | /* | ||
548 | * set clock according to i2s frame clock, | ||
549 | * sgtl5000 provide 2 clock sources. | ||
550 | * 1. sys_mclk. sample freq can only configure to | ||
551 | * 1/256, 1/384, 1/512 of sys_mclk. | ||
552 | * 2. pll. can derive any audio clocks. | ||
553 | * | ||
554 | * clock setting rules: | ||
555 | * 1. in slave mode, only sys_mclk can use. | ||
556 | * 2. as constraint by sys_mclk, sample freq should | ||
557 | * set to 32k, 44.1k and above. | ||
558 | * 3. using sys_mclk prefer to pll to save power. | ||
559 | */ | ||
560 | static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate) | ||
561 | { | ||
562 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
563 | int clk_ctl = 0; | ||
564 | int sys_fs; /* sample freq */ | ||
565 | |||
566 | /* | ||
567 | * sample freq should be divided by frame clock, | ||
568 | * if frame clock lower than 44.1khz, sample feq should set to | ||
569 | * 32khz or 44.1khz. | ||
570 | */ | ||
571 | switch (frame_rate) { | ||
572 | case 8000: | ||
573 | case 16000: | ||
574 | sys_fs = 32000; | ||
575 | break; | ||
576 | case 11025: | ||
577 | case 22050: | ||
578 | sys_fs = 44100; | ||
579 | break; | ||
580 | default: | ||
581 | sys_fs = frame_rate; | ||
582 | break; | ||
583 | } | ||
584 | |||
585 | /* set divided factor of frame clock */ | ||
586 | switch (sys_fs / frame_rate) { | ||
587 | case 4: | ||
588 | clk_ctl |= SGTL5000_RATE_MODE_DIV_4 << SGTL5000_RATE_MODE_SHIFT; | ||
589 | break; | ||
590 | case 2: | ||
591 | clk_ctl |= SGTL5000_RATE_MODE_DIV_2 << SGTL5000_RATE_MODE_SHIFT; | ||
592 | break; | ||
593 | case 1: | ||
594 | clk_ctl |= SGTL5000_RATE_MODE_DIV_1 << SGTL5000_RATE_MODE_SHIFT; | ||
595 | break; | ||
596 | default: | ||
597 | return -EINVAL; | ||
598 | } | ||
599 | |||
600 | /* set the sys_fs according to frame rate */ | ||
601 | switch (sys_fs) { | ||
602 | case 32000: | ||
603 | clk_ctl |= SGTL5000_SYS_FS_32k << SGTL5000_SYS_FS_SHIFT; | ||
604 | break; | ||
605 | case 44100: | ||
606 | clk_ctl |= SGTL5000_SYS_FS_44_1k << SGTL5000_SYS_FS_SHIFT; | ||
607 | break; | ||
608 | case 48000: | ||
609 | clk_ctl |= SGTL5000_SYS_FS_48k << SGTL5000_SYS_FS_SHIFT; | ||
610 | break; | ||
611 | case 96000: | ||
612 | clk_ctl |= SGTL5000_SYS_FS_96k << SGTL5000_SYS_FS_SHIFT; | ||
613 | break; | ||
614 | default: | ||
615 | dev_err(codec->dev, "frame rate %d not supported\n", | ||
616 | frame_rate); | ||
617 | return -EINVAL; | ||
618 | } | ||
619 | |||
620 | /* | ||
621 | * calculate the divider of mclk/sample_freq, | ||
622 | * factor of freq =96k can only be 256, since mclk in range (12m,27m) | ||
623 | */ | ||
624 | switch (sgtl5000->sysclk / sys_fs) { | ||
625 | case 256: | ||
626 | clk_ctl |= SGTL5000_MCLK_FREQ_256FS << | ||
627 | SGTL5000_MCLK_FREQ_SHIFT; | ||
628 | break; | ||
629 | case 384: | ||
630 | clk_ctl |= SGTL5000_MCLK_FREQ_384FS << | ||
631 | SGTL5000_MCLK_FREQ_SHIFT; | ||
632 | break; | ||
633 | case 512: | ||
634 | clk_ctl |= SGTL5000_MCLK_FREQ_512FS << | ||
635 | SGTL5000_MCLK_FREQ_SHIFT; | ||
636 | break; | ||
637 | default: | ||
638 | /* if mclk not satisify the divider, use pll */ | ||
639 | if (sgtl5000->master) { | ||
640 | clk_ctl |= SGTL5000_MCLK_FREQ_PLL << | ||
641 | SGTL5000_MCLK_FREQ_SHIFT; | ||
642 | } else { | ||
643 | dev_err(codec->dev, | ||
644 | "PLL not supported in slave mode\n"); | ||
645 | return -EINVAL; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | /* if using pll, please check manual 6.4.2 for detail */ | ||
650 | if ((clk_ctl & SGTL5000_MCLK_FREQ_MASK) == SGTL5000_MCLK_FREQ_PLL) { | ||
651 | u64 out, t; | ||
652 | int div2; | ||
653 | int pll_ctl; | ||
654 | unsigned int in, int_div, frac_div; | ||
655 | |||
656 | if (sgtl5000->sysclk > 17000000) { | ||
657 | div2 = 1; | ||
658 | in = sgtl5000->sysclk / 2; | ||
659 | } else { | ||
660 | div2 = 0; | ||
661 | in = sgtl5000->sysclk; | ||
662 | } | ||
663 | if (sys_fs == 44100) | ||
664 | out = 180633600; | ||
665 | else | ||
666 | out = 196608000; | ||
667 | t = do_div(out, in); | ||
668 | int_div = out; | ||
669 | t *= 2048; | ||
670 | do_div(t, in); | ||
671 | frac_div = t; | ||
672 | pll_ctl = int_div << SGTL5000_PLL_INT_DIV_SHIFT | | ||
673 | frac_div << SGTL5000_PLL_FRAC_DIV_SHIFT; | ||
674 | |||
675 | snd_soc_write(codec, SGTL5000_CHIP_PLL_CTRL, pll_ctl); | ||
676 | if (div2) | ||
677 | snd_soc_update_bits(codec, | ||
678 | SGTL5000_CHIP_CLK_TOP_CTRL, | ||
679 | SGTL5000_INPUT_FREQ_DIV2, | ||
680 | SGTL5000_INPUT_FREQ_DIV2); | ||
681 | else | ||
682 | snd_soc_update_bits(codec, | ||
683 | SGTL5000_CHIP_CLK_TOP_CTRL, | ||
684 | SGTL5000_INPUT_FREQ_DIV2, | ||
685 | 0); | ||
686 | |||
687 | /* power up pll */ | ||
688 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
689 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, | ||
690 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP); | ||
691 | } else { | ||
692 | /* power down pll */ | ||
693 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
694 | SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP, | ||
695 | 0); | ||
696 | } | ||
697 | |||
698 | /* if using pll, clk_ctrl must be set after pll power up */ | ||
699 | snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl); | ||
700 | |||
701 | return 0; | ||
702 | } | ||
703 | |||
704 | /* | ||
705 | * Set PCM DAI bit size and sample rate. | ||
706 | * input: params_rate, params_fmt | ||
707 | */ | ||
708 | static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream, | ||
709 | struct snd_pcm_hw_params *params, | ||
710 | struct snd_soc_dai *dai) | ||
711 | { | ||
712 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
713 | struct snd_soc_codec *codec = rtd->codec; | ||
714 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
715 | int channels = params_channels(params); | ||
716 | int i2s_ctl = 0; | ||
717 | int stereo; | ||
718 | int ret; | ||
719 | |||
720 | /* sysclk should already set */ | ||
721 | if (!sgtl5000->sysclk) { | ||
722 | dev_err(codec->dev, "%s: set sysclk first!\n", __func__); | ||
723 | return -EFAULT; | ||
724 | } | ||
725 | |||
726 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
727 | stereo = SGTL5000_DAC_STEREO; | ||
728 | else | ||
729 | stereo = SGTL5000_ADC_STEREO; | ||
730 | |||
731 | /* set mono to save power */ | ||
732 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, stereo, | ||
733 | channels == 1 ? 0 : stereo); | ||
734 | |||
735 | /* set codec clock base on lrclk */ | ||
736 | ret = sgtl5000_set_clock(codec, params_rate(params)); | ||
737 | if (ret) | ||
738 | return ret; | ||
739 | |||
740 | /* set i2s data format */ | ||
741 | switch (params_format(params)) { | ||
742 | case SNDRV_PCM_FORMAT_S16_LE: | ||
743 | if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) | ||
744 | return -EINVAL; | ||
745 | i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT; | ||
746 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS << | ||
747 | SGTL5000_I2S_SCLKFREQ_SHIFT; | ||
748 | break; | ||
749 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
750 | i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT; | ||
751 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << | ||
752 | SGTL5000_I2S_SCLKFREQ_SHIFT; | ||
753 | break; | ||
754 | case SNDRV_PCM_FORMAT_S24_LE: | ||
755 | i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT; | ||
756 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << | ||
757 | SGTL5000_I2S_SCLKFREQ_SHIFT; | ||
758 | break; | ||
759 | case SNDRV_PCM_FORMAT_S32_LE: | ||
760 | if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J) | ||
761 | return -EINVAL; | ||
762 | i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT; | ||
763 | i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS << | ||
764 | SGTL5000_I2S_SCLKFREQ_SHIFT; | ||
765 | break; | ||
766 | default: | ||
767 | return -EINVAL; | ||
768 | } | ||
769 | |||
770 | snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl); | ||
771 | |||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | static int ldo_regulator_is_enabled(struct regulator_dev *dev) | ||
776 | { | ||
777 | struct ldo_regulator *ldo = rdev_get_drvdata(dev); | ||
778 | |||
779 | return ldo->enabled; | ||
780 | } | ||
781 | |||
782 | static int ldo_regulator_enable(struct regulator_dev *dev) | ||
783 | { | ||
784 | struct ldo_regulator *ldo = rdev_get_drvdata(dev); | ||
785 | struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data; | ||
786 | int reg; | ||
787 | |||
788 | if (ldo_regulator_is_enabled(dev)) | ||
789 | return 0; | ||
790 | |||
791 | /* set regulator value firstly */ | ||
792 | reg = (1600 - ldo->voltage / 1000) / 50; | ||
793 | reg = clamp(reg, 0x0, 0xf); | ||
794 | |||
795 | /* amend the voltage value, unit: uV */ | ||
796 | ldo->voltage = (1600 - reg * 50) * 1000; | ||
797 | |||
798 | /* set voltage to register */ | ||
799 | snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, | ||
800 | (0x1 << 4) - 1, reg); | ||
801 | |||
802 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
803 | SGTL5000_LINEREG_D_POWERUP, | ||
804 | SGTL5000_LINEREG_D_POWERUP); | ||
805 | |||
806 | /* when internal ldo enabled, simple digital power can be disabled */ | ||
807 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
808 | SGTL5000_LINREG_SIMPLE_POWERUP, | ||
809 | 0); | ||
810 | |||
811 | ldo->enabled = 1; | ||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | static int ldo_regulator_disable(struct regulator_dev *dev) | ||
816 | { | ||
817 | struct ldo_regulator *ldo = rdev_get_drvdata(dev); | ||
818 | struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data; | ||
819 | |||
820 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
821 | SGTL5000_LINEREG_D_POWERUP, | ||
822 | 0); | ||
823 | |||
824 | /* clear voltage info */ | ||
825 | snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, | ||
826 | (0x1 << 4) - 1, 0); | ||
827 | |||
828 | ldo->enabled = 0; | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | static int ldo_regulator_get_voltage(struct regulator_dev *dev) | ||
834 | { | ||
835 | struct ldo_regulator *ldo = rdev_get_drvdata(dev); | ||
836 | |||
837 | return ldo->voltage; | ||
838 | } | ||
839 | |||
840 | static struct regulator_ops ldo_regulator_ops = { | ||
841 | .is_enabled = ldo_regulator_is_enabled, | ||
842 | .enable = ldo_regulator_enable, | ||
843 | .disable = ldo_regulator_disable, | ||
844 | .get_voltage = ldo_regulator_get_voltage, | ||
845 | }; | ||
846 | |||
847 | static int ldo_regulator_register(struct snd_soc_codec *codec, | ||
848 | struct regulator_init_data *init_data, | ||
849 | int voltage) | ||
850 | { | ||
851 | struct ldo_regulator *ldo; | ||
852 | |||
853 | ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL); | ||
854 | |||
855 | if (!ldo) { | ||
856 | dev_err(codec->dev, "failed to allocate ldo_regulator\n"); | ||
857 | return -ENOMEM; | ||
858 | } | ||
859 | |||
860 | ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL); | ||
861 | if (!ldo->desc.name) { | ||
862 | kfree(ldo); | ||
863 | dev_err(codec->dev, "failed to allocate decs name memory\n"); | ||
864 | return -ENOMEM; | ||
865 | } | ||
866 | |||
867 | ldo->desc.type = REGULATOR_VOLTAGE; | ||
868 | ldo->desc.owner = THIS_MODULE; | ||
869 | ldo->desc.ops = &ldo_regulator_ops; | ||
870 | ldo->desc.n_voltages = 1; | ||
871 | |||
872 | ldo->codec_data = codec; | ||
873 | ldo->voltage = voltage; | ||
874 | |||
875 | ldo->dev = regulator_register(&ldo->desc, codec->dev, | ||
876 | init_data, ldo); | ||
877 | if (IS_ERR(ldo->dev)) { | ||
878 | int ret = PTR_ERR(ldo->dev); | ||
879 | |||
880 | dev_err(codec->dev, "failed to register regulator\n"); | ||
881 | kfree(ldo->desc.name); | ||
882 | kfree(ldo); | ||
883 | |||
884 | return ret; | ||
885 | } | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | static int ldo_regulator_remove(struct snd_soc_codec *codec) | ||
891 | { | ||
892 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
893 | struct ldo_regulator *ldo = sgtl5000->ldo; | ||
894 | |||
895 | if (!ldo) | ||
896 | return 0; | ||
897 | |||
898 | regulator_unregister(ldo->dev); | ||
899 | kfree(ldo->desc.name); | ||
900 | kfree(ldo); | ||
901 | |||
902 | return 0; | ||
903 | } | ||
904 | |||
905 | /* | ||
906 | * set dac bias | ||
907 | * common state changes: | ||
908 | * startup: | ||
909 | * off --> standby --> prepare --> on | ||
910 | * standby --> prepare --> on | ||
911 | * | ||
912 | * stop: | ||
913 | * on --> prepare --> standby | ||
914 | */ | ||
915 | static int sgtl5000_set_bias_level(struct snd_soc_codec *codec, | ||
916 | enum snd_soc_bias_level level) | ||
917 | { | ||
918 | int ret; | ||
919 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
920 | |||
921 | switch (level) { | ||
922 | case SND_SOC_BIAS_ON: | ||
923 | case SND_SOC_BIAS_PREPARE: | ||
924 | break; | ||
925 | case SND_SOC_BIAS_STANDBY: | ||
926 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
927 | ret = regulator_bulk_enable( | ||
928 | ARRAY_SIZE(sgtl5000->supplies), | ||
929 | sgtl5000->supplies); | ||
930 | if (ret) | ||
931 | return ret; | ||
932 | udelay(10); | ||
933 | } | ||
934 | |||
935 | break; | ||
936 | case SND_SOC_BIAS_OFF: | ||
937 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
938 | sgtl5000->supplies); | ||
939 | break; | ||
940 | } | ||
941 | |||
942 | codec->dapm.bias_level = level; | ||
943 | return 0; | ||
944 | } | ||
945 | |||
946 | #define SGTL5000_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | ||
947 | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
948 | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
949 | SNDRV_PCM_FMTBIT_S32_LE) | ||
950 | |||
951 | static struct snd_soc_dai_ops sgtl5000_ops = { | ||
952 | .hw_params = sgtl5000_pcm_hw_params, | ||
953 | .digital_mute = sgtl5000_digital_mute, | ||
954 | .set_fmt = sgtl5000_set_dai_fmt, | ||
955 | .set_sysclk = sgtl5000_set_dai_sysclk, | ||
956 | }; | ||
957 | |||
958 | static struct snd_soc_dai_driver sgtl5000_dai = { | ||
959 | .name = "sgtl5000", | ||
960 | .playback = { | ||
961 | .stream_name = "Playback", | ||
962 | .channels_min = 1, | ||
963 | .channels_max = 2, | ||
964 | /* | ||
965 | * only support 8~48K + 96K, | ||
966 | * TODO modify hw_param to support more | ||
967 | */ | ||
968 | .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_96000, | ||
969 | .formats = SGTL5000_FORMATS, | ||
970 | }, | ||
971 | .capture = { | ||
972 | .stream_name = "Capture", | ||
973 | .channels_min = 1, | ||
974 | .channels_max = 2, | ||
975 | .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_96000, | ||
976 | .formats = SGTL5000_FORMATS, | ||
977 | }, | ||
978 | .ops = &sgtl5000_ops, | ||
979 | .symmetric_rates = 1, | ||
980 | }; | ||
981 | |||
982 | static int sgtl5000_volatile_register(struct snd_soc_codec *codec, | ||
983 | unsigned int reg) | ||
984 | { | ||
985 | switch (reg) { | ||
986 | case SGTL5000_CHIP_ID: | ||
987 | case SGTL5000_CHIP_ADCDAC_CTRL: | ||
988 | case SGTL5000_CHIP_ANA_STATUS: | ||
989 | return 1; | ||
990 | } | ||
991 | |||
992 | return 0; | ||
993 | } | ||
994 | |||
995 | #ifdef CONFIG_SUSPEND | ||
996 | static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
997 | { | ||
998 | sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
999 | |||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | /* | ||
1004 | * restore all sgtl5000 registers, | ||
1005 | * since a big hole between dap and regular registers, | ||
1006 | * we will restore them respectively. | ||
1007 | */ | ||
1008 | static int sgtl5000_restore_regs(struct snd_soc_codec *codec) | ||
1009 | { | ||
1010 | u16 *cache = codec->reg_cache; | ||
1011 | int i; | ||
1012 | int regular_regs = SGTL5000_CHIP_SHORT_CTRL >> 1; | ||
1013 | |||
1014 | /* restore regular registers */ | ||
1015 | for (i = 0; i < regular_regs; i++) { | ||
1016 | int reg = i << 1; | ||
1017 | |||
1018 | /* this regs depends on the others */ | ||
1019 | if (reg == SGTL5000_CHIP_ANA_POWER || | ||
1020 | reg == SGTL5000_CHIP_CLK_CTRL || | ||
1021 | reg == SGTL5000_CHIP_LINREG_CTRL || | ||
1022 | reg == SGTL5000_CHIP_LINE_OUT_CTRL || | ||
1023 | reg == SGTL5000_CHIP_CLK_CTRL) | ||
1024 | continue; | ||
1025 | |||
1026 | snd_soc_write(codec, reg, cache[i]); | ||
1027 | } | ||
1028 | |||
1029 | /* restore dap registers */ | ||
1030 | for (i = SGTL5000_DAP_REG_OFFSET >> 1; | ||
1031 | i < SGTL5000_MAX_REG_OFFSET >> 1; i++) { | ||
1032 | int reg = i << 1; | ||
1033 | |||
1034 | snd_soc_write(codec, reg, cache[i]); | ||
1035 | } | ||
1036 | |||
1037 | /* | ||
1038 | * restore power and other regs according | ||
1039 | * to set_power() and set_clock() | ||
1040 | */ | ||
1041 | snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, | ||
1042 | cache[SGTL5000_CHIP_LINREG_CTRL >> 1]); | ||
1043 | |||
1044 | snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, | ||
1045 | cache[SGTL5000_CHIP_ANA_POWER >> 1]); | ||
1046 | |||
1047 | snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, | ||
1048 | cache[SGTL5000_CHIP_CLK_CTRL >> 1]); | ||
1049 | |||
1050 | snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL, | ||
1051 | cache[SGTL5000_CHIP_REF_CTRL >> 1]); | ||
1052 | |||
1053 | snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL, | ||
1054 | cache[SGTL5000_CHIP_LINE_OUT_CTRL >> 1]); | ||
1055 | return 0; | ||
1056 | } | ||
1057 | |||
1058 | static int sgtl5000_resume(struct snd_soc_codec *codec) | ||
1059 | { | ||
1060 | /* Bring the codec back up to standby to enable regulators */ | ||
1061 | sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1062 | |||
1063 | /* Restore registers by cached in memory */ | ||
1064 | sgtl5000_restore_regs(codec); | ||
1065 | return 0; | ||
1066 | } | ||
1067 | #else | ||
1068 | #define sgtl5000_suspend NULL | ||
1069 | #define sgtl5000_resume NULL | ||
1070 | #endif /* CONFIG_SUSPEND */ | ||
1071 | |||
1072 | /* | ||
1073 | * sgtl5000 has 3 internal power supplies: | ||
1074 | * 1. VAG, normally set to vdda/2 | ||
1075 | * 2. chargepump, set to different value | ||
1076 | * according to voltage of vdda and vddio | ||
1077 | * 3. line out VAG, normally set to vddio/2 | ||
1078 | * | ||
1079 | * and should be set according to: | ||
1080 | * 1. vddd provided by external or not | ||
1081 | * 2. vdda and vddio voltage value. > 3.1v or not | ||
1082 | * 3. chip revision >=0x11 or not. If >=0x11, not use external vddd. | ||
1083 | */ | ||
1084 | static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) | ||
1085 | { | ||
1086 | int vddd; | ||
1087 | int vdda; | ||
1088 | int vddio; | ||
1089 | u16 ana_pwr; | ||
1090 | u16 lreg_ctrl; | ||
1091 | int vag; | ||
1092 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
1093 | |||
1094 | vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer); | ||
1095 | vddio = regulator_get_voltage(sgtl5000->supplies[VDDIO].consumer); | ||
1096 | vddd = regulator_get_voltage(sgtl5000->supplies[VDDD].consumer); | ||
1097 | |||
1098 | vdda = vdda / 1000; | ||
1099 | vddio = vddio / 1000; | ||
1100 | vddd = vddd / 1000; | ||
1101 | |||
1102 | if (vdda <= 0 || vddio <= 0 || vddd < 0) { | ||
1103 | dev_err(codec->dev, "regulator voltage not set correctly\n"); | ||
1104 | |||
1105 | return -EINVAL; | ||
1106 | } | ||
1107 | |||
1108 | /* according to datasheet, maximum voltage of supplies */ | ||
1109 | if (vdda > 3600 || vddio > 3600 || vddd > 1980) { | ||
1110 | dev_err(codec->dev, | ||
1111 | "exceed max voltage vdda %dmv vddio %dma vddd %dma\n", | ||
1112 | vdda, vddio, vddd); | ||
1113 | |||
1114 | return -EINVAL; | ||
1115 | } | ||
1116 | |||
1117 | /* reset value */ | ||
1118 | ana_pwr = snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER); | ||
1119 | ana_pwr |= SGTL5000_DAC_STEREO | | ||
1120 | SGTL5000_ADC_STEREO | | ||
1121 | SGTL5000_REFTOP_POWERUP; | ||
1122 | lreg_ctrl = snd_soc_read(codec, SGTL5000_CHIP_LINREG_CTRL); | ||
1123 | |||
1124 | if (vddio < 3100 && vdda < 3100) { | ||
1125 | /* enable internal oscillator used for charge pump */ | ||
1126 | snd_soc_update_bits(codec, SGTL5000_CHIP_CLK_TOP_CTRL, | ||
1127 | SGTL5000_INT_OSC_EN, | ||
1128 | SGTL5000_INT_OSC_EN); | ||
1129 | /* Enable VDDC charge pump */ | ||
1130 | ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP; | ||
1131 | } else if (vddio >= 3100 && vdda >= 3100) { | ||
1132 | /* | ||
1133 | * if vddio and vddd > 3.1v, | ||
1134 | * charge pump should be clean before set ana_pwr | ||
1135 | */ | ||
1136 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
1137 | SGTL5000_VDDC_CHRGPMP_POWERUP, 0); | ||
1138 | |||
1139 | /* VDDC use VDDIO rail */ | ||
1140 | lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD; | ||
1141 | lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << | ||
1142 | SGTL5000_VDDC_MAN_ASSN_SHIFT; | ||
1143 | } | ||
1144 | |||
1145 | snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl); | ||
1146 | |||
1147 | snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, ana_pwr); | ||
1148 | |||
1149 | /* set voltage to register */ | ||
1150 | snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, | ||
1151 | (0x1 << 4) - 1, 0x8); | ||
1152 | |||
1153 | /* | ||
1154 | * if vddd linear reg has been enabled, | ||
1155 | * simple digital supply should be clear to get | ||
1156 | * proper VDDD voltage. | ||
1157 | */ | ||
1158 | if (ana_pwr & SGTL5000_LINEREG_D_POWERUP) | ||
1159 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
1160 | SGTL5000_LINREG_SIMPLE_POWERUP, | ||
1161 | 0); | ||
1162 | else | ||
1163 | snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, | ||
1164 | SGTL5000_LINREG_SIMPLE_POWERUP | | ||
1165 | SGTL5000_STARTUP_POWERUP, | ||
1166 | 0); | ||
1167 | |||
1168 | /* | ||
1169 | * set ADC/DAC VAG to vdda / 2, | ||
1170 | * should stay in range (0.8v, 1.575v) | ||
1171 | */ | ||
1172 | vag = vdda / 2; | ||
1173 | if (vag <= SGTL5000_ANA_GND_BASE) | ||
1174 | vag = 0; | ||
1175 | else if (vag >= SGTL5000_ANA_GND_BASE + SGTL5000_ANA_GND_STP * | ||
1176 | (SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT)) | ||
1177 | vag = SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT; | ||
1178 | else | ||
1179 | vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP; | ||
1180 | |||
1181 | snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, | ||
1182 | vag << SGTL5000_ANA_GND_SHIFT, | ||
1183 | vag << SGTL5000_ANA_GND_SHIFT); | ||
1184 | |||
1185 | /* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */ | ||
1186 | vag = vddio / 2; | ||
1187 | if (vag <= SGTL5000_LINE_OUT_GND_BASE) | ||
1188 | vag = 0; | ||
1189 | else if (vag >= SGTL5000_LINE_OUT_GND_BASE + | ||
1190 | SGTL5000_LINE_OUT_GND_STP * SGTL5000_LINE_OUT_GND_MAX) | ||
1191 | vag = SGTL5000_LINE_OUT_GND_MAX; | ||
1192 | else | ||
1193 | vag = (vag - SGTL5000_LINE_OUT_GND_BASE) / | ||
1194 | SGTL5000_LINE_OUT_GND_STP; | ||
1195 | |||
1196 | snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL, | ||
1197 | vag << SGTL5000_LINE_OUT_GND_SHIFT | | ||
1198 | SGTL5000_LINE_OUT_CURRENT_360u << | ||
1199 | SGTL5000_LINE_OUT_CURRENT_SHIFT, | ||
1200 | vag << SGTL5000_LINE_OUT_GND_SHIFT | | ||
1201 | SGTL5000_LINE_OUT_CURRENT_360u << | ||
1202 | SGTL5000_LINE_OUT_CURRENT_SHIFT); | ||
1203 | |||
1204 | return 0; | ||
1205 | } | ||
1206 | |||
1207 | static int sgtl5000_enable_regulators(struct snd_soc_codec *codec) | ||
1208 | { | ||
1209 | u16 reg; | ||
1210 | int ret; | ||
1211 | int rev; | ||
1212 | int i; | ||
1213 | int external_vddd = 0; | ||
1214 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
1215 | |||
1216 | for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++) | ||
1217 | sgtl5000->supplies[i].supply = supply_names[i]; | ||
1218 | |||
1219 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), | ||
1220 | sgtl5000->supplies); | ||
1221 | if (!ret) | ||
1222 | external_vddd = 1; | ||
1223 | else { | ||
1224 | /* set internal ldo to 1.2v */ | ||
1225 | int voltage = LDO_VOLTAGE; | ||
1226 | |||
1227 | ret = ldo_regulator_register(codec, &ldo_init_data, voltage); | ||
1228 | if (ret) { | ||
1229 | dev_err(codec->dev, | ||
1230 | "Failed to register vddd internal supplies: %d\n", | ||
1231 | ret); | ||
1232 | return ret; | ||
1233 | } | ||
1234 | |||
1235 | sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; | ||
1236 | |||
1237 | ret = regulator_bulk_get(codec->dev, | ||
1238 | ARRAY_SIZE(sgtl5000->supplies), | ||
1239 | sgtl5000->supplies); | ||
1240 | |||
1241 | if (ret) { | ||
1242 | ldo_regulator_remove(codec); | ||
1243 | dev_err(codec->dev, | ||
1244 | "Failed to request supplies: %d\n", ret); | ||
1245 | |||
1246 | return ret; | ||
1247 | } | ||
1248 | } | ||
1249 | |||
1250 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | ||
1251 | sgtl5000->supplies); | ||
1252 | if (ret) | ||
1253 | goto err_regulator_free; | ||
1254 | |||
1255 | /* wait for all power rails bring up */ | ||
1256 | udelay(10); | ||
1257 | |||
1258 | /* read chip information */ | ||
1259 | reg = snd_soc_read(codec, SGTL5000_CHIP_ID); | ||
1260 | if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) != | ||
1261 | SGTL5000_PARTID_PART_ID) { | ||
1262 | dev_err(codec->dev, | ||
1263 | "Device with ID register %x is not a sgtl5000\n", reg); | ||
1264 | ret = -ENODEV; | ||
1265 | goto err_regulator_disable; | ||
1266 | } | ||
1267 | |||
1268 | rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT; | ||
1269 | dev_info(codec->dev, "sgtl5000 revision %d\n", rev); | ||
1270 | |||
1271 | /* | ||
1272 | * workaround for revision 0x11 and later, | ||
1273 | * roll back to use internal LDO | ||
1274 | */ | ||
1275 | if (external_vddd && rev >= 0x11) { | ||
1276 | int voltage = LDO_VOLTAGE; | ||
1277 | /* disable all regulator first */ | ||
1278 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
1279 | sgtl5000->supplies); | ||
1280 | /* free VDDD regulator */ | ||
1281 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1282 | sgtl5000->supplies); | ||
1283 | |||
1284 | ret = ldo_regulator_register(codec, &ldo_init_data, voltage); | ||
1285 | if (ret) | ||
1286 | return ret; | ||
1287 | |||
1288 | sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; | ||
1289 | |||
1290 | ret = regulator_bulk_get(codec->dev, | ||
1291 | ARRAY_SIZE(sgtl5000->supplies), | ||
1292 | sgtl5000->supplies); | ||
1293 | if (ret) { | ||
1294 | ldo_regulator_remove(codec); | ||
1295 | dev_err(codec->dev, | ||
1296 | "Failed to request supplies: %d\n", ret); | ||
1297 | |||
1298 | return ret; | ||
1299 | } | ||
1300 | |||
1301 | ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), | ||
1302 | sgtl5000->supplies); | ||
1303 | if (ret) | ||
1304 | goto err_regulator_free; | ||
1305 | |||
1306 | /* wait for all power rails bring up */ | ||
1307 | udelay(10); | ||
1308 | } | ||
1309 | |||
1310 | return 0; | ||
1311 | |||
1312 | err_regulator_disable: | ||
1313 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
1314 | sgtl5000->supplies); | ||
1315 | err_regulator_free: | ||
1316 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1317 | sgtl5000->supplies); | ||
1318 | if (external_vddd) | ||
1319 | ldo_regulator_remove(codec); | ||
1320 | return ret; | ||
1321 | |||
1322 | } | ||
1323 | |||
1324 | static int sgtl5000_probe(struct snd_soc_codec *codec) | ||
1325 | { | ||
1326 | int ret; | ||
1327 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
1328 | |||
1329 | /* setup i2c data ops */ | ||
1330 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C); | ||
1331 | if (ret < 0) { | ||
1332 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
1333 | return ret; | ||
1334 | } | ||
1335 | |||
1336 | ret = sgtl5000_enable_regulators(codec); | ||
1337 | if (ret) | ||
1338 | return ret; | ||
1339 | |||
1340 | /* power up sgtl5000 */ | ||
1341 | ret = sgtl5000_set_power_regs(codec); | ||
1342 | if (ret) | ||
1343 | goto err; | ||
1344 | |||
1345 | /* enable small pop, introduce 400ms delay in turning off */ | ||
1346 | snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL, | ||
1347 | SGTL5000_SMALL_POP, | ||
1348 | SGTL5000_SMALL_POP); | ||
1349 | |||
1350 | /* disable short cut detector */ | ||
1351 | snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0); | ||
1352 | |||
1353 | /* | ||
1354 | * set i2s as default input of sound switch | ||
1355 | * TODO: add sound switch to control and dapm widge. | ||
1356 | */ | ||
1357 | snd_soc_write(codec, SGTL5000_CHIP_SSS_CTRL, | ||
1358 | SGTL5000_DAC_SEL_I2S_IN << SGTL5000_DAC_SEL_SHIFT); | ||
1359 | snd_soc_write(codec, SGTL5000_CHIP_DIG_POWER, | ||
1360 | SGTL5000_ADC_EN | SGTL5000_DAC_EN); | ||
1361 | |||
1362 | /* enable dac volume ramp by default */ | ||
1363 | snd_soc_write(codec, SGTL5000_CHIP_ADCDAC_CTRL, | ||
1364 | SGTL5000_DAC_VOL_RAMP_EN | | ||
1365 | SGTL5000_DAC_MUTE_RIGHT | | ||
1366 | SGTL5000_DAC_MUTE_LEFT); | ||
1367 | |||
1368 | snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f); | ||
1369 | |||
1370 | snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL, | ||
1371 | SGTL5000_HP_ZCD_EN | | ||
1372 | SGTL5000_ADC_ZCD_EN); | ||
1373 | |||
1374 | snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0); | ||
1375 | |||
1376 | /* | ||
1377 | * disable DAP | ||
1378 | * TODO: | ||
1379 | * Enable DAP in kcontrol and dapm. | ||
1380 | */ | ||
1381 | snd_soc_write(codec, SGTL5000_DAP_CTRL, 0); | ||
1382 | |||
1383 | /* leading to standby state */ | ||
1384 | ret = sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1385 | if (ret) | ||
1386 | goto err; | ||
1387 | |||
1388 | snd_soc_add_controls(codec, sgtl5000_snd_controls, | ||
1389 | ARRAY_SIZE(sgtl5000_snd_controls)); | ||
1390 | |||
1391 | snd_soc_dapm_new_controls(&codec->dapm, sgtl5000_dapm_widgets, | ||
1392 | ARRAY_SIZE(sgtl5000_dapm_widgets)); | ||
1393 | |||
1394 | snd_soc_dapm_add_routes(&codec->dapm, audio_map, | ||
1395 | ARRAY_SIZE(audio_map)); | ||
1396 | |||
1397 | snd_soc_dapm_new_widgets(&codec->dapm); | ||
1398 | |||
1399 | return 0; | ||
1400 | |||
1401 | err: | ||
1402 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
1403 | sgtl5000->supplies); | ||
1404 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1405 | sgtl5000->supplies); | ||
1406 | ldo_regulator_remove(codec); | ||
1407 | |||
1408 | return ret; | ||
1409 | } | ||
1410 | |||
1411 | static int sgtl5000_remove(struct snd_soc_codec *codec) | ||
1412 | { | ||
1413 | struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); | ||
1414 | |||
1415 | sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1416 | |||
1417 | regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies), | ||
1418 | sgtl5000->supplies); | ||
1419 | regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), | ||
1420 | sgtl5000->supplies); | ||
1421 | ldo_regulator_remove(codec); | ||
1422 | |||
1423 | return 0; | ||
1424 | } | ||
1425 | |||
1426 | static struct snd_soc_codec_driver sgtl5000_driver = { | ||
1427 | .probe = sgtl5000_probe, | ||
1428 | .remove = sgtl5000_remove, | ||
1429 | .suspend = sgtl5000_suspend, | ||
1430 | .resume = sgtl5000_resume, | ||
1431 | .set_bias_level = sgtl5000_set_bias_level, | ||
1432 | .reg_cache_size = ARRAY_SIZE(sgtl5000_regs), | ||
1433 | .reg_word_size = sizeof(u16), | ||
1434 | .reg_cache_step = 2, | ||
1435 | .reg_cache_default = sgtl5000_regs, | ||
1436 | .volatile_register = sgtl5000_volatile_register, | ||
1437 | }; | ||
1438 | |||
1439 | static __devinit int sgtl5000_i2c_probe(struct i2c_client *client, | ||
1440 | const struct i2c_device_id *id) | ||
1441 | { | ||
1442 | struct sgtl5000_priv *sgtl5000; | ||
1443 | int ret; | ||
1444 | |||
1445 | sgtl5000 = kzalloc(sizeof(struct sgtl5000_priv), GFP_KERNEL); | ||
1446 | if (!sgtl5000) | ||
1447 | return -ENOMEM; | ||
1448 | |||
1449 | /* | ||
1450 | * copy DAP default values to default value array. | ||
1451 | * sgtl5000 register space has a big hole, merge it | ||
1452 | * at init phase makes life easy. | ||
1453 | * FIXME: should we drop 'const' of sgtl5000_regs? | ||
1454 | */ | ||
1455 | memcpy((void *)(&sgtl5000_regs[0] + (SGTL5000_DAP_REG_OFFSET >> 1)), | ||
1456 | sgtl5000_dap_regs, | ||
1457 | SGTL5000_MAX_REG_OFFSET - SGTL5000_DAP_REG_OFFSET); | ||
1458 | |||
1459 | i2c_set_clientdata(client, sgtl5000); | ||
1460 | |||
1461 | ret = snd_soc_register_codec(&client->dev, | ||
1462 | &sgtl5000_driver, &sgtl5000_dai, 1); | ||
1463 | if (ret) { | ||
1464 | dev_err(&client->dev, "Failed to register codec: %d\n", ret); | ||
1465 | kfree(sgtl5000); | ||
1466 | return ret; | ||
1467 | } | ||
1468 | |||
1469 | return 0; | ||
1470 | } | ||
1471 | |||
1472 | static __devexit int sgtl5000_i2c_remove(struct i2c_client *client) | ||
1473 | { | ||
1474 | struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client); | ||
1475 | |||
1476 | snd_soc_unregister_codec(&client->dev); | ||
1477 | |||
1478 | kfree(sgtl5000); | ||
1479 | return 0; | ||
1480 | } | ||
1481 | |||
1482 | static const struct i2c_device_id sgtl5000_id[] = { | ||
1483 | {"sgtl5000", 0}, | ||
1484 | {}, | ||
1485 | }; | ||
1486 | |||
1487 | MODULE_DEVICE_TABLE(i2c, sgtl5000_id); | ||
1488 | |||
1489 | static struct i2c_driver sgtl5000_i2c_driver = { | ||
1490 | .driver = { | ||
1491 | .name = "sgtl5000", | ||
1492 | .owner = THIS_MODULE, | ||
1493 | }, | ||
1494 | .probe = sgtl5000_i2c_probe, | ||
1495 | .remove = __devexit_p(sgtl5000_i2c_remove), | ||
1496 | .id_table = sgtl5000_id, | ||
1497 | }; | ||
1498 | |||
1499 | static int __init sgtl5000_modinit(void) | ||
1500 | { | ||
1501 | return i2c_add_driver(&sgtl5000_i2c_driver); | ||
1502 | } | ||
1503 | module_init(sgtl5000_modinit); | ||
1504 | |||
1505 | static void __exit sgtl5000_exit(void) | ||
1506 | { | ||
1507 | i2c_del_driver(&sgtl5000_i2c_driver); | ||
1508 | } | ||
1509 | module_exit(sgtl5000_exit); | ||
1510 | |||
1511 | MODULE_DESCRIPTION("Freescale SGTL5000 ALSA SoC Codec Driver"); | ||
1512 | MODULE_AUTHOR("Zeng Zhaoming <zhaoming.zeng@freescale.com>"); | ||
1513 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h new file mode 100644 index 000000000000..eec3ab368f39 --- /dev/null +++ b/sound/soc/codecs/sgtl5000.h | |||
@@ -0,0 +1,400 @@ | |||
1 | /* | ||
2 | * sgtl5000.h - SGTL5000 audio codec interface | ||
3 | * | ||
4 | * Copyright 2010-2011 Freescale Semiconductor, Inc. | ||
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 version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifndef _SGTL5000_H | ||
12 | #define _SGTL5000_H | ||
13 | |||
14 | /* | ||
15 | * Register values. | ||
16 | */ | ||
17 | #define SGTL5000_CHIP_ID 0x0000 | ||
18 | #define SGTL5000_CHIP_DIG_POWER 0x0002 | ||
19 | #define SGTL5000_CHIP_CLK_CTRL 0x0004 | ||
20 | #define SGTL5000_CHIP_I2S_CTRL 0x0006 | ||
21 | #define SGTL5000_CHIP_SSS_CTRL 0x000a | ||
22 | #define SGTL5000_CHIP_ADCDAC_CTRL 0x000e | ||
23 | #define SGTL5000_CHIP_DAC_VOL 0x0010 | ||
24 | #define SGTL5000_CHIP_PAD_STRENGTH 0x0014 | ||
25 | #define SGTL5000_CHIP_ANA_ADC_CTRL 0x0020 | ||
26 | #define SGTL5000_CHIP_ANA_HP_CTRL 0x0022 | ||
27 | #define SGTL5000_CHIP_ANA_CTRL 0x0024 | ||
28 | #define SGTL5000_CHIP_LINREG_CTRL 0x0026 | ||
29 | #define SGTL5000_CHIP_REF_CTRL 0x0028 | ||
30 | #define SGTL5000_CHIP_MIC_CTRL 0x002a | ||
31 | #define SGTL5000_CHIP_LINE_OUT_CTRL 0x002c | ||
32 | #define SGTL5000_CHIP_LINE_OUT_VOL 0x002e | ||
33 | #define SGTL5000_CHIP_ANA_POWER 0x0030 | ||
34 | #define SGTL5000_CHIP_PLL_CTRL 0x0032 | ||
35 | #define SGTL5000_CHIP_CLK_TOP_CTRL 0x0034 | ||
36 | #define SGTL5000_CHIP_ANA_STATUS 0x0036 | ||
37 | #define SGTL5000_CHIP_SHORT_CTRL 0x003c | ||
38 | #define SGTL5000_CHIP_ANA_TEST2 0x003a | ||
39 | #define SGTL5000_DAP_CTRL 0x0100 | ||
40 | #define SGTL5000_DAP_PEQ 0x0102 | ||
41 | #define SGTL5000_DAP_BASS_ENHANCE 0x0104 | ||
42 | #define SGTL5000_DAP_BASS_ENHANCE_CTRL 0x0106 | ||
43 | #define SGTL5000_DAP_AUDIO_EQ 0x0108 | ||
44 | #define SGTL5000_DAP_SURROUND 0x010a | ||
45 | #define SGTL5000_DAP_FLT_COEF_ACCESS 0x010c | ||
46 | #define SGTL5000_DAP_COEF_WR_B0_MSB 0x010e | ||
47 | #define SGTL5000_DAP_COEF_WR_B0_LSB 0x0110 | ||
48 | #define SGTL5000_DAP_EQ_BASS_BAND0 0x0116 | ||
49 | #define SGTL5000_DAP_EQ_BASS_BAND1 0x0118 | ||
50 | #define SGTL5000_DAP_EQ_BASS_BAND2 0x011a | ||
51 | #define SGTL5000_DAP_EQ_BASS_BAND3 0x011c | ||
52 | #define SGTL5000_DAP_EQ_BASS_BAND4 0x011e | ||
53 | #define SGTL5000_DAP_MAIN_CHAN 0x0120 | ||
54 | #define SGTL5000_DAP_MIX_CHAN 0x0122 | ||
55 | #define SGTL5000_DAP_AVC_CTRL 0x0124 | ||
56 | #define SGTL5000_DAP_AVC_THRESHOLD 0x0126 | ||
57 | #define SGTL5000_DAP_AVC_ATTACK 0x0128 | ||
58 | #define SGTL5000_DAP_AVC_DECAY 0x012a | ||
59 | #define SGTL5000_DAP_COEF_WR_B1_MSB 0x012c | ||
60 | #define SGTL5000_DAP_COEF_WR_B1_LSB 0x012e | ||
61 | #define SGTL5000_DAP_COEF_WR_B2_MSB 0x0130 | ||
62 | #define SGTL5000_DAP_COEF_WR_B2_LSB 0x0132 | ||
63 | #define SGTL5000_DAP_COEF_WR_A1_MSB 0x0134 | ||
64 | #define SGTL5000_DAP_COEF_WR_A1_LSB 0x0136 | ||
65 | #define SGTL5000_DAP_COEF_WR_A2_MSB 0x0138 | ||
66 | #define SGTL5000_DAP_COEF_WR_A2_LSB 0x013a | ||
67 | |||
68 | /* | ||
69 | * Field Definitions. | ||
70 | */ | ||
71 | |||
72 | /* | ||
73 | * SGTL5000_CHIP_ID | ||
74 | */ | ||
75 | #define SGTL5000_PARTID_MASK 0xff00 | ||
76 | #define SGTL5000_PARTID_SHIFT 8 | ||
77 | #define SGTL5000_PARTID_WIDTH 8 | ||
78 | #define SGTL5000_PARTID_PART_ID 0xa0 | ||
79 | #define SGTL5000_REVID_MASK 0x00ff | ||
80 | #define SGTL5000_REVID_SHIFT 0 | ||
81 | #define SGTL5000_REVID_WIDTH 8 | ||
82 | |||
83 | /* | ||
84 | * SGTL5000_CHIP_DIG_POWER | ||
85 | */ | ||
86 | #define SGTL5000_ADC_EN 0x0040 | ||
87 | #define SGTL5000_DAC_EN 0x0020 | ||
88 | #define SGTL5000_DAP_POWERUP 0x0010 | ||
89 | #define SGTL5000_I2S_OUT_POWERUP 0x0002 | ||
90 | #define SGTL5000_I2S_IN_POWERUP 0x0001 | ||
91 | |||
92 | /* | ||
93 | * SGTL5000_CHIP_CLK_CTRL | ||
94 | */ | ||
95 | #define SGTL5000_RATE_MODE_MASK 0x0030 | ||
96 | #define SGTL5000_RATE_MODE_SHIFT 4 | ||
97 | #define SGTL5000_RATE_MODE_WIDTH 2 | ||
98 | #define SGTL5000_RATE_MODE_DIV_1 0 | ||
99 | #define SGTL5000_RATE_MODE_DIV_2 1 | ||
100 | #define SGTL5000_RATE_MODE_DIV_4 2 | ||
101 | #define SGTL5000_RATE_MODE_DIV_6 3 | ||
102 | #define SGTL5000_SYS_FS_MASK 0x000c | ||
103 | #define SGTL5000_SYS_FS_SHIFT 2 | ||
104 | #define SGTL5000_SYS_FS_WIDTH 2 | ||
105 | #define SGTL5000_SYS_FS_32k 0x0 | ||
106 | #define SGTL5000_SYS_FS_44_1k 0x1 | ||
107 | #define SGTL5000_SYS_FS_48k 0x2 | ||
108 | #define SGTL5000_SYS_FS_96k 0x3 | ||
109 | #define SGTL5000_MCLK_FREQ_MASK 0x0003 | ||
110 | #define SGTL5000_MCLK_FREQ_SHIFT 0 | ||
111 | #define SGTL5000_MCLK_FREQ_WIDTH 2 | ||
112 | #define SGTL5000_MCLK_FREQ_256FS 0x0 | ||
113 | #define SGTL5000_MCLK_FREQ_384FS 0x1 | ||
114 | #define SGTL5000_MCLK_FREQ_512FS 0x2 | ||
115 | #define SGTL5000_MCLK_FREQ_PLL 0x3 | ||
116 | |||
117 | /* | ||
118 | * SGTL5000_CHIP_I2S_CTRL | ||
119 | */ | ||
120 | #define SGTL5000_I2S_SCLKFREQ_MASK 0x0100 | ||
121 | #define SGTL5000_I2S_SCLKFREQ_SHIFT 8 | ||
122 | #define SGTL5000_I2S_SCLKFREQ_WIDTH 1 | ||
123 | #define SGTL5000_I2S_SCLKFREQ_64FS 0x0 | ||
124 | #define SGTL5000_I2S_SCLKFREQ_32FS 0x1 /* Not for RJ mode */ | ||
125 | #define SGTL5000_I2S_MASTER 0x0080 | ||
126 | #define SGTL5000_I2S_SCLK_INV 0x0040 | ||
127 | #define SGTL5000_I2S_DLEN_MASK 0x0030 | ||
128 | #define SGTL5000_I2S_DLEN_SHIFT 4 | ||
129 | #define SGTL5000_I2S_DLEN_WIDTH 2 | ||
130 | #define SGTL5000_I2S_DLEN_32 0x0 | ||
131 | #define SGTL5000_I2S_DLEN_24 0x1 | ||
132 | #define SGTL5000_I2S_DLEN_20 0x2 | ||
133 | #define SGTL5000_I2S_DLEN_16 0x3 | ||
134 | #define SGTL5000_I2S_MODE_MASK 0x000c | ||
135 | #define SGTL5000_I2S_MODE_SHIFT 2 | ||
136 | #define SGTL5000_I2S_MODE_WIDTH 2 | ||
137 | #define SGTL5000_I2S_MODE_I2S_LJ 0x0 | ||
138 | #define SGTL5000_I2S_MODE_RJ 0x1 | ||
139 | #define SGTL5000_I2S_MODE_PCM 0x2 | ||
140 | #define SGTL5000_I2S_LRALIGN 0x0002 | ||
141 | #define SGTL5000_I2S_LRPOL 0x0001 /* set for which mode */ | ||
142 | |||
143 | /* | ||
144 | * SGTL5000_CHIP_SSS_CTRL | ||
145 | */ | ||
146 | #define SGTL5000_DAP_MIX_LRSWAP 0x4000 | ||
147 | #define SGTL5000_DAP_LRSWAP 0x2000 | ||
148 | #define SGTL5000_DAC_LRSWAP 0x1000 | ||
149 | #define SGTL5000_I2S_OUT_LRSWAP 0x0400 | ||
150 | #define SGTL5000_DAP_MIX_SEL_MASK 0x0300 | ||
151 | #define SGTL5000_DAP_MIX_SEL_SHIFT 8 | ||
152 | #define SGTL5000_DAP_MIX_SEL_WIDTH 2 | ||
153 | #define SGTL5000_DAP_MIX_SEL_ADC 0x0 | ||
154 | #define SGTL5000_DAP_MIX_SEL_I2S_IN 0x1 | ||
155 | #define SGTL5000_DAP_SEL_MASK 0x00c0 | ||
156 | #define SGTL5000_DAP_SEL_SHIFT 6 | ||
157 | #define SGTL5000_DAP_SEL_WIDTH 2 | ||
158 | #define SGTL5000_DAP_SEL_ADC 0x0 | ||
159 | #define SGTL5000_DAP_SEL_I2S_IN 0x1 | ||
160 | #define SGTL5000_DAC_SEL_MASK 0x0030 | ||
161 | #define SGTL5000_DAC_SEL_SHIFT 4 | ||
162 | #define SGTL5000_DAC_SEL_WIDTH 2 | ||
163 | #define SGTL5000_DAC_SEL_ADC 0x0 | ||
164 | #define SGTL5000_DAC_SEL_I2S_IN 0x1 | ||
165 | #define SGTL5000_DAC_SEL_DAP 0x3 | ||
166 | #define SGTL5000_I2S_OUT_SEL_MASK 0x0003 | ||
167 | #define SGTL5000_I2S_OUT_SEL_SHIFT 0 | ||
168 | #define SGTL5000_I2S_OUT_SEL_WIDTH 2 | ||
169 | #define SGTL5000_I2S_OUT_SEL_ADC 0x0 | ||
170 | #define SGTL5000_I2S_OUT_SEL_I2S_IN 0x1 | ||
171 | #define SGTL5000_I2S_OUT_SEL_DAP 0x3 | ||
172 | |||
173 | /* | ||
174 | * SGTL5000_CHIP_ADCDAC_CTRL | ||
175 | */ | ||
176 | #define SGTL5000_VOL_BUSY_DAC_RIGHT 0x2000 | ||
177 | #define SGTL5000_VOL_BUSY_DAC_LEFT 0x1000 | ||
178 | #define SGTL5000_DAC_VOL_RAMP_EN 0x0200 | ||
179 | #define SGTL5000_DAC_VOL_RAMP_EXPO 0x0100 | ||
180 | #define SGTL5000_DAC_MUTE_RIGHT 0x0008 | ||
181 | #define SGTL5000_DAC_MUTE_LEFT 0x0004 | ||
182 | #define SGTL5000_ADC_HPF_FREEZE 0x0002 | ||
183 | #define SGTL5000_ADC_HPF_BYPASS 0x0001 | ||
184 | |||
185 | /* | ||
186 | * SGTL5000_CHIP_DAC_VOL | ||
187 | */ | ||
188 | #define SGTL5000_DAC_VOL_RIGHT_MASK 0xff00 | ||
189 | #define SGTL5000_DAC_VOL_RIGHT_SHIFT 8 | ||
190 | #define SGTL5000_DAC_VOL_RIGHT_WIDTH 8 | ||
191 | #define SGTL5000_DAC_VOL_LEFT_MASK 0x00ff | ||
192 | #define SGTL5000_DAC_VOL_LEFT_SHIFT 0 | ||
193 | #define SGTL5000_DAC_VOL_LEFT_WIDTH 8 | ||
194 | |||
195 | /* | ||
196 | * SGTL5000_CHIP_PAD_STRENGTH | ||
197 | */ | ||
198 | #define SGTL5000_PAD_I2S_LRCLK_MASK 0x0300 | ||
199 | #define SGTL5000_PAD_I2S_LRCLK_SHIFT 8 | ||
200 | #define SGTL5000_PAD_I2S_LRCLK_WIDTH 2 | ||
201 | #define SGTL5000_PAD_I2S_SCLK_MASK 0x00c0 | ||
202 | #define SGTL5000_PAD_I2S_SCLK_SHIFT 6 | ||
203 | #define SGTL5000_PAD_I2S_SCLK_WIDTH 2 | ||
204 | #define SGTL5000_PAD_I2S_DOUT_MASK 0x0030 | ||
205 | #define SGTL5000_PAD_I2S_DOUT_SHIFT 4 | ||
206 | #define SGTL5000_PAD_I2S_DOUT_WIDTH 2 | ||
207 | #define SGTL5000_PAD_I2C_SDA_MASK 0x000c | ||
208 | #define SGTL5000_PAD_I2C_SDA_SHIFT 2 | ||
209 | #define SGTL5000_PAD_I2C_SDA_WIDTH 2 | ||
210 | #define SGTL5000_PAD_I2C_SCL_MASK 0x0003 | ||
211 | #define SGTL5000_PAD_I2C_SCL_SHIFT 0 | ||
212 | #define SGTL5000_PAD_I2C_SCL_WIDTH 2 | ||
213 | |||
214 | /* | ||
215 | * SGTL5000_CHIP_ANA_ADC_CTRL | ||
216 | */ | ||
217 | #define SGTL5000_ADC_VOL_M6DB 0x0100 | ||
218 | #define SGTL5000_ADC_VOL_RIGHT_MASK 0x00f0 | ||
219 | #define SGTL5000_ADC_VOL_RIGHT_SHIFT 4 | ||
220 | #define SGTL5000_ADC_VOL_RIGHT_WIDTH 4 | ||
221 | #define SGTL5000_ADC_VOL_LEFT_MASK 0x000f | ||
222 | #define SGTL5000_ADC_VOL_LEFT_SHIFT 0 | ||
223 | #define SGTL5000_ADC_VOL_LEFT_WIDTH 4 | ||
224 | |||
225 | /* | ||
226 | * SGTL5000_CHIP_ANA_HP_CTRL | ||
227 | */ | ||
228 | #define SGTL5000_HP_VOL_RIGHT_MASK 0x7f00 | ||
229 | #define SGTL5000_HP_VOL_RIGHT_SHIFT 8 | ||
230 | #define SGTL5000_HP_VOL_RIGHT_WIDTH 7 | ||
231 | #define SGTL5000_HP_VOL_LEFT_MASK 0x007f | ||
232 | #define SGTL5000_HP_VOL_LEFT_SHIFT 0 | ||
233 | #define SGTL5000_HP_VOL_LEFT_WIDTH 7 | ||
234 | |||
235 | /* | ||
236 | * SGTL5000_CHIP_ANA_CTRL | ||
237 | */ | ||
238 | #define SGTL5000_LINE_OUT_MUTE 0x0100 | ||
239 | #define SGTL5000_HP_SEL_MASK 0x0040 | ||
240 | #define SGTL5000_HP_SEL_SHIFT 6 | ||
241 | #define SGTL5000_HP_SEL_WIDTH 1 | ||
242 | #define SGTL5000_HP_SEL_DAC 0x0 | ||
243 | #define SGTL5000_HP_SEL_LINE_IN 0x1 | ||
244 | #define SGTL5000_HP_ZCD_EN 0x0020 | ||
245 | #define SGTL5000_HP_MUTE 0x0010 | ||
246 | #define SGTL5000_ADC_SEL_MASK 0x0004 | ||
247 | #define SGTL5000_ADC_SEL_SHIFT 2 | ||
248 | #define SGTL5000_ADC_SEL_WIDTH 1 | ||
249 | #define SGTL5000_ADC_SEL_MIC 0x0 | ||
250 | #define SGTL5000_ADC_SEL_LINE_IN 0x1 | ||
251 | #define SGTL5000_ADC_ZCD_EN 0x0002 | ||
252 | #define SGTL5000_ADC_MUTE 0x0001 | ||
253 | |||
254 | /* | ||
255 | * SGTL5000_CHIP_LINREG_CTRL | ||
256 | */ | ||
257 | #define SGTL5000_VDDC_MAN_ASSN_MASK 0x0040 | ||
258 | #define SGTL5000_VDDC_MAN_ASSN_SHIFT 6 | ||
259 | #define SGTL5000_VDDC_MAN_ASSN_WIDTH 1 | ||
260 | #define SGTL5000_VDDC_MAN_ASSN_VDDA 0x0 | ||
261 | #define SGTL5000_VDDC_MAN_ASSN_VDDIO 0x1 | ||
262 | #define SGTL5000_VDDC_ASSN_OVRD 0x0020 | ||
263 | #define SGTL5000_LINREG_VDDD_MASK 0x000f | ||
264 | #define SGTL5000_LINREG_VDDD_SHIFT 0 | ||
265 | #define SGTL5000_LINREG_VDDD_WIDTH 4 | ||
266 | |||
267 | /* | ||
268 | * SGTL5000_CHIP_REF_CTRL | ||
269 | */ | ||
270 | #define SGTL5000_ANA_GND_MASK 0x01f0 | ||
271 | #define SGTL5000_ANA_GND_SHIFT 4 | ||
272 | #define SGTL5000_ANA_GND_WIDTH 5 | ||
273 | #define SGTL5000_ANA_GND_BASE 800 /* mv */ | ||
274 | #define SGTL5000_ANA_GND_STP 25 /*mv */ | ||
275 | #define SGTL5000_BIAS_CTRL_MASK 0x000e | ||
276 | #define SGTL5000_BIAS_CTRL_SHIFT 1 | ||
277 | #define SGTL5000_BIAS_CTRL_WIDTH 3 | ||
278 | #define SGTL5000_SMALL_POP 0x0001 | ||
279 | |||
280 | /* | ||
281 | * SGTL5000_CHIP_MIC_CTRL | ||
282 | */ | ||
283 | #define SGTL5000_BIAS_R_MASK 0x0200 | ||
284 | #define SGTL5000_BIAS_R_SHIFT 8 | ||
285 | #define SGTL5000_BIAS_R_WIDTH 2 | ||
286 | #define SGTL5000_BIAS_R_off 0x0 | ||
287 | #define SGTL5000_BIAS_R_2K 0x1 | ||
288 | #define SGTL5000_BIAS_R_4k 0x2 | ||
289 | #define SGTL5000_BIAS_R_8k 0x3 | ||
290 | #define SGTL5000_BIAS_VOLT_MASK 0x0070 | ||
291 | #define SGTL5000_BIAS_VOLT_SHIFT 4 | ||
292 | #define SGTL5000_BIAS_VOLT_WIDTH 3 | ||
293 | #define SGTL5000_MIC_GAIN_MASK 0x0003 | ||
294 | #define SGTL5000_MIC_GAIN_SHIFT 0 | ||
295 | #define SGTL5000_MIC_GAIN_WIDTH 2 | ||
296 | |||
297 | /* | ||
298 | * SGTL5000_CHIP_LINE_OUT_CTRL | ||
299 | */ | ||
300 | #define SGTL5000_LINE_OUT_CURRENT_MASK 0x0f00 | ||
301 | #define SGTL5000_LINE_OUT_CURRENT_SHIFT 8 | ||
302 | #define SGTL5000_LINE_OUT_CURRENT_WIDTH 4 | ||
303 | #define SGTL5000_LINE_OUT_CURRENT_180u 0x0 | ||
304 | #define SGTL5000_LINE_OUT_CURRENT_270u 0x1 | ||
305 | #define SGTL5000_LINE_OUT_CURRENT_360u 0x3 | ||
306 | #define SGTL5000_LINE_OUT_CURRENT_450u 0x7 | ||
307 | #define SGTL5000_LINE_OUT_CURRENT_540u 0xf | ||
308 | #define SGTL5000_LINE_OUT_GND_MASK 0x003f | ||
309 | #define SGTL5000_LINE_OUT_GND_SHIFT 0 | ||
310 | #define SGTL5000_LINE_OUT_GND_WIDTH 6 | ||
311 | #define SGTL5000_LINE_OUT_GND_BASE 800 /* mv */ | ||
312 | #define SGTL5000_LINE_OUT_GND_STP 25 | ||
313 | #define SGTL5000_LINE_OUT_GND_MAX 0x23 | ||
314 | |||
315 | /* | ||
316 | * SGTL5000_CHIP_LINE_OUT_VOL | ||
317 | */ | ||
318 | #define SGTL5000_LINE_OUT_VOL_RIGHT_MASK 0x1f00 | ||
319 | #define SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT 8 | ||
320 | #define SGTL5000_LINE_OUT_VOL_RIGHT_WIDTH 5 | ||
321 | #define SGTL5000_LINE_OUT_VOL_LEFT_MASK 0x001f | ||
322 | #define SGTL5000_LINE_OUT_VOL_LEFT_SHIFT 0 | ||
323 | #define SGTL5000_LINE_OUT_VOL_LEFT_WIDTH 5 | ||
324 | |||
325 | /* | ||
326 | * SGTL5000_CHIP_ANA_POWER | ||
327 | */ | ||
328 | #define SGTL5000_DAC_STEREO 0x4000 | ||
329 | #define SGTL5000_LINREG_SIMPLE_POWERUP 0x2000 | ||
330 | #define SGTL5000_STARTUP_POWERUP 0x1000 | ||
331 | #define SGTL5000_VDDC_CHRGPMP_POWERUP 0x0800 | ||
332 | #define SGTL5000_PLL_POWERUP 0x0400 | ||
333 | #define SGTL5000_LINEREG_D_POWERUP 0x0200 | ||
334 | #define SGTL5000_VCOAMP_POWERUP 0x0100 | ||
335 | #define SGTL5000_VAG_POWERUP 0x0080 | ||
336 | #define SGTL5000_ADC_STEREO 0x0040 | ||
337 | #define SGTL5000_REFTOP_POWERUP 0x0020 | ||
338 | #define SGTL5000_HP_POWERUP 0x0010 | ||
339 | #define SGTL5000_DAC_POWERUP 0x0008 | ||
340 | #define SGTL5000_CAPLESS_HP_POWERUP 0x0004 | ||
341 | #define SGTL5000_ADC_POWERUP 0x0002 | ||
342 | #define SGTL5000_LINE_OUT_POWERUP 0x0001 | ||
343 | |||
344 | /* | ||
345 | * SGTL5000_CHIP_PLL_CTRL | ||
346 | */ | ||
347 | #define SGTL5000_PLL_INT_DIV_MASK 0xf800 | ||
348 | #define SGTL5000_PLL_INT_DIV_SHIFT 11 | ||
349 | #define SGTL5000_PLL_INT_DIV_WIDTH 5 | ||
350 | #define SGTL5000_PLL_FRAC_DIV_MASK 0x0700 | ||
351 | #define SGTL5000_PLL_FRAC_DIV_SHIFT 0 | ||
352 | #define SGTL5000_PLL_FRAC_DIV_WIDTH 11 | ||
353 | |||
354 | /* | ||
355 | * SGTL5000_CHIP_CLK_TOP_CTRL | ||
356 | */ | ||
357 | #define SGTL5000_INT_OSC_EN 0x0800 | ||
358 | #define SGTL5000_INPUT_FREQ_DIV2 0x0008 | ||
359 | |||
360 | /* | ||
361 | * SGTL5000_CHIP_ANA_STATUS | ||
362 | */ | ||
363 | #define SGTL5000_HP_LRSHORT 0x0200 | ||
364 | #define SGTL5000_CAPLESS_SHORT 0x0100 | ||
365 | #define SGTL5000_PLL_LOCKED 0x0010 | ||
366 | |||
367 | /* | ||
368 | * SGTL5000_CHIP_SHORT_CTRL | ||
369 | */ | ||
370 | #define SGTL5000_LVLADJR_MASK 0x7000 | ||
371 | #define SGTL5000_LVLADJR_SHIFT 12 | ||
372 | #define SGTL5000_LVLADJR_WIDTH 3 | ||
373 | #define SGTL5000_LVLADJL_MASK 0x0700 | ||
374 | #define SGTL5000_LVLADJL_SHIFT 8 | ||
375 | #define SGTL5000_LVLADJL_WIDTH 3 | ||
376 | #define SGTL5000_LVLADJC_MASK 0x0070 | ||
377 | #define SGTL5000_LVLADJC_SHIFT 4 | ||
378 | #define SGTL5000_LVLADJC_WIDTH 3 | ||
379 | #define SGTL5000_LR_SHORT_MOD_MASK 0x000c | ||
380 | #define SGTL5000_LR_SHORT_MOD_SHIFT 2 | ||
381 | #define SGTL5000_LR_SHORT_MOD_WIDTH 2 | ||
382 | #define SGTL5000_CM_SHORT_MOD_MASK 0x0003 | ||
383 | #define SGTL5000_CM_SHORT_MOD_SHIFT 0 | ||
384 | #define SGTL5000_CM_SHORT_MOD_WIDTH 2 | ||
385 | |||
386 | /* | ||
387 | *SGTL5000_CHIP_ANA_TEST2 | ||
388 | */ | ||
389 | #define SGTL5000_MONO_DAC 0x1000 | ||
390 | |||
391 | /* | ||
392 | * SGTL5000_DAP_CTRL | ||
393 | */ | ||
394 | #define SGTL5000_DAP_MIX_EN 0x0010 | ||
395 | #define SGTL5000_DAP_EN 0x0001 | ||
396 | |||
397 | #define SGTL5000_SYSCLK 0x00 | ||
398 | #define SGTL5000_LRCLK 0x01 | ||
399 | |||
400 | #endif | ||
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c new file mode 100644 index 000000000000..2a30eae1881c --- /dev/null +++ b/sound/soc/codecs/sn95031.c | |||
@@ -0,0 +1,949 @@ | |||
1 | /* | ||
2 | * sn95031.c - TI sn95031 Codec driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Intel Corp | ||
5 | * Author: Vinod Koul <vinod.koul@intel.com> | ||
6 | * Author: Harsha Priya <priya.harsha@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program 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; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | * | ||
24 | * | ||
25 | */ | ||
26 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
27 | |||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <asm/intel_scu_ipc.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/soc-dapm.h> | ||
35 | #include <sound/initval.h> | ||
36 | #include <sound/tlv.h> | ||
37 | #include <sound/jack.h> | ||
38 | #include "sn95031.h" | ||
39 | |||
40 | #define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100) | ||
41 | #define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) | ||
42 | |||
43 | /* adc helper functions */ | ||
44 | |||
45 | /* enables mic bias voltage */ | ||
46 | static void sn95031_enable_mic_bias(struct snd_soc_codec *codec) | ||
47 | { | ||
48 | snd_soc_write(codec, SN95031_VAUD, BIT(2)|BIT(1)|BIT(0)); | ||
49 | snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(2), BIT(2)); | ||
50 | } | ||
51 | |||
52 | /* Enable/Disable the ADC depending on the argument */ | ||
53 | static void configure_adc(struct snd_soc_codec *sn95031_codec, int val) | ||
54 | { | ||
55 | int value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); | ||
56 | |||
57 | if (val) { | ||
58 | /* Enable and start the ADC */ | ||
59 | value |= (SN95031_ADC_ENBL | SN95031_ADC_START); | ||
60 | value &= (~SN95031_ADC_NO_LOOP); | ||
61 | } else { | ||
62 | /* Just stop the ADC */ | ||
63 | value &= (~SN95031_ADC_START); | ||
64 | } | ||
65 | snd_soc_write(sn95031_codec, SN95031_ADC1CNTL1, value); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * finds an empty channel for conversion | ||
70 | * If the ADC is not enabled then start using 0th channel | ||
71 | * itself. Otherwise find an empty channel by looking for a | ||
72 | * channel in which the stopbit is set to 1. returns the index | ||
73 | * of the first free channel if succeeds or an error code. | ||
74 | * | ||
75 | * Context: can sleep | ||
76 | * | ||
77 | */ | ||
78 | static int find_free_channel(struct snd_soc_codec *sn95031_codec) | ||
79 | { | ||
80 | int ret = 0, i, value; | ||
81 | |||
82 | /* check whether ADC is enabled */ | ||
83 | value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); | ||
84 | |||
85 | if ((value & SN95031_ADC_ENBL) == 0) | ||
86 | return 0; | ||
87 | |||
88 | /* ADC is already enabled; Looking for an empty channel */ | ||
89 | for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) { | ||
90 | value = snd_soc_read(sn95031_codec, | ||
91 | SN95031_ADC_CHNL_START_ADDR + i); | ||
92 | if (value & SN95031_STOPBIT_MASK) { | ||
93 | ret = i; | ||
94 | break; | ||
95 | } | ||
96 | } | ||
97 | return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret; | ||
98 | } | ||
99 | |||
100 | /* Initialize the ADC for reading micbias values. Can sleep. */ | ||
101 | static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec) | ||
102 | { | ||
103 | int base_addr, chnl_addr; | ||
104 | int value; | ||
105 | static int channel_index; | ||
106 | |||
107 | /* Index of the first channel in which the stop bit is set */ | ||
108 | channel_index = find_free_channel(sn95031_codec); | ||
109 | if (channel_index < 0) { | ||
110 | pr_err("No free ADC channels"); | ||
111 | return channel_index; | ||
112 | } | ||
113 | |||
114 | base_addr = SN95031_ADC_CHNL_START_ADDR + channel_index; | ||
115 | |||
116 | if (!(channel_index == 0 || channel_index == SN95031_ADC_LOOP_MAX)) { | ||
117 | /* Reset stop bit for channels other than 0 and 12 */ | ||
118 | value = snd_soc_read(sn95031_codec, base_addr); | ||
119 | /* Set the stop bit to zero */ | ||
120 | snd_soc_write(sn95031_codec, base_addr, value & 0xEF); | ||
121 | /* Index of the first free channel */ | ||
122 | base_addr++; | ||
123 | channel_index++; | ||
124 | } | ||
125 | |||
126 | /* Since this is the last channel, set the stop bit | ||
127 | to 1 by ORing the DIE_SENSOR_CODE with 0x10 */ | ||
128 | snd_soc_write(sn95031_codec, base_addr, | ||
129 | SN95031_AUDIO_DETECT_CODE | 0x10); | ||
130 | |||
131 | chnl_addr = SN95031_ADC_DATA_START_ADDR + 2 * channel_index; | ||
132 | pr_debug("mid_initialize : %x", chnl_addr); | ||
133 | configure_adc(sn95031_codec, 1); | ||
134 | return chnl_addr; | ||
135 | } | ||
136 | |||
137 | |||
138 | /* reads the ADC registers and gets the mic bias value in mV. */ | ||
139 | static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec) | ||
140 | { | ||
141 | u16 adc_adr = sn95031_initialize_adc(codec); | ||
142 | u16 adc_val1, adc_val2; | ||
143 | unsigned int mic_bias; | ||
144 | |||
145 | sn95031_enable_mic_bias(codec); | ||
146 | |||
147 | /* Enable the sound card for conversion before reading */ | ||
148 | snd_soc_write(codec, SN95031_ADC1CNTL3, 0x05); | ||
149 | /* Re-toggle the RRDATARD bit */ | ||
150 | snd_soc_write(codec, SN95031_ADC1CNTL3, 0x04); | ||
151 | |||
152 | /* Read the higher bits of data */ | ||
153 | msleep(1000); | ||
154 | adc_val1 = snd_soc_read(codec, adc_adr); | ||
155 | adc_adr++; | ||
156 | adc_val2 = snd_soc_read(codec, adc_adr); | ||
157 | |||
158 | /* Adding lower two bits to the higher bits */ | ||
159 | mic_bias = (adc_val1 << 2) + (adc_val2 & 3); | ||
160 | mic_bias = (mic_bias * SN95031_ADC_ONE_LSB_MULTIPLIER) / 1000; | ||
161 | pr_debug("mic bias = %dmV\n", mic_bias); | ||
162 | return mic_bias; | ||
163 | } | ||
164 | EXPORT_SYMBOL_GPL(sn95031_get_mic_bias); | ||
165 | /*end - adc helper functions */ | ||
166 | |||
167 | static inline unsigned int sn95031_read(struct snd_soc_codec *codec, | ||
168 | unsigned int reg) | ||
169 | { | ||
170 | u8 value = 0; | ||
171 | int ret; | ||
172 | |||
173 | ret = intel_scu_ipc_ioread8(reg, &value); | ||
174 | if (ret) | ||
175 | pr_err("read of %x failed, err %d\n", reg, ret); | ||
176 | return value; | ||
177 | |||
178 | } | ||
179 | |||
180 | static inline int sn95031_write(struct snd_soc_codec *codec, | ||
181 | unsigned int reg, unsigned int value) | ||
182 | { | ||
183 | int ret; | ||
184 | |||
185 | ret = intel_scu_ipc_iowrite8(reg, value); | ||
186 | if (ret) | ||
187 | pr_err("write of %x failed, err %d\n", reg, ret); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static int sn95031_set_vaud_bias(struct snd_soc_codec *codec, | ||
192 | enum snd_soc_bias_level level) | ||
193 | { | ||
194 | switch (level) { | ||
195 | case SND_SOC_BIAS_ON: | ||
196 | break; | ||
197 | |||
198 | case SND_SOC_BIAS_PREPARE: | ||
199 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | ||
200 | pr_debug("vaud_bias powering up pll\n"); | ||
201 | /* power up the pll */ | ||
202 | snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5)); | ||
203 | /* enable pcm 2 */ | ||
204 | snd_soc_update_bits(codec, SN95031_PCM2C2, | ||
205 | BIT(0), BIT(0)); | ||
206 | } | ||
207 | break; | ||
208 | |||
209 | case SND_SOC_BIAS_STANDBY: | ||
210 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
211 | pr_debug("vaud_bias power up rail\n"); | ||
212 | /* power up the rail */ | ||
213 | snd_soc_write(codec, SN95031_VAUD, | ||
214 | BIT(2)|BIT(1)|BIT(0)); | ||
215 | msleep(1); | ||
216 | } else if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { | ||
217 | /* turn off pcm */ | ||
218 | pr_debug("vaud_bias power dn pcm\n"); | ||
219 | snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0); | ||
220 | snd_soc_write(codec, SN95031_AUDPLLCTRL, 0); | ||
221 | } | ||
222 | break; | ||
223 | |||
224 | |||
225 | case SND_SOC_BIAS_OFF: | ||
226 | pr_debug("vaud_bias _OFF doing rail shutdown\n"); | ||
227 | snd_soc_write(codec, SN95031_VAUD, BIT(3)); | ||
228 | break; | ||
229 | } | ||
230 | |||
231 | codec->dapm.bias_level = level; | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static int sn95031_vhs_event(struct snd_soc_dapm_widget *w, | ||
236 | struct snd_kcontrol *kcontrol, int event) | ||
237 | { | ||
238 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
239 | pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); | ||
240 | /* power up the rail */ | ||
241 | snd_soc_write(w->codec, SN95031_VHSP, 0x3D); | ||
242 | snd_soc_write(w->codec, SN95031_VHSN, 0x3F); | ||
243 | msleep(1); | ||
244 | } else if (SND_SOC_DAPM_EVENT_OFF(event)) { | ||
245 | pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); | ||
246 | snd_soc_write(w->codec, SN95031_VHSP, 0xC4); | ||
247 | snd_soc_write(w->codec, SN95031_VHSN, 0x04); | ||
248 | } | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int sn95031_vihf_event(struct snd_soc_dapm_widget *w, | ||
253 | struct snd_kcontrol *kcontrol, int event) | ||
254 | { | ||
255 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
256 | pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n"); | ||
257 | /* power up the rail */ | ||
258 | snd_soc_write(w->codec, SN95031_VIHF, 0x27); | ||
259 | msleep(1); | ||
260 | } else if (SND_SOC_DAPM_EVENT_OFF(event)) { | ||
261 | pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n"); | ||
262 | snd_soc_write(w->codec, SN95031_VIHF, 0x24); | ||
263 | } | ||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w, | ||
268 | struct snd_kcontrol *k, int event) | ||
269 | { | ||
270 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; | ||
271 | |||
272 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
273 | ldo = BIT(5)|BIT(4); | ||
274 | clk_dir = BIT(0); | ||
275 | data_dir = BIT(7); | ||
276 | } | ||
277 | /* program DMIC LDO, clock and set clock */ | ||
278 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); | ||
279 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(0), clk_dir); | ||
280 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(7), data_dir); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w, | ||
285 | struct snd_kcontrol *k, int event) | ||
286 | { | ||
287 | unsigned int ldo = 0, clk_dir = 0, data_dir = 0; | ||
288 | |||
289 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
290 | ldo = BIT(5)|BIT(4); | ||
291 | clk_dir = BIT(2); | ||
292 | data_dir = BIT(1); | ||
293 | } | ||
294 | /* program DMIC LDO, clock and set clock */ | ||
295 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo); | ||
296 | snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(2), clk_dir); | ||
297 | snd_soc_update_bits(w->codec, SN95031_DMICBUF45, BIT(1), data_dir); | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w, | ||
302 | struct snd_kcontrol *k, int event) | ||
303 | { | ||
304 | unsigned int ldo = 0; | ||
305 | |||
306 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
307 | ldo = BIT(7)|BIT(6); | ||
308 | |||
309 | /* program DMIC LDO */ | ||
310 | snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo); | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | /* mux controls */ | ||
315 | static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" }; | ||
316 | |||
317 | static const struct soc_enum sn95031_micl_enum = | ||
318 | SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts); | ||
319 | |||
320 | static const struct snd_kcontrol_new sn95031_micl_mux_control = | ||
321 | SOC_DAPM_ENUM("Route", sn95031_micl_enum); | ||
322 | |||
323 | static const struct soc_enum sn95031_micr_enum = | ||
324 | SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts); | ||
325 | |||
326 | static const struct snd_kcontrol_new sn95031_micr_mux_control = | ||
327 | SOC_DAPM_ENUM("Route", sn95031_micr_enum); | ||
328 | |||
329 | static const char *sn95031_input_texts[] = { "DMIC1", "DMIC2", "DMIC3", | ||
330 | "DMIC4", "DMIC5", "DMIC6", | ||
331 | "ADC Left", "ADC Right" }; | ||
332 | |||
333 | static const struct soc_enum sn95031_input1_enum = | ||
334 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts); | ||
335 | |||
336 | static const struct snd_kcontrol_new sn95031_input1_mux_control = | ||
337 | SOC_DAPM_ENUM("Route", sn95031_input1_enum); | ||
338 | |||
339 | static const struct soc_enum sn95031_input2_enum = | ||
340 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts); | ||
341 | |||
342 | static const struct snd_kcontrol_new sn95031_input2_mux_control = | ||
343 | SOC_DAPM_ENUM("Route", sn95031_input2_enum); | ||
344 | |||
345 | static const struct soc_enum sn95031_input3_enum = | ||
346 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts); | ||
347 | |||
348 | static const struct snd_kcontrol_new sn95031_input3_mux_control = | ||
349 | SOC_DAPM_ENUM("Route", sn95031_input3_enum); | ||
350 | |||
351 | static const struct soc_enum sn95031_input4_enum = | ||
352 | SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts); | ||
353 | |||
354 | static const struct snd_kcontrol_new sn95031_input4_mux_control = | ||
355 | SOC_DAPM_ENUM("Route", sn95031_input4_enum); | ||
356 | |||
357 | /* capture path controls */ | ||
358 | |||
359 | static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"}; | ||
360 | |||
361 | /* 0dB to 30dB in 10dB steps */ | ||
362 | static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0); | ||
363 | |||
364 | static const struct soc_enum sn95031_micmode1_enum = | ||
365 | SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text); | ||
366 | static const struct soc_enum sn95031_micmode2_enum = | ||
367 | SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text); | ||
368 | |||
369 | static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"}; | ||
370 | |||
371 | static const struct soc_enum sn95031_dmic12_cfg_enum = | ||
372 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text); | ||
373 | static const struct soc_enum sn95031_dmic34_cfg_enum = | ||
374 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text); | ||
375 | static const struct soc_enum sn95031_dmic56_cfg_enum = | ||
376 | SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text); | ||
377 | |||
378 | static const struct snd_kcontrol_new sn95031_snd_controls[] = { | ||
379 | SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum), | ||
380 | SOC_ENUM("Mic2Mode Capture Route", sn95031_micmode2_enum), | ||
381 | SOC_ENUM("DMIC12 Capture Route", sn95031_dmic12_cfg_enum), | ||
382 | SOC_ENUM("DMIC34 Capture Route", sn95031_dmic34_cfg_enum), | ||
383 | SOC_ENUM("DMIC56 Capture Route", sn95031_dmic56_cfg_enum), | ||
384 | SOC_SINGLE_TLV("Mic1 Capture Volume", SN95031_MICAMP1, | ||
385 | 2, 4, 0, mic_tlv), | ||
386 | SOC_SINGLE_TLV("Mic2 Capture Volume", SN95031_MICAMP2, | ||
387 | 2, 4, 0, mic_tlv), | ||
388 | }; | ||
389 | |||
390 | /* DAPM widgets */ | ||
391 | static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = { | ||
392 | |||
393 | /* all end points mic, hs etc */ | ||
394 | SND_SOC_DAPM_OUTPUT("HPOUTL"), | ||
395 | SND_SOC_DAPM_OUTPUT("HPOUTR"), | ||
396 | SND_SOC_DAPM_OUTPUT("EPOUT"), | ||
397 | SND_SOC_DAPM_OUTPUT("IHFOUTL"), | ||
398 | SND_SOC_DAPM_OUTPUT("IHFOUTR"), | ||
399 | SND_SOC_DAPM_OUTPUT("LINEOUTL"), | ||
400 | SND_SOC_DAPM_OUTPUT("LINEOUTR"), | ||
401 | SND_SOC_DAPM_OUTPUT("VIB1OUT"), | ||
402 | SND_SOC_DAPM_OUTPUT("VIB2OUT"), | ||
403 | |||
404 | SND_SOC_DAPM_INPUT("AMIC1"), /* headset mic */ | ||
405 | SND_SOC_DAPM_INPUT("AMIC2"), | ||
406 | SND_SOC_DAPM_INPUT("DMIC1"), | ||
407 | SND_SOC_DAPM_INPUT("DMIC2"), | ||
408 | SND_SOC_DAPM_INPUT("DMIC3"), | ||
409 | SND_SOC_DAPM_INPUT("DMIC4"), | ||
410 | SND_SOC_DAPM_INPUT("DMIC5"), | ||
411 | SND_SOC_DAPM_INPUT("DMIC6"), | ||
412 | SND_SOC_DAPM_INPUT("LINEINL"), | ||
413 | SND_SOC_DAPM_INPUT("LINEINR"), | ||
414 | |||
415 | SND_SOC_DAPM_MICBIAS("AMIC1Bias", SN95031_MICBIAS, 2, 0), | ||
416 | SND_SOC_DAPM_MICBIAS("AMIC2Bias", SN95031_MICBIAS, 3, 0), | ||
417 | SND_SOC_DAPM_MICBIAS("DMIC12Bias", SN95031_DMICMUX, 3, 0), | ||
418 | SND_SOC_DAPM_MICBIAS("DMIC34Bias", SN95031_DMICMUX, 4, 0), | ||
419 | SND_SOC_DAPM_MICBIAS("DMIC56Bias", SN95031_DMICMUX, 5, 0), | ||
420 | |||
421 | SND_SOC_DAPM_SUPPLY("DMIC12supply", SN95031_DMICLK, 0, 0, | ||
422 | sn95031_dmic12_event, | ||
423 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
424 | SND_SOC_DAPM_SUPPLY("DMIC34supply", SN95031_DMICLK, 1, 0, | ||
425 | sn95031_dmic34_event, | ||
426 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
427 | SND_SOC_DAPM_SUPPLY("DMIC56supply", SN95031_DMICLK, 2, 0, | ||
428 | sn95031_dmic56_event, | ||
429 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
430 | |||
431 | SND_SOC_DAPM_AIF_OUT("PCM_Out", "Capture", 0, | ||
432 | SND_SOC_NOPM, 0, 0), | ||
433 | |||
434 | SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0, | ||
435 | sn95031_vhs_event, | ||
436 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
437 | SND_SOC_DAPM_SUPPLY("Speaker Rail", SND_SOC_NOPM, 0, 0, | ||
438 | sn95031_vihf_event, | ||
439 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
440 | |||
441 | /* playback path driver enables */ | ||
442 | SND_SOC_DAPM_PGA("Headset Left Playback", | ||
443 | SN95031_DRIVEREN, 0, 0, NULL, 0), | ||
444 | SND_SOC_DAPM_PGA("Headset Right Playback", | ||
445 | SN95031_DRIVEREN, 1, 0, NULL, 0), | ||
446 | SND_SOC_DAPM_PGA("Speaker Left Playback", | ||
447 | SN95031_DRIVEREN, 2, 0, NULL, 0), | ||
448 | SND_SOC_DAPM_PGA("Speaker Right Playback", | ||
449 | SN95031_DRIVEREN, 3, 0, NULL, 0), | ||
450 | SND_SOC_DAPM_PGA("Vibra1 Playback", | ||
451 | SN95031_DRIVEREN, 4, 0, NULL, 0), | ||
452 | SND_SOC_DAPM_PGA("Vibra2 Playback", | ||
453 | SN95031_DRIVEREN, 5, 0, NULL, 0), | ||
454 | SND_SOC_DAPM_PGA("Earpiece Playback", | ||
455 | SN95031_DRIVEREN, 6, 0, NULL, 0), | ||
456 | SND_SOC_DAPM_PGA("Lineout Left Playback", | ||
457 | SN95031_LOCTL, 0, 0, NULL, 0), | ||
458 | SND_SOC_DAPM_PGA("Lineout Right Playback", | ||
459 | SN95031_LOCTL, 4, 0, NULL, 0), | ||
460 | |||
461 | /* playback path filter enable */ | ||
462 | SND_SOC_DAPM_PGA("Headset Left Filter", | ||
463 | SN95031_HSEPRXCTRL, 4, 0, NULL, 0), | ||
464 | SND_SOC_DAPM_PGA("Headset Right Filter", | ||
465 | SN95031_HSEPRXCTRL, 5, 0, NULL, 0), | ||
466 | SND_SOC_DAPM_PGA("Speaker Left Filter", | ||
467 | SN95031_IHFRXCTRL, 0, 0, NULL, 0), | ||
468 | SND_SOC_DAPM_PGA("Speaker Right Filter", | ||
469 | SN95031_IHFRXCTRL, 1, 0, NULL, 0), | ||
470 | |||
471 | /* DACs */ | ||
472 | SND_SOC_DAPM_DAC("HSDAC Left", "Headset", | ||
473 | SN95031_DACCONFIG, 0, 0), | ||
474 | SND_SOC_DAPM_DAC("HSDAC Right", "Headset", | ||
475 | SN95031_DACCONFIG, 1, 0), | ||
476 | SND_SOC_DAPM_DAC("IHFDAC Left", "Speaker", | ||
477 | SN95031_DACCONFIG, 2, 0), | ||
478 | SND_SOC_DAPM_DAC("IHFDAC Right", "Speaker", | ||
479 | SN95031_DACCONFIG, 3, 0), | ||
480 | SND_SOC_DAPM_DAC("Vibra1 DAC", "Vibra1", | ||
481 | SN95031_VIB1C5, 1, 0), | ||
482 | SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2", | ||
483 | SN95031_VIB2C5, 1, 0), | ||
484 | |||
485 | /* capture widgets */ | ||
486 | SND_SOC_DAPM_PGA("LineIn Enable Left", SN95031_MICAMP1, | ||
487 | 7, 0, NULL, 0), | ||
488 | SND_SOC_DAPM_PGA("LineIn Enable Right", SN95031_MICAMP2, | ||
489 | 7, 0, NULL, 0), | ||
490 | |||
491 | SND_SOC_DAPM_PGA("MIC1 Enable", SN95031_MICAMP1, 0, 0, NULL, 0), | ||
492 | SND_SOC_DAPM_PGA("MIC2 Enable", SN95031_MICAMP2, 0, 0, NULL, 0), | ||
493 | SND_SOC_DAPM_PGA("TX1 Enable", SN95031_AUDIOTXEN, 2, 0, NULL, 0), | ||
494 | SND_SOC_DAPM_PGA("TX2 Enable", SN95031_AUDIOTXEN, 3, 0, NULL, 0), | ||
495 | SND_SOC_DAPM_PGA("TX3 Enable", SN95031_AUDIOTXEN, 4, 0, NULL, 0), | ||
496 | SND_SOC_DAPM_PGA("TX4 Enable", SN95031_AUDIOTXEN, 5, 0, NULL, 0), | ||
497 | |||
498 | /* ADC have null stream as they will be turned ON by TX path */ | ||
499 | SND_SOC_DAPM_ADC("ADC Left", NULL, | ||
500 | SN95031_ADCCONFIG, 0, 0), | ||
501 | SND_SOC_DAPM_ADC("ADC Right", NULL, | ||
502 | SN95031_ADCCONFIG, 2, 0), | ||
503 | |||
504 | SND_SOC_DAPM_MUX("Mic_InputL Capture Route", | ||
505 | SND_SOC_NOPM, 0, 0, &sn95031_micl_mux_control), | ||
506 | SND_SOC_DAPM_MUX("Mic_InputR Capture Route", | ||
507 | SND_SOC_NOPM, 0, 0, &sn95031_micr_mux_control), | ||
508 | |||
509 | SND_SOC_DAPM_MUX("Txpath1 Capture Route", | ||
510 | SND_SOC_NOPM, 0, 0, &sn95031_input1_mux_control), | ||
511 | SND_SOC_DAPM_MUX("Txpath2 Capture Route", | ||
512 | SND_SOC_NOPM, 0, 0, &sn95031_input2_mux_control), | ||
513 | SND_SOC_DAPM_MUX("Txpath3 Capture Route", | ||
514 | SND_SOC_NOPM, 0, 0, &sn95031_input3_mux_control), | ||
515 | SND_SOC_DAPM_MUX("Txpath4 Capture Route", | ||
516 | SND_SOC_NOPM, 0, 0, &sn95031_input4_mux_control), | ||
517 | |||
518 | }; | ||
519 | |||
520 | static const struct snd_soc_dapm_route sn95031_audio_map[] = { | ||
521 | /* headset and earpiece map */ | ||
522 | { "HPOUTL", NULL, "Headset Rail"}, | ||
523 | { "HPOUTR", NULL, "Headset Rail"}, | ||
524 | { "HPOUTL", NULL, "Headset Left Playback" }, | ||
525 | { "HPOUTR", NULL, "Headset Right Playback" }, | ||
526 | { "EPOUT", NULL, "Earpiece Playback" }, | ||
527 | { "Headset Left Playback", NULL, "Headset Left Filter"}, | ||
528 | { "Headset Right Playback", NULL, "Headset Right Filter"}, | ||
529 | { "Earpiece Playback", NULL, "Headset Left Filter"}, | ||
530 | { "Headset Left Filter", NULL, "HSDAC Left"}, | ||
531 | { "Headset Right Filter", NULL, "HSDAC Right"}, | ||
532 | |||
533 | /* speaker map */ | ||
534 | { "IHFOUTL", NULL, "Speaker Rail"}, | ||
535 | { "IHFOUTR", NULL, "Speaker Rail"}, | ||
536 | { "IHFOUTL", "NULL", "Speaker Left Playback"}, | ||
537 | { "IHFOUTR", "NULL", "Speaker Right Playback"}, | ||
538 | { "Speaker Left Playback", NULL, "Speaker Left Filter"}, | ||
539 | { "Speaker Right Playback", NULL, "Speaker Right Filter"}, | ||
540 | { "Speaker Left Filter", NULL, "IHFDAC Left"}, | ||
541 | { "Speaker Right Filter", NULL, "IHFDAC Right"}, | ||
542 | |||
543 | /* vibra map */ | ||
544 | { "VIB1OUT", NULL, "Vibra1 Playback"}, | ||
545 | { "Vibra1 Playback", NULL, "Vibra1 DAC"}, | ||
546 | |||
547 | { "VIB2OUT", NULL, "Vibra2 Playback"}, | ||
548 | { "Vibra2 Playback", NULL, "Vibra2 DAC"}, | ||
549 | |||
550 | /* lineout */ | ||
551 | { "LINEOUTL", NULL, "Lineout Left Playback"}, | ||
552 | { "LINEOUTR", NULL, "Lineout Right Playback"}, | ||
553 | { "Lineout Left Playback", NULL, "Headset Left Filter"}, | ||
554 | { "Lineout Left Playback", NULL, "Speaker Left Filter"}, | ||
555 | { "Lineout Left Playback", NULL, "Vibra1 DAC"}, | ||
556 | { "Lineout Right Playback", NULL, "Headset Right Filter"}, | ||
557 | { "Lineout Right Playback", NULL, "Speaker Right Filter"}, | ||
558 | { "Lineout Right Playback", NULL, "Vibra2 DAC"}, | ||
559 | |||
560 | /* Headset (AMIC1) mic */ | ||
561 | { "AMIC1Bias", NULL, "AMIC1"}, | ||
562 | { "MIC1 Enable", NULL, "AMIC1Bias"}, | ||
563 | { "Mic_InputL Capture Route", "AMIC", "MIC1 Enable"}, | ||
564 | |||
565 | /* AMIC2 */ | ||
566 | { "AMIC2Bias", NULL, "AMIC2"}, | ||
567 | { "MIC2 Enable", NULL, "AMIC2Bias"}, | ||
568 | { "Mic_InputR Capture Route", "AMIC", "MIC2 Enable"}, | ||
569 | |||
570 | |||
571 | /* Linein */ | ||
572 | { "LineIn Enable Left", NULL, "LINEINL"}, | ||
573 | { "LineIn Enable Right", NULL, "LINEINR"}, | ||
574 | { "Mic_InputL Capture Route", "LineIn", "LineIn Enable Left"}, | ||
575 | { "Mic_InputR Capture Route", "LineIn", "LineIn Enable Right"}, | ||
576 | |||
577 | /* ADC connection */ | ||
578 | { "ADC Left", NULL, "Mic_InputL Capture Route"}, | ||
579 | { "ADC Right", NULL, "Mic_InputR Capture Route"}, | ||
580 | |||
581 | /*DMIC connections */ | ||
582 | { "DMIC1", NULL, "DMIC12supply"}, | ||
583 | { "DMIC2", NULL, "DMIC12supply"}, | ||
584 | { "DMIC3", NULL, "DMIC34supply"}, | ||
585 | { "DMIC4", NULL, "DMIC34supply"}, | ||
586 | { "DMIC5", NULL, "DMIC56supply"}, | ||
587 | { "DMIC6", NULL, "DMIC56supply"}, | ||
588 | |||
589 | { "DMIC12Bias", NULL, "DMIC1"}, | ||
590 | { "DMIC12Bias", NULL, "DMIC2"}, | ||
591 | { "DMIC34Bias", NULL, "DMIC3"}, | ||
592 | { "DMIC34Bias", NULL, "DMIC4"}, | ||
593 | { "DMIC56Bias", NULL, "DMIC5"}, | ||
594 | { "DMIC56Bias", NULL, "DMIC6"}, | ||
595 | |||
596 | /*TX path inputs*/ | ||
597 | { "Txpath1 Capture Route", "ADC Left", "ADC Left"}, | ||
598 | { "Txpath2 Capture Route", "ADC Left", "ADC Left"}, | ||
599 | { "Txpath3 Capture Route", "ADC Left", "ADC Left"}, | ||
600 | { "Txpath4 Capture Route", "ADC Left", "ADC Left"}, | ||
601 | { "Txpath1 Capture Route", "ADC Right", "ADC Right"}, | ||
602 | { "Txpath2 Capture Route", "ADC Right", "ADC Right"}, | ||
603 | { "Txpath3 Capture Route", "ADC Right", "ADC Right"}, | ||
604 | { "Txpath4 Capture Route", "ADC Right", "ADC Right"}, | ||
605 | { "Txpath1 Capture Route", "DMIC1", "DMIC1"}, | ||
606 | { "Txpath2 Capture Route", "DMIC1", "DMIC1"}, | ||
607 | { "Txpath3 Capture Route", "DMIC1", "DMIC1"}, | ||
608 | { "Txpath4 Capture Route", "DMIC1", "DMIC1"}, | ||
609 | { "Txpath1 Capture Route", "DMIC2", "DMIC2"}, | ||
610 | { "Txpath2 Capture Route", "DMIC2", "DMIC2"}, | ||
611 | { "Txpath3 Capture Route", "DMIC2", "DMIC2"}, | ||
612 | { "Txpath4 Capture Route", "DMIC2", "DMIC2"}, | ||
613 | { "Txpath1 Capture Route", "DMIC3", "DMIC3"}, | ||
614 | { "Txpath2 Capture Route", "DMIC3", "DMIC3"}, | ||
615 | { "Txpath3 Capture Route", "DMIC3", "DMIC3"}, | ||
616 | { "Txpath4 Capture Route", "DMIC3", "DMIC3"}, | ||
617 | { "Txpath1 Capture Route", "DMIC4", "DMIC4"}, | ||
618 | { "Txpath2 Capture Route", "DMIC4", "DMIC4"}, | ||
619 | { "Txpath3 Capture Route", "DMIC4", "DMIC4"}, | ||
620 | { "Txpath4 Capture Route", "DMIC4", "DMIC4"}, | ||
621 | { "Txpath1 Capture Route", "DMIC5", "DMIC5"}, | ||
622 | { "Txpath2 Capture Route", "DMIC5", "DMIC5"}, | ||
623 | { "Txpath3 Capture Route", "DMIC5", "DMIC5"}, | ||
624 | { "Txpath4 Capture Route", "DMIC5", "DMIC5"}, | ||
625 | { "Txpath1 Capture Route", "DMIC6", "DMIC6"}, | ||
626 | { "Txpath2 Capture Route", "DMIC6", "DMIC6"}, | ||
627 | { "Txpath3 Capture Route", "DMIC6", "DMIC6"}, | ||
628 | { "Txpath4 Capture Route", "DMIC6", "DMIC6"}, | ||
629 | |||
630 | /* tx path */ | ||
631 | { "TX1 Enable", NULL, "Txpath1 Capture Route"}, | ||
632 | { "TX2 Enable", NULL, "Txpath2 Capture Route"}, | ||
633 | { "TX3 Enable", NULL, "Txpath3 Capture Route"}, | ||
634 | { "TX4 Enable", NULL, "Txpath4 Capture Route"}, | ||
635 | { "PCM_Out", NULL, "TX1 Enable"}, | ||
636 | { "PCM_Out", NULL, "TX2 Enable"}, | ||
637 | { "PCM_Out", NULL, "TX3 Enable"}, | ||
638 | { "PCM_Out", NULL, "TX4 Enable"}, | ||
639 | |||
640 | }; | ||
641 | |||
642 | /* speaker and headset mutes, for audio pops and clicks */ | ||
643 | static int sn95031_pcm_hs_mute(struct snd_soc_dai *dai, int mute) | ||
644 | { | ||
645 | snd_soc_update_bits(dai->codec, | ||
646 | SN95031_HSLVOLCTRL, BIT(7), (!mute << 7)); | ||
647 | snd_soc_update_bits(dai->codec, | ||
648 | SN95031_HSRVOLCTRL, BIT(7), (!mute << 7)); | ||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute) | ||
653 | { | ||
654 | snd_soc_update_bits(dai->codec, | ||
655 | SN95031_IHFLVOLCTRL, BIT(7), (!mute << 7)); | ||
656 | snd_soc_update_bits(dai->codec, | ||
657 | SN95031_IHFRVOLCTRL, BIT(7), (!mute << 7)); | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, | ||
662 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
663 | { | ||
664 | unsigned int format, rate; | ||
665 | |||
666 | switch (params_format(params)) { | ||
667 | case SNDRV_PCM_FORMAT_S16_LE: | ||
668 | format = BIT(4)|BIT(5); | ||
669 | break; | ||
670 | |||
671 | case SNDRV_PCM_FORMAT_S24_LE: | ||
672 | format = 0; | ||
673 | break; | ||
674 | default: | ||
675 | return -EINVAL; | ||
676 | } | ||
677 | snd_soc_update_bits(dai->codec, SN95031_PCM2C2, | ||
678 | BIT(4)|BIT(5), format); | ||
679 | |||
680 | switch (params_rate(params)) { | ||
681 | case 48000: | ||
682 | pr_debug("RATE_48000\n"); | ||
683 | rate = 0; | ||
684 | break; | ||
685 | |||
686 | case 44100: | ||
687 | pr_debug("RATE_44100\n"); | ||
688 | rate = BIT(7); | ||
689 | break; | ||
690 | |||
691 | default: | ||
692 | pr_err("ERR rate %d\n", params_rate(params)); | ||
693 | return -EINVAL; | ||
694 | } | ||
695 | snd_soc_update_bits(dai->codec, SN95031_PCM1C1, BIT(7), rate); | ||
696 | |||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | /* Codec DAI section */ | ||
701 | static struct snd_soc_dai_ops sn95031_headset_dai_ops = { | ||
702 | .digital_mute = sn95031_pcm_hs_mute, | ||
703 | .hw_params = sn95031_pcm_hw_params, | ||
704 | }; | ||
705 | |||
706 | static struct snd_soc_dai_ops sn95031_speaker_dai_ops = { | ||
707 | .digital_mute = sn95031_pcm_spkr_mute, | ||
708 | .hw_params = sn95031_pcm_hw_params, | ||
709 | }; | ||
710 | |||
711 | static struct snd_soc_dai_ops sn95031_vib1_dai_ops = { | ||
712 | .hw_params = sn95031_pcm_hw_params, | ||
713 | }; | ||
714 | |||
715 | static struct snd_soc_dai_ops sn95031_vib2_dai_ops = { | ||
716 | .hw_params = sn95031_pcm_hw_params, | ||
717 | }; | ||
718 | |||
719 | struct snd_soc_dai_driver sn95031_dais[] = { | ||
720 | { | ||
721 | .name = "SN95031 Headset", | ||
722 | .playback = { | ||
723 | .stream_name = "Headset", | ||
724 | .channels_min = 2, | ||
725 | .channels_max = 2, | ||
726 | .rates = SN95031_RATES, | ||
727 | .formats = SN95031_FORMATS, | ||
728 | }, | ||
729 | .capture = { | ||
730 | .stream_name = "Capture", | ||
731 | .channels_min = 1, | ||
732 | .channels_max = 5, | ||
733 | .rates = SN95031_RATES, | ||
734 | .formats = SN95031_FORMATS, | ||
735 | }, | ||
736 | .ops = &sn95031_headset_dai_ops, | ||
737 | }, | ||
738 | { .name = "SN95031 Speaker", | ||
739 | .playback = { | ||
740 | .stream_name = "Speaker", | ||
741 | .channels_min = 2, | ||
742 | .channels_max = 2, | ||
743 | .rates = SN95031_RATES, | ||
744 | .formats = SN95031_FORMATS, | ||
745 | }, | ||
746 | .ops = &sn95031_speaker_dai_ops, | ||
747 | }, | ||
748 | { .name = "SN95031 Vibra1", | ||
749 | .playback = { | ||
750 | .stream_name = "Vibra1", | ||
751 | .channels_min = 1, | ||
752 | .channels_max = 1, | ||
753 | .rates = SN95031_RATES, | ||
754 | .formats = SN95031_FORMATS, | ||
755 | }, | ||
756 | .ops = &sn95031_vib1_dai_ops, | ||
757 | }, | ||
758 | { .name = "SN95031 Vibra2", | ||
759 | .playback = { | ||
760 | .stream_name = "Vibra2", | ||
761 | .channels_min = 1, | ||
762 | .channels_max = 1, | ||
763 | .rates = SN95031_RATES, | ||
764 | .formats = SN95031_FORMATS, | ||
765 | }, | ||
766 | .ops = &sn95031_vib2_dai_ops, | ||
767 | }, | ||
768 | }; | ||
769 | |||
770 | static inline void sn95031_disable_jack_btn(struct snd_soc_codec *codec) | ||
771 | { | ||
772 | snd_soc_write(codec, SN95031_BTNCTRL2, 0x00); | ||
773 | } | ||
774 | |||
775 | static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec) | ||
776 | { | ||
777 | snd_soc_write(codec, SN95031_BTNCTRL1, 0x77); | ||
778 | snd_soc_write(codec, SN95031_BTNCTRL2, 0x01); | ||
779 | } | ||
780 | |||
781 | static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack) | ||
782 | { | ||
783 | int micbias = sn95031_get_mic_bias(mfld_jack->codec); | ||
784 | |||
785 | int jack_type = snd_soc_jack_get_type(mfld_jack, micbias); | ||
786 | |||
787 | pr_debug("jack type detected = %d\n", jack_type); | ||
788 | if (jack_type == SND_JACK_HEADSET) | ||
789 | sn95031_enable_jack_btn(mfld_jack->codec); | ||
790 | return jack_type; | ||
791 | } | ||
792 | |||
793 | void sn95031_jack_detection(struct mfld_jack_data *jack_data) | ||
794 | { | ||
795 | unsigned int status; | ||
796 | unsigned int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET; | ||
797 | |||
798 | pr_debug("interrupt id read in sram = 0x%x\n", jack_data->intr_id); | ||
799 | if (jack_data->intr_id & 0x1) { | ||
800 | pr_debug("short_push detected\n"); | ||
801 | status = SND_JACK_HEADSET | SND_JACK_BTN_0; | ||
802 | } else if (jack_data->intr_id & 0x2) { | ||
803 | pr_debug("long_push detected\n"); | ||
804 | status = SND_JACK_HEADSET | SND_JACK_BTN_1; | ||
805 | } else if (jack_data->intr_id & 0x4) { | ||
806 | pr_debug("headset or headphones inserted\n"); | ||
807 | status = sn95031_get_headset_state(jack_data->mfld_jack); | ||
808 | } else if (jack_data->intr_id & 0x8) { | ||
809 | pr_debug("headset or headphones removed\n"); | ||
810 | status = 0; | ||
811 | sn95031_disable_jack_btn(jack_data->mfld_jack->codec); | ||
812 | } else { | ||
813 | pr_err("unidentified interrupt\n"); | ||
814 | return; | ||
815 | } | ||
816 | |||
817 | snd_soc_jack_report(jack_data->mfld_jack, status, mask); | ||
818 | /*button pressed and released so we send explicit button release */ | ||
819 | if ((status & SND_JACK_BTN_0) | (status & SND_JACK_BTN_1)) | ||
820 | snd_soc_jack_report(jack_data->mfld_jack, | ||
821 | SND_JACK_HEADSET, mask); | ||
822 | } | ||
823 | EXPORT_SYMBOL_GPL(sn95031_jack_detection); | ||
824 | |||
825 | /* codec registration */ | ||
826 | static int sn95031_codec_probe(struct snd_soc_codec *codec) | ||
827 | { | ||
828 | int ret; | ||
829 | |||
830 | pr_debug("codec_probe called\n"); | ||
831 | |||
832 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | ||
833 | codec->dapm.idle_bias_off = 1; | ||
834 | |||
835 | /* PCM interface config | ||
836 | * This sets the pcm rx slot conguration to max 6 slots | ||
837 | * for max 4 dais (2 stereo and 2 mono) | ||
838 | */ | ||
839 | snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10); | ||
840 | snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32); | ||
841 | snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54); | ||
842 | snd_soc_write(codec, SN95031_PCM2TXSLOT01, 0x10); | ||
843 | snd_soc_write(codec, SN95031_PCM2TXSLOT23, 0x32); | ||
844 | /* pcm port setting | ||
845 | * This sets the pcm port to slave and clock at 19.2Mhz which | ||
846 | * can support 6slots, sampling rate set per stream in hw-params | ||
847 | */ | ||
848 | snd_soc_write(codec, SN95031_PCM1C1, 0x00); | ||
849 | snd_soc_write(codec, SN95031_PCM2C1, 0x01); | ||
850 | snd_soc_write(codec, SN95031_PCM2C2, 0x0A); | ||
851 | snd_soc_write(codec, SN95031_HSMIXER, BIT(0)|BIT(4)); | ||
852 | /* vendor vibra workround, the vibras are muted by | ||
853 | * custom register so unmute them | ||
854 | */ | ||
855 | snd_soc_write(codec, SN95031_SSR5, 0x80); | ||
856 | snd_soc_write(codec, SN95031_SSR6, 0x80); | ||
857 | snd_soc_write(codec, SN95031_VIB1C5, 0x00); | ||
858 | snd_soc_write(codec, SN95031_VIB2C5, 0x00); | ||
859 | /* configure vibras for pcm port */ | ||
860 | snd_soc_write(codec, SN95031_VIB1C3, 0x00); | ||
861 | snd_soc_write(codec, SN95031_VIB2C3, 0x00); | ||
862 | |||
863 | /* soft mute ramp time */ | ||
864 | snd_soc_write(codec, SN95031_SOFTMUTE, 0x3); | ||
865 | /* fix the initial volume at 1dB, | ||
866 | * default in +9dB, | ||
867 | * 1dB give optimal swing on DAC, amps | ||
868 | */ | ||
869 | snd_soc_write(codec, SN95031_HSLVOLCTRL, 0x08); | ||
870 | snd_soc_write(codec, SN95031_HSRVOLCTRL, 0x08); | ||
871 | snd_soc_write(codec, SN95031_IHFLVOLCTRL, 0x08); | ||
872 | snd_soc_write(codec, SN95031_IHFRVOLCTRL, 0x08); | ||
873 | /* dac mode and lineout workaround */ | ||
874 | snd_soc_write(codec, SN95031_SSR2, 0x10); | ||
875 | snd_soc_write(codec, SN95031_SSR3, 0x40); | ||
876 | |||
877 | snd_soc_add_controls(codec, sn95031_snd_controls, | ||
878 | ARRAY_SIZE(sn95031_snd_controls)); | ||
879 | |||
880 | ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets, | ||
881 | ARRAY_SIZE(sn95031_dapm_widgets)); | ||
882 | if (ret) | ||
883 | pr_err("soc_dapm_new_control failed %d", ret); | ||
884 | ret = snd_soc_dapm_add_routes(&codec->dapm, sn95031_audio_map, | ||
885 | ARRAY_SIZE(sn95031_audio_map)); | ||
886 | if (ret) | ||
887 | pr_err("soc_dapm_add_routes failed %d", ret); | ||
888 | |||
889 | return ret; | ||
890 | } | ||
891 | |||
892 | static int sn95031_codec_remove(struct snd_soc_codec *codec) | ||
893 | { | ||
894 | pr_debug("codec_remove called\n"); | ||
895 | sn95031_set_vaud_bias(codec, SND_SOC_BIAS_OFF); | ||
896 | |||
897 | return 0; | ||
898 | } | ||
899 | |||
900 | struct snd_soc_codec_driver sn95031_codec = { | ||
901 | .probe = sn95031_codec_probe, | ||
902 | .remove = sn95031_codec_remove, | ||
903 | .read = sn95031_read, | ||
904 | .write = sn95031_write, | ||
905 | .set_bias_level = sn95031_set_vaud_bias, | ||
906 | }; | ||
907 | |||
908 | static int __devinit sn95031_device_probe(struct platform_device *pdev) | ||
909 | { | ||
910 | pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev)); | ||
911 | return snd_soc_register_codec(&pdev->dev, &sn95031_codec, | ||
912 | sn95031_dais, ARRAY_SIZE(sn95031_dais)); | ||
913 | } | ||
914 | |||
915 | static int __devexit sn95031_device_remove(struct platform_device *pdev) | ||
916 | { | ||
917 | pr_debug("codec device remove called\n"); | ||
918 | snd_soc_unregister_codec(&pdev->dev); | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static struct platform_driver sn95031_codec_driver = { | ||
923 | .driver = { | ||
924 | .name = "sn95031", | ||
925 | .owner = THIS_MODULE, | ||
926 | }, | ||
927 | .probe = sn95031_device_probe, | ||
928 | .remove = sn95031_device_remove, | ||
929 | }; | ||
930 | |||
931 | static int __init sn95031_init(void) | ||
932 | { | ||
933 | pr_debug("driver init called\n"); | ||
934 | return platform_driver_register(&sn95031_codec_driver); | ||
935 | } | ||
936 | module_init(sn95031_init); | ||
937 | |||
938 | static void __exit sn95031_exit(void) | ||
939 | { | ||
940 | pr_debug("driver exit called\n"); | ||
941 | platform_driver_unregister(&sn95031_codec_driver); | ||
942 | } | ||
943 | module_exit(sn95031_exit); | ||
944 | |||
945 | MODULE_DESCRIPTION("ASoC TI SN95031 codec driver"); | ||
946 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); | ||
947 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); | ||
948 | MODULE_LICENSE("GPL v2"); | ||
949 | MODULE_ALIAS("platform:sn95031"); | ||
diff --git a/sound/soc/codecs/sn95031.h b/sound/soc/codecs/sn95031.h new file mode 100644 index 000000000000..20376d234fb8 --- /dev/null +++ b/sound/soc/codecs/sn95031.h | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * sn95031.h - TI sn95031 Codec driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Intel Corp | ||
5 | * Author: Vinod Koul <vinod.koul@intel.com> | ||
6 | * Author: Harsha Priya <priya.harsha@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program 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; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | * | ||
24 | * | ||
25 | */ | ||
26 | #ifndef _SN95031_H | ||
27 | #define _SN95031_H | ||
28 | |||
29 | /*register map*/ | ||
30 | #define SN95031_VAUD 0xDB | ||
31 | #define SN95031_VHSP 0xDC | ||
32 | #define SN95031_VHSN 0xDD | ||
33 | #define SN95031_VIHF 0xC9 | ||
34 | |||
35 | #define SN95031_AUDPLLCTRL 0x240 | ||
36 | #define SN95031_DMICBUF0123 0x241 | ||
37 | #define SN95031_DMICBUF45 0x242 | ||
38 | #define SN95031_DMICGPO 0x244 | ||
39 | #define SN95031_DMICMUX 0x245 | ||
40 | #define SN95031_DMICLK 0x246 | ||
41 | #define SN95031_MICBIAS 0x247 | ||
42 | #define SN95031_ADCCONFIG 0x248 | ||
43 | #define SN95031_MICAMP1 0x249 | ||
44 | #define SN95031_MICAMP2 0x24A | ||
45 | #define SN95031_NOISEMUX 0x24B | ||
46 | #define SN95031_AUDIOMUX12 0x24C | ||
47 | #define SN95031_AUDIOMUX34 0x24D | ||
48 | #define SN95031_AUDIOSINC 0x24E | ||
49 | #define SN95031_AUDIOTXEN 0x24F | ||
50 | #define SN95031_HSEPRXCTRL 0x250 | ||
51 | #define SN95031_IHFRXCTRL 0x251 | ||
52 | #define SN95031_HSMIXER 0x256 | ||
53 | #define SN95031_DACCONFIG 0x257 | ||
54 | #define SN95031_SOFTMUTE 0x258 | ||
55 | #define SN95031_HSLVOLCTRL 0x259 | ||
56 | #define SN95031_HSRVOLCTRL 0x25A | ||
57 | #define SN95031_IHFLVOLCTRL 0x25B | ||
58 | #define SN95031_IHFRVOLCTRL 0x25C | ||
59 | #define SN95031_DRIVEREN 0x25D | ||
60 | #define SN95031_LOCTL 0x25E | ||
61 | #define SN95031_VIB1C1 0x25F | ||
62 | #define SN95031_VIB1C2 0x260 | ||
63 | #define SN95031_VIB1C3 0x261 | ||
64 | #define SN95031_VIB1SPIPCM1 0x262 | ||
65 | #define SN95031_VIB1SPIPCM2 0x263 | ||
66 | #define SN95031_VIB1C5 0x264 | ||
67 | #define SN95031_VIB2C1 0x265 | ||
68 | #define SN95031_VIB2C2 0x266 | ||
69 | #define SN95031_VIB2C3 0x267 | ||
70 | #define SN95031_VIB2SPIPCM1 0x268 | ||
71 | #define SN95031_VIB2SPIPCM2 0x269 | ||
72 | #define SN95031_VIB2C5 0x26A | ||
73 | #define SN95031_BTNCTRL1 0x26B | ||
74 | #define SN95031_BTNCTRL2 0x26C | ||
75 | #define SN95031_PCM1TXSLOT01 0x26D | ||
76 | #define SN95031_PCM1TXSLOT23 0x26E | ||
77 | #define SN95031_PCM1TXSLOT45 0x26F | ||
78 | #define SN95031_PCM1RXSLOT0_3 0x270 | ||
79 | #define SN95031_PCM1RXSLOT45 0x271 | ||
80 | #define SN95031_PCM2TXSLOT01 0x272 | ||
81 | #define SN95031_PCM2TXSLOT23 0x273 | ||
82 | #define SN95031_PCM2TXSLOT45 0x274 | ||
83 | #define SN95031_PCM2RXSLOT01 0x275 | ||
84 | #define SN95031_PCM2RXSLOT23 0x276 | ||
85 | #define SN95031_PCM2RXSLOT45 0x277 | ||
86 | #define SN95031_PCM1C1 0x278 | ||
87 | #define SN95031_PCM1C2 0x279 | ||
88 | #define SN95031_PCM1C3 0x27A | ||
89 | #define SN95031_PCM2C1 0x27B | ||
90 | #define SN95031_PCM2C2 0x27C | ||
91 | /*end codec register defn*/ | ||
92 | |||
93 | /*vendor defn these are not part of avp*/ | ||
94 | #define SN95031_SSR2 0x381 | ||
95 | #define SN95031_SSR3 0x382 | ||
96 | #define SN95031_SSR5 0x384 | ||
97 | #define SN95031_SSR6 0x385 | ||
98 | |||
99 | /* ADC registers */ | ||
100 | |||
101 | #define SN95031_ADC1CNTL1 0x1C0 | ||
102 | #define SN95031_ADC_ENBL 0x10 | ||
103 | #define SN95031_ADC_START 0x08 | ||
104 | #define SN95031_ADC1CNTL3 0x1C2 | ||
105 | #define SN95031_ADCTHERM_ENBL 0x04 | ||
106 | #define SN95031_ADCRRDATA_ENBL 0x05 | ||
107 | #define SN95031_STOPBIT_MASK 16 | ||
108 | #define SN95031_ADCTHERM_MASK 4 | ||
109 | #define SN95031_ADC_CHANLS_MAX 15 /* Number of ADC channels */ | ||
110 | #define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1) | ||
111 | #define SN95031_ADC_NO_LOOP 0x07 | ||
112 | #define SN95031_AUDIO_GPIO_CTRL 0x070 | ||
113 | |||
114 | /* ADC channel code values */ | ||
115 | #define SN95031_AUDIO_DETECT_CODE 0x06 | ||
116 | |||
117 | /* ADC base addresses */ | ||
118 | #define SN95031_ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */ | ||
119 | #define SN95031_ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */ | ||
120 | /* multipier to convert to mV */ | ||
121 | #define SN95031_ADC_ONE_LSB_MULTIPLIER 2346 | ||
122 | |||
123 | |||
124 | struct mfld_jack_data { | ||
125 | int intr_id; | ||
126 | int micbias_vol; | ||
127 | struct snd_soc_jack *mfld_jack; | ||
128 | }; | ||
129 | |||
130 | extern void sn95031_jack_detection(struct mfld_jack_data *jack_data); | ||
131 | |||
132 | #endif | ||
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c new file mode 100644 index 000000000000..e93b9d1ae1dd --- /dev/null +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -0,0 +1,794 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/codecs/tlv320aic32x4.c | ||
3 | * | ||
4 | * Copyright 2011 Vista Silicon S.L. | ||
5 | * | ||
6 | * Author: Javier Martin <javier.martin@vista-silicon.com> | ||
7 | * | ||
8 | * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27. | ||
9 | * | ||
10 | * 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 | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||
23 | * MA 02110-1301, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/pm.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <linux/cdev.h> | ||
34 | #include <linux/slab.h> | ||
35 | |||
36 | #include <sound/tlv320aic32x4.h> | ||
37 | #include <sound/core.h> | ||
38 | #include <sound/pcm.h> | ||
39 | #include <sound/pcm_params.h> | ||
40 | #include <sound/soc.h> | ||
41 | #include <sound/soc-dapm.h> | ||
42 | #include <sound/initval.h> | ||
43 | #include <sound/tlv.h> | ||
44 | |||
45 | #include "tlv320aic32x4.h" | ||
46 | |||
47 | struct aic32x4_rate_divs { | ||
48 | u32 mclk; | ||
49 | u32 rate; | ||
50 | u8 p_val; | ||
51 | u8 pll_j; | ||
52 | u16 pll_d; | ||
53 | u16 dosr; | ||
54 | u8 ndac; | ||
55 | u8 mdac; | ||
56 | u8 aosr; | ||
57 | u8 nadc; | ||
58 | u8 madc; | ||
59 | u8 blck_N; | ||
60 | }; | ||
61 | |||
62 | struct aic32x4_priv { | ||
63 | u32 sysclk; | ||
64 | s32 master; | ||
65 | u8 page_no; | ||
66 | void *control_data; | ||
67 | u32 power_cfg; | ||
68 | u32 micpga_routing; | ||
69 | bool swapdacs; | ||
70 | }; | ||
71 | |||
72 | /* 0dB min, 1dB steps */ | ||
73 | static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0); | ||
74 | /* 0dB min, 0.5dB steps */ | ||
75 | static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0); | ||
76 | |||
77 | static const struct snd_kcontrol_new aic32x4_snd_controls[] = { | ||
78 | SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL, | ||
79 | AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5), | ||
80 | SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN, | ||
81 | AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1), | ||
82 | SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN, | ||
83 | AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1), | ||
84 | SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN, | ||
85 | AIC32X4_HPRGAIN, 6, 0x01, 1), | ||
86 | SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN, | ||
87 | AIC32X4_LORGAIN, 6, 0x01, 1), | ||
88 | SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL, | ||
89 | AIC32X4_RMICPGAVOL, 7, 0x01, 1), | ||
90 | |||
91 | SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0), | ||
92 | SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0), | ||
93 | |||
94 | SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL, | ||
95 | AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5), | ||
96 | SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL, | ||
97 | AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5), | ||
98 | |||
99 | SOC_SINGLE("Auto-mute Switch", AIC32X4_DACMUTE, 4, 7, 0), | ||
100 | |||
101 | SOC_SINGLE("AGC Left Switch", AIC32X4_LAGC1, 7, 1, 0), | ||
102 | SOC_SINGLE("AGC Right Switch", AIC32X4_RAGC1, 7, 1, 0), | ||
103 | SOC_DOUBLE_R("AGC Target Level", AIC32X4_LAGC1, AIC32X4_RAGC1, | ||
104 | 4, 0x07, 0), | ||
105 | SOC_DOUBLE_R("AGC Gain Hysteresis", AIC32X4_LAGC1, AIC32X4_RAGC1, | ||
106 | 0, 0x03, 0), | ||
107 | SOC_DOUBLE_R("AGC Hysteresis", AIC32X4_LAGC2, AIC32X4_RAGC2, | ||
108 | 6, 0x03, 0), | ||
109 | SOC_DOUBLE_R("AGC Noise Threshold", AIC32X4_LAGC2, AIC32X4_RAGC2, | ||
110 | 1, 0x1F, 0), | ||
111 | SOC_DOUBLE_R("AGC Max PGA", AIC32X4_LAGC3, AIC32X4_RAGC3, | ||
112 | 0, 0x7F, 0), | ||
113 | SOC_DOUBLE_R("AGC Attack Time", AIC32X4_LAGC4, AIC32X4_RAGC4, | ||
114 | 3, 0x1F, 0), | ||
115 | SOC_DOUBLE_R("AGC Decay Time", AIC32X4_LAGC5, AIC32X4_RAGC5, | ||
116 | 3, 0x1F, 0), | ||
117 | SOC_DOUBLE_R("AGC Noise Debounce", AIC32X4_LAGC6, AIC32X4_RAGC6, | ||
118 | 0, 0x1F, 0), | ||
119 | SOC_DOUBLE_R("AGC Signal Debounce", AIC32X4_LAGC7, AIC32X4_RAGC7, | ||
120 | 0, 0x0F, 0), | ||
121 | }; | ||
122 | |||
123 | static const struct aic32x4_rate_divs aic32x4_divs[] = { | ||
124 | /* 8k rate */ | ||
125 | {AIC32X4_FREQ_12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24}, | ||
126 | {AIC32X4_FREQ_24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24}, | ||
127 | {AIC32X4_FREQ_25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24}, | ||
128 | /* 11.025k rate */ | ||
129 | {AIC32X4_FREQ_12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16}, | ||
130 | {AIC32X4_FREQ_24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16}, | ||
131 | /* 16k rate */ | ||
132 | {AIC32X4_FREQ_12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12}, | ||
133 | {AIC32X4_FREQ_24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12}, | ||
134 | {AIC32X4_FREQ_25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12}, | ||
135 | /* 22.05k rate */ | ||
136 | {AIC32X4_FREQ_12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8}, | ||
137 | {AIC32X4_FREQ_24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8}, | ||
138 | {AIC32X4_FREQ_25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8}, | ||
139 | /* 32k rate */ | ||
140 | {AIC32X4_FREQ_12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6}, | ||
141 | {AIC32X4_FREQ_24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6}, | ||
142 | /* 44.1k rate */ | ||
143 | {AIC32X4_FREQ_12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4}, | ||
144 | {AIC32X4_FREQ_24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4}, | ||
145 | {AIC32X4_FREQ_25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4}, | ||
146 | /* 48k rate */ | ||
147 | {AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4}, | ||
148 | {AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4}, | ||
149 | {AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4} | ||
150 | }; | ||
151 | |||
152 | static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { | ||
153 | SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0), | ||
154 | SOC_DAPM_SINGLE("IN1_L Switch", AIC32X4_HPLROUTE, 2, 1, 0), | ||
155 | }; | ||
156 | |||
157 | static const struct snd_kcontrol_new hpr_output_mixer_controls[] = { | ||
158 | SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_HPRROUTE, 3, 1, 0), | ||
159 | SOC_DAPM_SINGLE("IN1_R Switch", AIC32X4_HPRROUTE, 2, 1, 0), | ||
160 | }; | ||
161 | |||
162 | static const struct snd_kcontrol_new lol_output_mixer_controls[] = { | ||
163 | SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_LOLROUTE, 3, 1, 0), | ||
164 | }; | ||
165 | |||
166 | static const struct snd_kcontrol_new lor_output_mixer_controls[] = { | ||
167 | SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0), | ||
168 | }; | ||
169 | |||
170 | static const struct snd_kcontrol_new left_input_mixer_controls[] = { | ||
171 | SOC_DAPM_SINGLE("IN1_L P Switch", AIC32X4_LMICPGAPIN, 6, 1, 0), | ||
172 | SOC_DAPM_SINGLE("IN2_L P Switch", AIC32X4_LMICPGAPIN, 4, 1, 0), | ||
173 | SOC_DAPM_SINGLE("IN3_L P Switch", AIC32X4_LMICPGAPIN, 2, 1, 0), | ||
174 | }; | ||
175 | |||
176 | static const struct snd_kcontrol_new right_input_mixer_controls[] = { | ||
177 | SOC_DAPM_SINGLE("IN1_R P Switch", AIC32X4_RMICPGAPIN, 6, 1, 0), | ||
178 | SOC_DAPM_SINGLE("IN2_R P Switch", AIC32X4_RMICPGAPIN, 4, 1, 0), | ||
179 | SOC_DAPM_SINGLE("IN3_R P Switch", AIC32X4_RMICPGAPIN, 2, 1, 0), | ||
180 | }; | ||
181 | |||
182 | static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = { | ||
183 | SND_SOC_DAPM_DAC("Left DAC", "Left Playback", AIC32X4_DACSETUP, 7, 0), | ||
184 | SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0, | ||
185 | &hpl_output_mixer_controls[0], | ||
186 | ARRAY_SIZE(hpl_output_mixer_controls)), | ||
187 | SND_SOC_DAPM_PGA("HPL Power", AIC32X4_OUTPWRCTL, 5, 0, NULL, 0), | ||
188 | |||
189 | SND_SOC_DAPM_MIXER("LOL Output Mixer", SND_SOC_NOPM, 0, 0, | ||
190 | &lol_output_mixer_controls[0], | ||
191 | ARRAY_SIZE(lol_output_mixer_controls)), | ||
192 | SND_SOC_DAPM_PGA("LOL Power", AIC32X4_OUTPWRCTL, 3, 0, NULL, 0), | ||
193 | |||
194 | SND_SOC_DAPM_DAC("Right DAC", "Right Playback", AIC32X4_DACSETUP, 6, 0), | ||
195 | SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0, | ||
196 | &hpr_output_mixer_controls[0], | ||
197 | ARRAY_SIZE(hpr_output_mixer_controls)), | ||
198 | SND_SOC_DAPM_PGA("HPR Power", AIC32X4_OUTPWRCTL, 4, 0, NULL, 0), | ||
199 | SND_SOC_DAPM_MIXER("LOR Output Mixer", SND_SOC_NOPM, 0, 0, | ||
200 | &lor_output_mixer_controls[0], | ||
201 | ARRAY_SIZE(lor_output_mixer_controls)), | ||
202 | SND_SOC_DAPM_PGA("LOR Power", AIC32X4_OUTPWRCTL, 2, 0, NULL, 0), | ||
203 | SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0, | ||
204 | &left_input_mixer_controls[0], | ||
205 | ARRAY_SIZE(left_input_mixer_controls)), | ||
206 | SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0, | ||
207 | &right_input_mixer_controls[0], | ||
208 | ARRAY_SIZE(right_input_mixer_controls)), | ||
209 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0), | ||
210 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC32X4_ADCSETUP, 6, 0), | ||
211 | SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0), | ||
212 | |||
213 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
214 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
215 | SND_SOC_DAPM_OUTPUT("LOL"), | ||
216 | SND_SOC_DAPM_OUTPUT("LOR"), | ||
217 | SND_SOC_DAPM_INPUT("IN1_L"), | ||
218 | SND_SOC_DAPM_INPUT("IN1_R"), | ||
219 | SND_SOC_DAPM_INPUT("IN2_L"), | ||
220 | SND_SOC_DAPM_INPUT("IN2_R"), | ||
221 | SND_SOC_DAPM_INPUT("IN3_L"), | ||
222 | SND_SOC_DAPM_INPUT("IN3_R"), | ||
223 | }; | ||
224 | |||
225 | static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = { | ||
226 | /* Left Output */ | ||
227 | {"HPL Output Mixer", "L_DAC Switch", "Left DAC"}, | ||
228 | {"HPL Output Mixer", "IN1_L Switch", "IN1_L"}, | ||
229 | |||
230 | {"HPL Power", NULL, "HPL Output Mixer"}, | ||
231 | {"HPL", NULL, "HPL Power"}, | ||
232 | |||
233 | {"LOL Output Mixer", "L_DAC Switch", "Left DAC"}, | ||
234 | |||
235 | {"LOL Power", NULL, "LOL Output Mixer"}, | ||
236 | {"LOL", NULL, "LOL Power"}, | ||
237 | |||
238 | /* Right Output */ | ||
239 | {"HPR Output Mixer", "R_DAC Switch", "Right DAC"}, | ||
240 | {"HPR Output Mixer", "IN1_R Switch", "IN1_R"}, | ||
241 | |||
242 | {"HPR Power", NULL, "HPR Output Mixer"}, | ||
243 | {"HPR", NULL, "HPR Power"}, | ||
244 | |||
245 | {"LOR Output Mixer", "R_DAC Switch", "Right DAC"}, | ||
246 | |||
247 | {"LOR Power", NULL, "LOR Output Mixer"}, | ||
248 | {"LOR", NULL, "LOR Power"}, | ||
249 | |||
250 | /* Left input */ | ||
251 | {"Left Input Mixer", "IN1_L P Switch", "IN1_L"}, | ||
252 | {"Left Input Mixer", "IN2_L P Switch", "IN2_L"}, | ||
253 | {"Left Input Mixer", "IN3_L P Switch", "IN3_L"}, | ||
254 | |||
255 | {"Left ADC", NULL, "Left Input Mixer"}, | ||
256 | |||
257 | /* Right Input */ | ||
258 | {"Right Input Mixer", "IN1_R P Switch", "IN1_R"}, | ||
259 | {"Right Input Mixer", "IN2_R P Switch", "IN2_R"}, | ||
260 | {"Right Input Mixer", "IN3_R P Switch", "IN3_R"}, | ||
261 | |||
262 | {"Right ADC", NULL, "Right Input Mixer"}, | ||
263 | }; | ||
264 | |||
265 | static inline int aic32x4_change_page(struct snd_soc_codec *codec, | ||
266 | unsigned int new_page) | ||
267 | { | ||
268 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
269 | u8 data[2]; | ||
270 | int ret; | ||
271 | |||
272 | data[0] = 0x00; | ||
273 | data[1] = new_page & 0xff; | ||
274 | |||
275 | ret = codec->hw_write(codec->control_data, data, 2); | ||
276 | if (ret == 2) { | ||
277 | aic32x4->page_no = new_page; | ||
278 | return 0; | ||
279 | } else { | ||
280 | return ret; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static int aic32x4_write(struct snd_soc_codec *codec, unsigned int reg, | ||
285 | unsigned int val) | ||
286 | { | ||
287 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
288 | unsigned int page = reg / 128; | ||
289 | unsigned int fixed_reg = reg % 128; | ||
290 | u8 data[2]; | ||
291 | int ret; | ||
292 | |||
293 | /* A write to AIC32X4_PSEL is really a non-explicit page change */ | ||
294 | if (reg == AIC32X4_PSEL) | ||
295 | return aic32x4_change_page(codec, val); | ||
296 | |||
297 | if (aic32x4->page_no != page) { | ||
298 | ret = aic32x4_change_page(codec, page); | ||
299 | if (ret != 0) | ||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | data[0] = fixed_reg & 0xff; | ||
304 | data[1] = val & 0xff; | ||
305 | |||
306 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
307 | return 0; | ||
308 | else | ||
309 | return -EIO; | ||
310 | } | ||
311 | |||
312 | static unsigned int aic32x4_read(struct snd_soc_codec *codec, unsigned int reg) | ||
313 | { | ||
314 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
315 | unsigned int page = reg / 128; | ||
316 | unsigned int fixed_reg = reg % 128; | ||
317 | int ret; | ||
318 | |||
319 | if (aic32x4->page_no != page) { | ||
320 | ret = aic32x4_change_page(codec, page); | ||
321 | if (ret != 0) | ||
322 | return ret; | ||
323 | } | ||
324 | return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff); | ||
325 | } | ||
326 | |||
327 | static inline int aic32x4_get_divs(int mclk, int rate) | ||
328 | { | ||
329 | int i; | ||
330 | |||
331 | for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) { | ||
332 | if ((aic32x4_divs[i].rate == rate) | ||
333 | && (aic32x4_divs[i].mclk == mclk)) { | ||
334 | return i; | ||
335 | } | ||
336 | } | ||
337 | printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n"); | ||
338 | return -EINVAL; | ||
339 | } | ||
340 | |||
341 | static int aic32x4_add_widgets(struct snd_soc_codec *codec) | ||
342 | { | ||
343 | snd_soc_dapm_new_controls(&codec->dapm, aic32x4_dapm_widgets, | ||
344 | ARRAY_SIZE(aic32x4_dapm_widgets)); | ||
345 | |||
346 | snd_soc_dapm_add_routes(&codec->dapm, aic32x4_dapm_routes, | ||
347 | ARRAY_SIZE(aic32x4_dapm_routes)); | ||
348 | |||
349 | snd_soc_dapm_new_widgets(&codec->dapm); | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
354 | int clk_id, unsigned int freq, int dir) | ||
355 | { | ||
356 | struct snd_soc_codec *codec = codec_dai->codec; | ||
357 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
358 | |||
359 | switch (freq) { | ||
360 | case AIC32X4_FREQ_12000000: | ||
361 | case AIC32X4_FREQ_24000000: | ||
362 | case AIC32X4_FREQ_25000000: | ||
363 | aic32x4->sysclk = freq; | ||
364 | return 0; | ||
365 | } | ||
366 | printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n"); | ||
367 | return -EINVAL; | ||
368 | } | ||
369 | |||
370 | static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
371 | { | ||
372 | struct snd_soc_codec *codec = codec_dai->codec; | ||
373 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
374 | u8 iface_reg_1; | ||
375 | u8 iface_reg_2; | ||
376 | u8 iface_reg_3; | ||
377 | |||
378 | iface_reg_1 = snd_soc_read(codec, AIC32X4_IFACE1); | ||
379 | iface_reg_1 = iface_reg_1 & ~(3 << 6 | 3 << 2); | ||
380 | iface_reg_2 = snd_soc_read(codec, AIC32X4_IFACE2); | ||
381 | iface_reg_2 = 0; | ||
382 | iface_reg_3 = snd_soc_read(codec, AIC32X4_IFACE3); | ||
383 | iface_reg_3 = iface_reg_3 & ~(1 << 3); | ||
384 | |||
385 | /* set master/slave audio interface */ | ||
386 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
387 | case SND_SOC_DAIFMT_CBM_CFM: | ||
388 | aic32x4->master = 1; | ||
389 | iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER; | ||
390 | break; | ||
391 | case SND_SOC_DAIFMT_CBS_CFS: | ||
392 | aic32x4->master = 0; | ||
393 | break; | ||
394 | default: | ||
395 | printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n"); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
400 | case SND_SOC_DAIFMT_I2S: | ||
401 | break; | ||
402 | case SND_SOC_DAIFMT_DSP_A: | ||
403 | iface_reg_1 |= (AIC32X4_DSP_MODE << AIC32X4_PLLJ_SHIFT); | ||
404 | iface_reg_3 |= (1 << 3); /* invert bit clock */ | ||
405 | iface_reg_2 = 0x01; /* add offset 1 */ | ||
406 | break; | ||
407 | case SND_SOC_DAIFMT_DSP_B: | ||
408 | iface_reg_1 |= (AIC32X4_DSP_MODE << AIC32X4_PLLJ_SHIFT); | ||
409 | iface_reg_3 |= (1 << 3); /* invert bit clock */ | ||
410 | break; | ||
411 | case SND_SOC_DAIFMT_RIGHT_J: | ||
412 | iface_reg_1 |= | ||
413 | (AIC32X4_RIGHT_JUSTIFIED_MODE << AIC32X4_PLLJ_SHIFT); | ||
414 | break; | ||
415 | case SND_SOC_DAIFMT_LEFT_J: | ||
416 | iface_reg_1 |= | ||
417 | (AIC32X4_LEFT_JUSTIFIED_MODE << AIC32X4_PLLJ_SHIFT); | ||
418 | break; | ||
419 | default: | ||
420 | printk(KERN_ERR "aic32x4: invalid DAI interface format\n"); | ||
421 | return -EINVAL; | ||
422 | } | ||
423 | |||
424 | snd_soc_write(codec, AIC32X4_IFACE1, iface_reg_1); | ||
425 | snd_soc_write(codec, AIC32X4_IFACE2, iface_reg_2); | ||
426 | snd_soc_write(codec, AIC32X4_IFACE3, iface_reg_3); | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static int aic32x4_hw_params(struct snd_pcm_substream *substream, | ||
431 | struct snd_pcm_hw_params *params, | ||
432 | struct snd_soc_dai *dai) | ||
433 | { | ||
434 | struct snd_soc_codec *codec = dai->codec; | ||
435 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
436 | u8 data; | ||
437 | int i; | ||
438 | |||
439 | i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params)); | ||
440 | if (i < 0) { | ||
441 | printk(KERN_ERR "aic32x4: sampling rate not supported\n"); | ||
442 | return i; | ||
443 | } | ||
444 | |||
445 | /* Use PLL as CODEC_CLKIN and DAC_MOD_CLK as BDIV_CLKIN */ | ||
446 | snd_soc_write(codec, AIC32X4_CLKMUX, AIC32X4_PLLCLKIN); | ||
447 | snd_soc_write(codec, AIC32X4_IFACE3, AIC32X4_DACMOD2BCLK); | ||
448 | |||
449 | /* We will fix R value to 1 and will make P & J=K.D as varialble */ | ||
450 | data = snd_soc_read(codec, AIC32X4_PLLPR); | ||
451 | data &= ~(7 << 4); | ||
452 | snd_soc_write(codec, AIC32X4_PLLPR, | ||
453 | (data | (aic32x4_divs[i].p_val << 4) | 0x01)); | ||
454 | |||
455 | snd_soc_write(codec, AIC32X4_PLLJ, aic32x4_divs[i].pll_j); | ||
456 | |||
457 | snd_soc_write(codec, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8)); | ||
458 | snd_soc_write(codec, AIC32X4_PLLDLSB, | ||
459 | (aic32x4_divs[i].pll_d & 0xff)); | ||
460 | |||
461 | /* NDAC divider value */ | ||
462 | data = snd_soc_read(codec, AIC32X4_NDAC); | ||
463 | data &= ~(0x7f); | ||
464 | snd_soc_write(codec, AIC32X4_NDAC, data | aic32x4_divs[i].ndac); | ||
465 | |||
466 | /* MDAC divider value */ | ||
467 | data = snd_soc_read(codec, AIC32X4_MDAC); | ||
468 | data &= ~(0x7f); | ||
469 | snd_soc_write(codec, AIC32X4_MDAC, data | aic32x4_divs[i].mdac); | ||
470 | |||
471 | /* DOSR MSB & LSB values */ | ||
472 | snd_soc_write(codec, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8); | ||
473 | snd_soc_write(codec, AIC32X4_DOSRLSB, | ||
474 | (aic32x4_divs[i].dosr & 0xff)); | ||
475 | |||
476 | /* NADC divider value */ | ||
477 | data = snd_soc_read(codec, AIC32X4_NADC); | ||
478 | data &= ~(0x7f); | ||
479 | snd_soc_write(codec, AIC32X4_NADC, data | aic32x4_divs[i].nadc); | ||
480 | |||
481 | /* MADC divider value */ | ||
482 | data = snd_soc_read(codec, AIC32X4_MADC); | ||
483 | data &= ~(0x7f); | ||
484 | snd_soc_write(codec, AIC32X4_MADC, data | aic32x4_divs[i].madc); | ||
485 | |||
486 | /* AOSR value */ | ||
487 | snd_soc_write(codec, AIC32X4_AOSR, aic32x4_divs[i].aosr); | ||
488 | |||
489 | /* BCLK N divider */ | ||
490 | data = snd_soc_read(codec, AIC32X4_BCLKN); | ||
491 | data &= ~(0x7f); | ||
492 | snd_soc_write(codec, AIC32X4_BCLKN, data | aic32x4_divs[i].blck_N); | ||
493 | |||
494 | data = snd_soc_read(codec, AIC32X4_IFACE1); | ||
495 | data = data & ~(3 << 4); | ||
496 | switch (params_format(params)) { | ||
497 | case SNDRV_PCM_FORMAT_S16_LE: | ||
498 | break; | ||
499 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
500 | data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT); | ||
501 | break; | ||
502 | case SNDRV_PCM_FORMAT_S24_LE: | ||
503 | data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT); | ||
504 | break; | ||
505 | case SNDRV_PCM_FORMAT_S32_LE: | ||
506 | data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT); | ||
507 | break; | ||
508 | } | ||
509 | snd_soc_write(codec, AIC32X4_IFACE1, data); | ||
510 | |||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | static int aic32x4_mute(struct snd_soc_dai *dai, int mute) | ||
515 | { | ||
516 | struct snd_soc_codec *codec = dai->codec; | ||
517 | u8 dac_reg; | ||
518 | |||
519 | dac_reg = snd_soc_read(codec, AIC32X4_DACMUTE) & ~AIC32X4_MUTEON; | ||
520 | if (mute) | ||
521 | snd_soc_write(codec, AIC32X4_DACMUTE, dac_reg | AIC32X4_MUTEON); | ||
522 | else | ||
523 | snd_soc_write(codec, AIC32X4_DACMUTE, dac_reg); | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int aic32x4_set_bias_level(struct snd_soc_codec *codec, | ||
528 | enum snd_soc_bias_level level) | ||
529 | { | ||
530 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
531 | u8 value; | ||
532 | |||
533 | switch (level) { | ||
534 | case SND_SOC_BIAS_ON: | ||
535 | if (aic32x4->master) { | ||
536 | /* Switch on PLL */ | ||
537 | value = snd_soc_read(codec, AIC32X4_PLLPR); | ||
538 | snd_soc_write(codec, AIC32X4_PLLPR, | ||
539 | (value | AIC32X4_PLLEN)); | ||
540 | |||
541 | /* Switch on NDAC Divider */ | ||
542 | value = snd_soc_read(codec, AIC32X4_NDAC); | ||
543 | snd_soc_write(codec, AIC32X4_NDAC, | ||
544 | value | AIC32X4_NDACEN); | ||
545 | |||
546 | /* Switch on MDAC Divider */ | ||
547 | value = snd_soc_read(codec, AIC32X4_MDAC); | ||
548 | snd_soc_write(codec, AIC32X4_MDAC, | ||
549 | value | AIC32X4_MDACEN); | ||
550 | |||
551 | /* Switch on NADC Divider */ | ||
552 | value = snd_soc_read(codec, AIC32X4_NADC); | ||
553 | snd_soc_write(codec, AIC32X4_NADC, | ||
554 | value | AIC32X4_MDACEN); | ||
555 | |||
556 | /* Switch on MADC Divider */ | ||
557 | value = snd_soc_read(codec, AIC32X4_MADC); | ||
558 | snd_soc_write(codec, AIC32X4_MADC, | ||
559 | value | AIC32X4_MDACEN); | ||
560 | |||
561 | /* Switch on BCLK_N Divider */ | ||
562 | value = snd_soc_read(codec, AIC32X4_BCLKN); | ||
563 | snd_soc_write(codec, AIC32X4_BCLKN, | ||
564 | value | AIC32X4_BCLKEN); | ||
565 | } | ||
566 | break; | ||
567 | case SND_SOC_BIAS_PREPARE: | ||
568 | break; | ||
569 | case SND_SOC_BIAS_STANDBY: | ||
570 | if (aic32x4->master) { | ||
571 | /* Switch off PLL */ | ||
572 | value = snd_soc_read(codec, AIC32X4_PLLPR); | ||
573 | snd_soc_write(codec, AIC32X4_PLLPR, | ||
574 | (value & ~AIC32X4_PLLEN)); | ||
575 | |||
576 | /* Switch off NDAC Divider */ | ||
577 | value = snd_soc_read(codec, AIC32X4_NDAC); | ||
578 | snd_soc_write(codec, AIC32X4_NDAC, | ||
579 | value & ~AIC32X4_NDACEN); | ||
580 | |||
581 | /* Switch off MDAC Divider */ | ||
582 | value = snd_soc_read(codec, AIC32X4_MDAC); | ||
583 | snd_soc_write(codec, AIC32X4_MDAC, | ||
584 | value & ~AIC32X4_MDACEN); | ||
585 | |||
586 | /* Switch off NADC Divider */ | ||
587 | value = snd_soc_read(codec, AIC32X4_NADC); | ||
588 | snd_soc_write(codec, AIC32X4_NADC, | ||
589 | value & ~AIC32X4_NDACEN); | ||
590 | |||
591 | /* Switch off MADC Divider */ | ||
592 | value = snd_soc_read(codec, AIC32X4_MADC); | ||
593 | snd_soc_write(codec, AIC32X4_MADC, | ||
594 | value & ~AIC32X4_MDACEN); | ||
595 | value = snd_soc_read(codec, AIC32X4_BCLKN); | ||
596 | |||
597 | /* Switch off BCLK_N Divider */ | ||
598 | snd_soc_write(codec, AIC32X4_BCLKN, | ||
599 | value & ~AIC32X4_BCLKEN); | ||
600 | } | ||
601 | break; | ||
602 | case SND_SOC_BIAS_OFF: | ||
603 | break; | ||
604 | } | ||
605 | codec->dapm.bias_level = level; | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | #define AIC32X4_RATES SNDRV_PCM_RATE_8000_48000 | ||
610 | #define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ | ||
611 | | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
612 | |||
613 | static struct snd_soc_dai_ops aic32x4_ops = { | ||
614 | .hw_params = aic32x4_hw_params, | ||
615 | .digital_mute = aic32x4_mute, | ||
616 | .set_fmt = aic32x4_set_dai_fmt, | ||
617 | .set_sysclk = aic32x4_set_dai_sysclk, | ||
618 | }; | ||
619 | |||
620 | static struct snd_soc_dai_driver aic32x4_dai = { | ||
621 | .name = "tlv320aic32x4-hifi", | ||
622 | .playback = { | ||
623 | .stream_name = "Playback", | ||
624 | .channels_min = 1, | ||
625 | .channels_max = 2, | ||
626 | .rates = AIC32X4_RATES, | ||
627 | .formats = AIC32X4_FORMATS,}, | ||
628 | .capture = { | ||
629 | .stream_name = "Capture", | ||
630 | .channels_min = 1, | ||
631 | .channels_max = 2, | ||
632 | .rates = AIC32X4_RATES, | ||
633 | .formats = AIC32X4_FORMATS,}, | ||
634 | .ops = &aic32x4_ops, | ||
635 | .symmetric_rates = 1, | ||
636 | }; | ||
637 | |||
638 | static int aic32x4_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
639 | { | ||
640 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | static int aic32x4_resume(struct snd_soc_codec *codec) | ||
645 | { | ||
646 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
647 | return 0; | ||
648 | } | ||
649 | |||
650 | static int aic32x4_probe(struct snd_soc_codec *codec) | ||
651 | { | ||
652 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | ||
653 | u32 tmp_reg; | ||
654 | |||
655 | codec->hw_write = (hw_write_t) i2c_master_send; | ||
656 | codec->control_data = aic32x4->control_data; | ||
657 | |||
658 | snd_soc_write(codec, AIC32X4_RESET, 0x01); | ||
659 | |||
660 | /* Power platform configuration */ | ||
661 | if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) { | ||
662 | snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN | | ||
663 | AIC32X4_MICBIAS_2075V); | ||
664 | } | ||
665 | if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) { | ||
666 | snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE); | ||
667 | } | ||
668 | if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) { | ||
669 | snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN); | ||
670 | } | ||
671 | tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE); | ||
672 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) { | ||
673 | tmp_reg |= AIC32X4_LDOIN_18_36; | ||
674 | } | ||
675 | if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) { | ||
676 | tmp_reg |= AIC32X4_LDOIN2HP; | ||
677 | } | ||
678 | snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg); | ||
679 | |||
680 | /* Do DACs need to be swapped? */ | ||
681 | if (aic32x4->swapdacs) { | ||
682 | snd_soc_write(codec, AIC32X4_DACSETUP, AIC32X4_LDAC2RCHN | AIC32X4_RDAC2LCHN); | ||
683 | } else { | ||
684 | snd_soc_write(codec, AIC32X4_DACSETUP, AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN); | ||
685 | } | ||
686 | |||
687 | /* Mic PGA routing */ | ||
688 | if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) { | ||
689 | snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K); | ||
690 | } | ||
691 | if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) { | ||
692 | snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K); | ||
693 | } | ||
694 | |||
695 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
696 | snd_soc_add_controls(codec, aic32x4_snd_controls, | ||
697 | ARRAY_SIZE(aic32x4_snd_controls)); | ||
698 | aic32x4_add_widgets(codec); | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | static int aic32x4_remove(struct snd_soc_codec *codec) | ||
704 | { | ||
705 | aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
706 | return 0; | ||
707 | } | ||
708 | |||
709 | static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = { | ||
710 | .read = aic32x4_read, | ||
711 | .write = aic32x4_write, | ||
712 | .probe = aic32x4_probe, | ||
713 | .remove = aic32x4_remove, | ||
714 | .suspend = aic32x4_suspend, | ||
715 | .resume = aic32x4_resume, | ||
716 | .set_bias_level = aic32x4_set_bias_level, | ||
717 | }; | ||
718 | |||
719 | static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c, | ||
720 | const struct i2c_device_id *id) | ||
721 | { | ||
722 | struct aic32x4_pdata *pdata = i2c->dev.platform_data; | ||
723 | struct aic32x4_priv *aic32x4; | ||
724 | int ret; | ||
725 | |||
726 | aic32x4 = kzalloc(sizeof(struct aic32x4_priv), GFP_KERNEL); | ||
727 | if (aic32x4 == NULL) | ||
728 | return -ENOMEM; | ||
729 | |||
730 | aic32x4->control_data = i2c; | ||
731 | i2c_set_clientdata(i2c, aic32x4); | ||
732 | |||
733 | if (pdata) { | ||
734 | aic32x4->power_cfg = pdata->power_cfg; | ||
735 | aic32x4->swapdacs = pdata->swapdacs; | ||
736 | aic32x4->micpga_routing = pdata->micpga_routing; | ||
737 | } else { | ||
738 | aic32x4->power_cfg = 0; | ||
739 | aic32x4->swapdacs = false; | ||
740 | aic32x4->micpga_routing = 0; | ||
741 | } | ||
742 | |||
743 | ret = snd_soc_register_codec(&i2c->dev, | ||
744 | &soc_codec_dev_aic32x4, &aic32x4_dai, 1); | ||
745 | if (ret < 0) | ||
746 | kfree(aic32x4); | ||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | static __devexit int aic32x4_i2c_remove(struct i2c_client *client) | ||
751 | { | ||
752 | snd_soc_unregister_codec(&client->dev); | ||
753 | kfree(i2c_get_clientdata(client)); | ||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | static const struct i2c_device_id aic32x4_i2c_id[] = { | ||
758 | { "tlv320aic32x4", 0 }, | ||
759 | { } | ||
760 | }; | ||
761 | MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id); | ||
762 | |||
763 | static struct i2c_driver aic32x4_i2c_driver = { | ||
764 | .driver = { | ||
765 | .name = "tlv320aic32x4", | ||
766 | .owner = THIS_MODULE, | ||
767 | }, | ||
768 | .probe = aic32x4_i2c_probe, | ||
769 | .remove = __devexit_p(aic32x4_i2c_remove), | ||
770 | .id_table = aic32x4_i2c_id, | ||
771 | }; | ||
772 | |||
773 | static int __init aic32x4_modinit(void) | ||
774 | { | ||
775 | int ret = 0; | ||
776 | |||
777 | ret = i2c_add_driver(&aic32x4_i2c_driver); | ||
778 | if (ret != 0) { | ||
779 | printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n", | ||
780 | ret); | ||
781 | } | ||
782 | return ret; | ||
783 | } | ||
784 | module_init(aic32x4_modinit); | ||
785 | |||
786 | static void __exit aic32x4_exit(void) | ||
787 | { | ||
788 | i2c_del_driver(&aic32x4_i2c_driver); | ||
789 | } | ||
790 | module_exit(aic32x4_exit); | ||
791 | |||
792 | MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); | ||
793 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); | ||
794 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h new file mode 100644 index 000000000000..aae2b2440398 --- /dev/null +++ b/sound/soc/codecs/tlv320aic32x4.h | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * tlv320aic32x4.h | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | |||
10 | #ifndef _TLV320AIC32X4_H | ||
11 | #define _TLV320AIC32X4_H | ||
12 | |||
13 | /* tlv320aic32x4 register space (in decimal to match datasheet) */ | ||
14 | |||
15 | #define AIC32X4_PAGE1 128 | ||
16 | |||
17 | #define AIC32X4_PSEL 0 | ||
18 | #define AIC32X4_RESET 1 | ||
19 | #define AIC32X4_CLKMUX 4 | ||
20 | #define AIC32X4_PLLPR 5 | ||
21 | #define AIC32X4_PLLJ 6 | ||
22 | #define AIC32X4_PLLDMSB 7 | ||
23 | #define AIC32X4_PLLDLSB 8 | ||
24 | #define AIC32X4_NDAC 11 | ||
25 | #define AIC32X4_MDAC 12 | ||
26 | #define AIC32X4_DOSRMSB 13 | ||
27 | #define AIC32X4_DOSRLSB 14 | ||
28 | #define AIC32X4_NADC 18 | ||
29 | #define AIC32X4_MADC 19 | ||
30 | #define AIC32X4_AOSR 20 | ||
31 | #define AIC32X4_CLKMUX2 25 | ||
32 | #define AIC32X4_CLKOUTM 26 | ||
33 | #define AIC32X4_IFACE1 27 | ||
34 | #define AIC32X4_IFACE2 28 | ||
35 | #define AIC32X4_IFACE3 29 | ||
36 | #define AIC32X4_BCLKN 30 | ||
37 | #define AIC32X4_IFACE4 31 | ||
38 | #define AIC32X4_IFACE5 32 | ||
39 | #define AIC32X4_IFACE6 33 | ||
40 | #define AIC32X4_DOUTCTL 53 | ||
41 | #define AIC32X4_DINCTL 54 | ||
42 | #define AIC32X4_DACSPB 60 | ||
43 | #define AIC32X4_ADCSPB 61 | ||
44 | #define AIC32X4_DACSETUP 63 | ||
45 | #define AIC32X4_DACMUTE 64 | ||
46 | #define AIC32X4_LDACVOL 65 | ||
47 | #define AIC32X4_RDACVOL 66 | ||
48 | #define AIC32X4_ADCSETUP 81 | ||
49 | #define AIC32X4_ADCFGA 82 | ||
50 | #define AIC32X4_LADCVOL 83 | ||
51 | #define AIC32X4_RADCVOL 84 | ||
52 | #define AIC32X4_LAGC1 86 | ||
53 | #define AIC32X4_LAGC2 87 | ||
54 | #define AIC32X4_LAGC3 88 | ||
55 | #define AIC32X4_LAGC4 89 | ||
56 | #define AIC32X4_LAGC5 90 | ||
57 | #define AIC32X4_LAGC6 91 | ||
58 | #define AIC32X4_LAGC7 92 | ||
59 | #define AIC32X4_RAGC1 94 | ||
60 | #define AIC32X4_RAGC2 95 | ||
61 | #define AIC32X4_RAGC3 96 | ||
62 | #define AIC32X4_RAGC4 97 | ||
63 | #define AIC32X4_RAGC5 98 | ||
64 | #define AIC32X4_RAGC6 99 | ||
65 | #define AIC32X4_RAGC7 100 | ||
66 | #define AIC32X4_PWRCFG (AIC32X4_PAGE1 + 1) | ||
67 | #define AIC32X4_LDOCTL (AIC32X4_PAGE1 + 2) | ||
68 | #define AIC32X4_OUTPWRCTL (AIC32X4_PAGE1 + 9) | ||
69 | #define AIC32X4_CMMODE (AIC32X4_PAGE1 + 10) | ||
70 | #define AIC32X4_HPLROUTE (AIC32X4_PAGE1 + 12) | ||
71 | #define AIC32X4_HPRROUTE (AIC32X4_PAGE1 + 13) | ||
72 | #define AIC32X4_LOLROUTE (AIC32X4_PAGE1 + 14) | ||
73 | #define AIC32X4_LORROUTE (AIC32X4_PAGE1 + 15) | ||
74 | #define AIC32X4_HPLGAIN (AIC32X4_PAGE1 + 16) | ||
75 | #define AIC32X4_HPRGAIN (AIC32X4_PAGE1 + 17) | ||
76 | #define AIC32X4_LOLGAIN (AIC32X4_PAGE1 + 18) | ||
77 | #define AIC32X4_LORGAIN (AIC32X4_PAGE1 + 19) | ||
78 | #define AIC32X4_HEADSTART (AIC32X4_PAGE1 + 20) | ||
79 | #define AIC32X4_MICBIAS (AIC32X4_PAGE1 + 51) | ||
80 | #define AIC32X4_LMICPGAPIN (AIC32X4_PAGE1 + 52) | ||
81 | #define AIC32X4_LMICPGANIN (AIC32X4_PAGE1 + 54) | ||
82 | #define AIC32X4_RMICPGAPIN (AIC32X4_PAGE1 + 55) | ||
83 | #define AIC32X4_RMICPGANIN (AIC32X4_PAGE1 + 57) | ||
84 | #define AIC32X4_FLOATINGINPUT (AIC32X4_PAGE1 + 58) | ||
85 | #define AIC32X4_LMICPGAVOL (AIC32X4_PAGE1 + 59) | ||
86 | #define AIC32X4_RMICPGAVOL (AIC32X4_PAGE1 + 60) | ||
87 | |||
88 | #define AIC32X4_FREQ_12000000 12000000 | ||
89 | #define AIC32X4_FREQ_24000000 24000000 | ||
90 | #define AIC32X4_FREQ_25000000 25000000 | ||
91 | |||
92 | #define AIC32X4_WORD_LEN_16BITS 0x00 | ||
93 | #define AIC32X4_WORD_LEN_20BITS 0x01 | ||
94 | #define AIC32X4_WORD_LEN_24BITS 0x02 | ||
95 | #define AIC32X4_WORD_LEN_32BITS 0x03 | ||
96 | |||
97 | #define AIC32X4_I2S_MODE 0x00 | ||
98 | #define AIC32X4_DSP_MODE 0x01 | ||
99 | #define AIC32X4_RIGHT_JUSTIFIED_MODE 0x02 | ||
100 | #define AIC32X4_LEFT_JUSTIFIED_MODE 0x03 | ||
101 | |||
102 | #define AIC32X4_AVDDWEAKDISABLE 0x08 | ||
103 | #define AIC32X4_LDOCTLEN 0x01 | ||
104 | |||
105 | #define AIC32X4_LDOIN_18_36 0x01 | ||
106 | #define AIC32X4_LDOIN2HP 0x02 | ||
107 | |||
108 | #define AIC32X4_DACSPBLOCK_MASK 0x1f | ||
109 | #define AIC32X4_ADCSPBLOCK_MASK 0x1f | ||
110 | |||
111 | #define AIC32X4_PLLJ_SHIFT 6 | ||
112 | #define AIC32X4_DOSRMSB_SHIFT 4 | ||
113 | |||
114 | #define AIC32X4_PLLCLKIN 0x03 | ||
115 | |||
116 | #define AIC32X4_MICBIAS_LDOIN 0x08 | ||
117 | #define AIC32X4_MICBIAS_2075V 0x60 | ||
118 | |||
119 | #define AIC32X4_LMICPGANIN_IN2R_10K 0x10 | ||
120 | #define AIC32X4_RMICPGANIN_IN1L_10K 0x10 | ||
121 | |||
122 | #define AIC32X4_LMICPGAVOL_NOGAIN 0x80 | ||
123 | #define AIC32X4_RMICPGAVOL_NOGAIN 0x80 | ||
124 | |||
125 | #define AIC32X4_BCLKMASTER 0x08 | ||
126 | #define AIC32X4_WCLKMASTER 0x04 | ||
127 | #define AIC32X4_PLLEN (0x01 << 7) | ||
128 | #define AIC32X4_NDACEN (0x01 << 7) | ||
129 | #define AIC32X4_MDACEN (0x01 << 7) | ||
130 | #define AIC32X4_NADCEN (0x01 << 7) | ||
131 | #define AIC32X4_MADCEN (0x01 << 7) | ||
132 | #define AIC32X4_BCLKEN (0x01 << 7) | ||
133 | #define AIC32X4_DACEN (0x03 << 6) | ||
134 | #define AIC32X4_RDAC2LCHN (0x02 << 2) | ||
135 | #define AIC32X4_LDAC2RCHN (0x02 << 4) | ||
136 | #define AIC32X4_LDAC2LCHN (0x01 << 4) | ||
137 | #define AIC32X4_RDAC2RCHN (0x01 << 2) | ||
138 | |||
139 | #define AIC32X4_SSTEP2WCLK 0x01 | ||
140 | #define AIC32X4_MUTEON 0x0C | ||
141 | #define AIC32X4_DACMOD2BCLK 0x01 | ||
142 | |||
143 | #endif /* _TLV320AIC32X4_H */ | ||
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 71d7be8ac488..00b6d87e7bdb 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1615,6 +1615,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = { | |||
1615 | }, | 1615 | }, |
1616 | { }, | 1616 | { }, |
1617 | }; | 1617 | }; |
1618 | MODULE_DEVICE_TABLE(i2c, tlv320dac33_i2c_id); | ||
1618 | 1619 | ||
1619 | static struct i2c_driver tlv320dac33_i2c_driver = { | 1620 | static struct i2c_driver tlv320dac33_i2c_driver = { |
1620 | .driver = { | 1621 | .driver = { |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 4bbf1b15a493..482fcdb59bfa 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -724,8 +724,8 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w, | |||
724 | return 0; | 724 | return 0; |
725 | } | 725 | } |
726 | 726 | ||
727 | void twl6040_hs_jack_report(struct snd_soc_codec *codec, | 727 | static void twl6040_hs_jack_report(struct snd_soc_codec *codec, |
728 | struct snd_soc_jack *jack, int report) | 728 | struct snd_soc_jack *jack, int report) |
729 | { | 729 | { |
730 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | 730 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); |
731 | int status; | 731 | int status; |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 80ddf4fd23db..a3b9cbb20ee9 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -836,24 +836,25 @@ static void wm2000_i2c_shutdown(struct i2c_client *i2c) | |||
836 | } | 836 | } |
837 | 837 | ||
838 | #ifdef CONFIG_PM | 838 | #ifdef CONFIG_PM |
839 | static int wm2000_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg) | 839 | static int wm2000_i2c_suspend(struct device *dev) |
840 | { | 840 | { |
841 | struct i2c_client *i2c = to_i2c_client(dev); | ||
841 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | 842 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); |
842 | 843 | ||
843 | return wm2000_anc_transition(wm2000, ANC_OFF); | 844 | return wm2000_anc_transition(wm2000, ANC_OFF); |
844 | } | 845 | } |
845 | 846 | ||
846 | static int wm2000_i2c_resume(struct i2c_client *i2c) | 847 | static int wm2000_i2c_resume(struct device *dev) |
847 | { | 848 | { |
849 | struct i2c_client *i2c = to_i2c_client(dev); | ||
848 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | 850 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); |
849 | 851 | ||
850 | return wm2000_anc_set_mode(wm2000); | 852 | return wm2000_anc_set_mode(wm2000); |
851 | } | 853 | } |
852 | #else | ||
853 | #define wm2000_i2c_suspend NULL | ||
854 | #define wm2000_i2c_resume NULL | ||
855 | #endif | 854 | #endif |
856 | 855 | ||
856 | static SIMPLE_DEV_PM_OPS(wm2000_pm, wm2000_i2c_suspend, wm2000_i2c_resume); | ||
857 | |||
857 | static const struct i2c_device_id wm2000_i2c_id[] = { | 858 | static const struct i2c_device_id wm2000_i2c_id[] = { |
858 | { "wm2000", 0 }, | 859 | { "wm2000", 0 }, |
859 | { } | 860 | { } |
@@ -864,11 +865,10 @@ static struct i2c_driver wm2000_i2c_driver = { | |||
864 | .driver = { | 865 | .driver = { |
865 | .name = "wm2000", | 866 | .name = "wm2000", |
866 | .owner = THIS_MODULE, | 867 | .owner = THIS_MODULE, |
868 | .pm = &wm2000_pm, | ||
867 | }, | 869 | }, |
868 | .probe = wm2000_i2c_probe, | 870 | .probe = wm2000_i2c_probe, |
869 | .remove = __devexit_p(wm2000_i2c_remove), | 871 | .remove = __devexit_p(wm2000_i2c_remove), |
870 | .suspend = wm2000_i2c_suspend, | ||
871 | .resume = wm2000_i2c_resume, | ||
872 | .shutdown = wm2000_i2c_shutdown, | 872 | .shutdown = wm2000_i2c_shutdown, |
873 | .id_table = wm2000_i2c_id, | 873 | .id_table = wm2000_i2c_id, |
874 | }; | 874 | }; |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 5eb2f501ce32..4fd4d8dca0fc 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -58,7 +58,7 @@ static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { | |||
58 | 0x0000, /* R8 - ZERO_DETECT */ | 58 | 0x0000, /* R8 - ZERO_DETECT */ |
59 | }; | 59 | }; |
60 | 60 | ||
61 | static int wm8523_volatile_register(unsigned int reg) | 61 | static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
62 | { | 62 | { |
63 | switch (reg) { | 63 | switch (reg) { |
64 | case WM8523_DEVICE_ID: | 64 | case WM8523_DEVICE_ID: |
@@ -414,7 +414,6 @@ static int wm8523_resume(struct snd_soc_codec *codec) | |||
414 | static int wm8523_probe(struct snd_soc_codec *codec) | 414 | static int wm8523_probe(struct snd_soc_codec *codec) |
415 | { | 415 | { |
416 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 416 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
417 | u16 *reg_cache = codec->reg_cache; | ||
418 | int ret, i; | 417 | int ret, i; |
419 | 418 | ||
420 | codec->hw_write = (hw_write_t)i2c_master_send; | 419 | codec->hw_write = (hw_write_t)i2c_master_send; |
@@ -471,8 +470,9 @@ static int wm8523_probe(struct snd_soc_codec *codec) | |||
471 | } | 470 | } |
472 | 471 | ||
473 | /* Change some default settings - latch VU and enable ZC */ | 472 | /* Change some default settings - latch VU and enable ZC */ |
474 | reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; | 473 | snd_soc_update_bits(codec, WM8523_DAC_GAINR, |
475 | reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; | 474 | WM8523_DACR_VU, WM8523_DACR_VU); |
475 | snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC); | ||
476 | 476 | ||
477 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 477 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
478 | 478 | ||
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 494f2d31d75b..25af901fe813 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -421,7 +421,6 @@ static int wm8741_resume(struct snd_soc_codec *codec) | |||
421 | static int wm8741_probe(struct snd_soc_codec *codec) | 421 | static int wm8741_probe(struct snd_soc_codec *codec) |
422 | { | 422 | { |
423 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 423 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
424 | u16 *reg_cache = codec->reg_cache; | ||
425 | int ret = 0; | 424 | int ret = 0; |
426 | 425 | ||
427 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); | 426 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); |
@@ -437,10 +436,14 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
437 | } | 436 | } |
438 | 437 | ||
439 | /* Change some default settings - latch VU */ | 438 | /* Change some default settings - latch VU */ |
440 | reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL; | 439 | snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION, |
441 | reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM; | 440 | WM8741_UPDATELL, WM8741_UPDATELL); |
442 | reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL; | 441 | snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION, |
443 | reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM; | 442 | WM8741_UPDATELM, WM8741_UPDATELM); |
443 | snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION, | ||
444 | WM8741_UPDATERL, WM8741_UPDATERL); | ||
445 | snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION, | ||
446 | WM8741_UPDATERM, WM8741_UPDATERM); | ||
444 | 447 | ||
445 | snd_soc_add_controls(codec, wm8741_snd_controls, | 448 | snd_soc_add_controls(codec, wm8741_snd_controls, |
446 | ARRAY_SIZE(wm8741_snd_controls)); | 449 | ARRAY_SIZE(wm8741_snd_controls)); |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 79b02ae125c5..3f09deea8d9d 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -55,8 +55,10 @@ static int caps_charge = 2000; | |||
55 | module_param(caps_charge, int, 0); | 55 | module_param(caps_charge, int, 0); |
56 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); | 56 | MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); |
57 | 57 | ||
58 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, | 58 | static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec, |
59 | struct snd_soc_dai *dai, unsigned int hifi); | 59 | unsigned int fmt); |
60 | static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec, | ||
61 | unsigned int fmt); | ||
60 | 62 | ||
61 | /* | 63 | /* |
62 | * wm8753 register cache | 64 | * wm8753 register cache |
@@ -87,6 +89,10 @@ struct wm8753_priv { | |||
87 | enum snd_soc_control_type control_type; | 89 | enum snd_soc_control_type control_type; |
88 | unsigned int sysclk; | 90 | unsigned int sysclk; |
89 | unsigned int pcmclk; | 91 | unsigned int pcmclk; |
92 | |||
93 | unsigned int voice_fmt; | ||
94 | unsigned int hifi_fmt; | ||
95 | |||
90 | int dai_func; | 96 | int dai_func; |
91 | }; | 97 | }; |
92 | 98 | ||
@@ -170,9 +176,9 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol, | |||
170 | struct snd_ctl_elem_value *ucontrol) | 176 | struct snd_ctl_elem_value *ucontrol) |
171 | { | 177 | { |
172 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 178 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
173 | int mode = snd_soc_read(codec, WM8753_IOCTL); | 179 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
174 | 180 | ||
175 | ucontrol->value.integer.value[0] = (mode & 0xc) >> 2; | 181 | ucontrol->value.integer.value[0] = wm8753->dai_func; |
176 | return 0; | 182 | return 0; |
177 | } | 183 | } |
178 | 184 | ||
@@ -180,16 +186,26 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol, | |||
180 | struct snd_ctl_elem_value *ucontrol) | 186 | struct snd_ctl_elem_value *ucontrol) |
181 | { | 187 | { |
182 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 188 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
183 | int mode = snd_soc_read(codec, WM8753_IOCTL); | ||
184 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 189 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
190 | u16 ioctl; | ||
191 | |||
192 | if (codec->active) | ||
193 | return -EBUSY; | ||
194 | |||
195 | ioctl = snd_soc_read(codec, WM8753_IOCTL); | ||
196 | |||
197 | wm8753->dai_func = ucontrol->value.integer.value[0]; | ||
198 | |||
199 | if (((ioctl >> 2) & 0x3) == wm8753->dai_func) | ||
200 | return 1; | ||
201 | |||
202 | ioctl = (ioctl & 0x1f3) | (wm8753->dai_func << 2); | ||
203 | snd_soc_write(codec, WM8753_IOCTL, ioctl); | ||
185 | 204 | ||
186 | if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) | ||
187 | return 0; | ||
188 | 205 | ||
189 | mode &= 0xfff3; | 206 | wm8753_hifi_write_dai_fmt(codec, wm8753->hifi_fmt); |
190 | mode |= (ucontrol->value.integer.value[0] << 2); | 207 | wm8753_voice_write_dai_fmt(codec, wm8753->voice_fmt); |
191 | 208 | ||
192 | wm8753->dai_func = ucontrol->value.integer.value[0]; | ||
193 | return 1; | 209 | return 1; |
194 | } | 210 | } |
195 | 211 | ||
@@ -828,10 +844,9 @@ static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
828 | /* | 844 | /* |
829 | * Set's ADC and Voice DAC format. | 845 | * Set's ADC and Voice DAC format. |
830 | */ | 846 | */ |
831 | static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, | 847 | static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec *codec, |
832 | unsigned int fmt) | 848 | unsigned int fmt) |
833 | { | 849 | { |
834 | struct snd_soc_codec *codec = codec_dai->codec; | ||
835 | u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec; | 850 | u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec; |
836 | 851 | ||
837 | /* interface format */ | 852 | /* interface format */ |
@@ -858,13 +873,6 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
858 | return 0; | 873 | return 0; |
859 | } | 874 | } |
860 | 875 | ||
861 | static int wm8753_pcm_startup(struct snd_pcm_substream *substream, | ||
862 | struct snd_soc_dai *dai) | ||
863 | { | ||
864 | wm8753_set_dai_mode(dai->codec, dai, 0); | ||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | /* | 876 | /* |
869 | * Set PCM DAI bit size and sample rate. | 877 | * Set PCM DAI bit size and sample rate. |
870 | */ | 878 | */ |
@@ -905,10 +913,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, | |||
905 | /* | 913 | /* |
906 | * Set's PCM dai fmt and BCLK. | 914 | * Set's PCM dai fmt and BCLK. |
907 | */ | 915 | */ |
908 | static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai, | 916 | static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec *codec, |
909 | unsigned int fmt) | 917 | unsigned int fmt) |
910 | { | 918 | { |
911 | struct snd_soc_codec *codec = codec_dai->codec; | ||
912 | u16 voice, ioctl; | 919 | u16 voice, ioctl; |
913 | 920 | ||
914 | voice = snd_soc_read(codec, WM8753_PCM) & 0x011f; | 921 | voice = snd_soc_read(codec, WM8753_PCM) & 0x011f; |
@@ -999,10 +1006,9 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
999 | /* | 1006 | /* |
1000 | * Set's HiFi DAC format. | 1007 | * Set's HiFi DAC format. |
1001 | */ | 1008 | */ |
1002 | static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, | 1009 | static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec *codec, |
1003 | unsigned int fmt) | 1010 | unsigned int fmt) |
1004 | { | 1011 | { |
1005 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1006 | u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0; | 1012 | u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0; |
1007 | 1013 | ||
1008 | /* interface format */ | 1014 | /* interface format */ |
@@ -1032,10 +1038,9 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1032 | /* | 1038 | /* |
1033 | * Set's I2S DAI format. | 1039 | * Set's I2S DAI format. |
1034 | */ | 1040 | */ |
1035 | static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, | 1041 | static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec *codec, |
1036 | unsigned int fmt) | 1042 | unsigned int fmt) |
1037 | { | 1043 | { |
1038 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1039 | u16 ioctl, hifi; | 1044 | u16 ioctl, hifi; |
1040 | 1045 | ||
1041 | hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; | 1046 | hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f; |
@@ -1098,13 +1103,6 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1098 | return 0; | 1103 | return 0; |
1099 | } | 1104 | } |
1100 | 1105 | ||
1101 | static int wm8753_i2s_startup(struct snd_pcm_substream *substream, | ||
1102 | struct snd_soc_dai *dai) | ||
1103 | { | ||
1104 | wm8753_set_dai_mode(dai->codec, dai, 1); | ||
1105 | return 0; | ||
1106 | } | ||
1107 | |||
1108 | /* | 1106 | /* |
1109 | * Set PCM DAI bit size and sample rate. | 1107 | * Set PCM DAI bit size and sample rate. |
1110 | */ | 1108 | */ |
@@ -1147,61 +1145,117 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, | |||
1147 | return 0; | 1145 | return 0; |
1148 | } | 1146 | } |
1149 | 1147 | ||
1150 | static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai, | 1148 | static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec *codec, |
1151 | unsigned int fmt) | 1149 | unsigned int fmt) |
1152 | { | 1150 | { |
1153 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1154 | u16 clock; | 1151 | u16 clock; |
1155 | 1152 | ||
1156 | /* set clk source as pcmclk */ | 1153 | /* set clk source as pcmclk */ |
1157 | clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; | 1154 | clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; |
1158 | snd_soc_write(codec, WM8753_CLOCK, clock); | 1155 | snd_soc_write(codec, WM8753_CLOCK, clock); |
1159 | 1156 | ||
1160 | if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) | 1157 | return wm8753_vdac_adc_set_dai_fmt(codec, fmt); |
1161 | return -EINVAL; | ||
1162 | return wm8753_pcm_set_dai_fmt(codec_dai, fmt); | ||
1163 | } | 1158 | } |
1164 | 1159 | ||
1165 | static int wm8753_mode1h_set_dai_fmt(struct snd_soc_dai *codec_dai, | 1160 | static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec *codec, |
1166 | unsigned int fmt) | 1161 | unsigned int fmt) |
1167 | { | 1162 | { |
1168 | if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) | 1163 | return wm8753_hdac_set_dai_fmt(codec, fmt); |
1169 | return -EINVAL; | ||
1170 | return wm8753_i2s_set_dai_fmt(codec_dai, fmt); | ||
1171 | } | 1164 | } |
1172 | 1165 | ||
1173 | static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai, | 1166 | static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec *codec, |
1174 | unsigned int fmt) | 1167 | unsigned int fmt) |
1175 | { | 1168 | { |
1176 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1177 | u16 clock; | 1169 | u16 clock; |
1178 | 1170 | ||
1179 | /* set clk source as pcmclk */ | 1171 | /* set clk source as pcmclk */ |
1180 | clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; | 1172 | clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; |
1181 | snd_soc_write(codec, WM8753_CLOCK, clock); | 1173 | snd_soc_write(codec, WM8753_CLOCK, clock); |
1182 | 1174 | ||
1183 | if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) | 1175 | return wm8753_vdac_adc_set_dai_fmt(codec, fmt); |
1184 | return -EINVAL; | ||
1185 | return wm8753_i2s_set_dai_fmt(codec_dai, fmt); | ||
1186 | } | 1176 | } |
1187 | 1177 | ||
1188 | static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai, | 1178 | static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec *codec, |
1189 | unsigned int fmt) | 1179 | unsigned int fmt) |
1190 | { | 1180 | { |
1191 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1192 | u16 clock; | 1181 | u16 clock; |
1193 | 1182 | ||
1194 | /* set clk source as mclk */ | 1183 | /* set clk source as mclk */ |
1195 | clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; | 1184 | clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb; |
1196 | snd_soc_write(codec, WM8753_CLOCK, clock | 0x4); | 1185 | snd_soc_write(codec, WM8753_CLOCK, clock | 0x4); |
1197 | 1186 | ||
1198 | if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0) | 1187 | if (wm8753_hdac_set_dai_fmt(codec, fmt) < 0) |
1199 | return -EINVAL; | 1188 | return -EINVAL; |
1200 | if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0) | 1189 | return wm8753_vdac_adc_set_dai_fmt(codec, fmt); |
1201 | return -EINVAL; | ||
1202 | return wm8753_i2s_set_dai_fmt(codec_dai, fmt); | ||
1203 | } | 1190 | } |
1204 | 1191 | ||
1192 | static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec, | ||
1193 | unsigned int fmt) | ||
1194 | { | ||
1195 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1196 | int ret = 0; | ||
1197 | |||
1198 | switch (wm8753->dai_func) { | ||
1199 | case 0: | ||
1200 | ret = wm8753_mode1h_set_dai_fmt(codec, fmt); | ||
1201 | break; | ||
1202 | case 1: | ||
1203 | ret = wm8753_mode2_set_dai_fmt(codec, fmt); | ||
1204 | break; | ||
1205 | case 2: | ||
1206 | case 3: | ||
1207 | ret = wm8753_mode3_4_set_dai_fmt(codec, fmt); | ||
1208 | break; | ||
1209 | default: | ||
1210 | break; | ||
1211 | } | ||
1212 | if (ret) | ||
1213 | return ret; | ||
1214 | |||
1215 | return wm8753_i2s_set_dai_fmt(codec, fmt); | ||
1216 | } | ||
1217 | |||
1218 | static int wm8753_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
1219 | unsigned int fmt) | ||
1220 | { | ||
1221 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1222 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1223 | |||
1224 | wm8753->hifi_fmt = fmt; | ||
1225 | |||
1226 | return wm8753_hifi_write_dai_fmt(codec, fmt); | ||
1227 | }; | ||
1228 | |||
1229 | static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec, | ||
1230 | unsigned int fmt) | ||
1231 | { | ||
1232 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1233 | int ret = 0; | ||
1234 | |||
1235 | if (wm8753->dai_func != 0) | ||
1236 | return 0; | ||
1237 | |||
1238 | ret = wm8753_mode1v_set_dai_fmt(codec, fmt); | ||
1239 | if (ret) | ||
1240 | return ret; | ||
1241 | ret = wm8753_pcm_set_dai_fmt(codec, fmt); | ||
1242 | if (ret) | ||
1243 | return ret; | ||
1244 | |||
1245 | return 0; | ||
1246 | }; | ||
1247 | |||
1248 | static int wm8753_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
1249 | unsigned int fmt) | ||
1250 | { | ||
1251 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1252 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1253 | |||
1254 | wm8753->voice_fmt = fmt; | ||
1255 | |||
1256 | return wm8753_voice_write_dai_fmt(codec, fmt); | ||
1257 | }; | ||
1258 | |||
1205 | static int wm8753_mute(struct snd_soc_dai *dai, int mute) | 1259 | static int wm8753_mute(struct snd_soc_dai *dai, int mute) |
1206 | { | 1260 | { |
1207 | struct snd_soc_codec *codec = dai->codec; | 1261 | struct snd_soc_codec *codec = dai->codec; |
@@ -1268,57 +1322,25 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
1268 | * 3. Voice disabled - HIFI over HIFI | 1322 | * 3. Voice disabled - HIFI over HIFI |
1269 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture | 1323 | * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture |
1270 | */ | 1324 | */ |
1271 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { | 1325 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = { |
1272 | .startup = wm8753_i2s_startup, | ||
1273 | .hw_params = wm8753_i2s_hw_params, | 1326 | .hw_params = wm8753_i2s_hw_params, |
1274 | .digital_mute = wm8753_mute, | 1327 | .digital_mute = wm8753_mute, |
1275 | .set_fmt = wm8753_mode1h_set_dai_fmt, | 1328 | .set_fmt = wm8753_hifi_set_dai_fmt, |
1276 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1277 | .set_pll = wm8753_set_dai_pll, | ||
1278 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1279 | }; | ||
1280 | |||
1281 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { | ||
1282 | .startup = wm8753_pcm_startup, | ||
1283 | .hw_params = wm8753_pcm_hw_params, | ||
1284 | .digital_mute = wm8753_mute, | ||
1285 | .set_fmt = wm8753_mode1v_set_dai_fmt, | ||
1286 | .set_clkdiv = wm8753_set_dai_clkdiv, | 1329 | .set_clkdiv = wm8753_set_dai_clkdiv, |
1287 | .set_pll = wm8753_set_dai_pll, | 1330 | .set_pll = wm8753_set_dai_pll, |
1288 | .set_sysclk = wm8753_set_dai_sysclk, | 1331 | .set_sysclk = wm8753_set_dai_sysclk, |
1289 | }; | 1332 | }; |
1290 | 1333 | ||
1291 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { | 1334 | static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = { |
1292 | .startup = wm8753_pcm_startup, | ||
1293 | .hw_params = wm8753_pcm_hw_params, | 1335 | .hw_params = wm8753_pcm_hw_params, |
1294 | .digital_mute = wm8753_mute, | 1336 | .digital_mute = wm8753_mute, |
1295 | .set_fmt = wm8753_mode2_set_dai_fmt, | 1337 | .set_fmt = wm8753_voice_set_dai_fmt, |
1296 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1297 | .set_pll = wm8753_set_dai_pll, | ||
1298 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1299 | }; | ||
1300 | |||
1301 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { | ||
1302 | .startup = wm8753_i2s_startup, | ||
1303 | .hw_params = wm8753_i2s_hw_params, | ||
1304 | .digital_mute = wm8753_mute, | ||
1305 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | ||
1306 | .set_clkdiv = wm8753_set_dai_clkdiv, | ||
1307 | .set_pll = wm8753_set_dai_pll, | ||
1308 | .set_sysclk = wm8753_set_dai_sysclk, | ||
1309 | }; | ||
1310 | |||
1311 | static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { | ||
1312 | .startup = wm8753_i2s_startup, | ||
1313 | .hw_params = wm8753_i2s_hw_params, | ||
1314 | .digital_mute = wm8753_mute, | ||
1315 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | ||
1316 | .set_clkdiv = wm8753_set_dai_clkdiv, | 1338 | .set_clkdiv = wm8753_set_dai_clkdiv, |
1317 | .set_pll = wm8753_set_dai_pll, | 1339 | .set_pll = wm8753_set_dai_pll, |
1318 | .set_sysclk = wm8753_set_dai_sysclk, | 1340 | .set_sysclk = wm8753_set_dai_sysclk, |
1319 | }; | 1341 | }; |
1320 | 1342 | ||
1321 | static struct snd_soc_dai_driver wm8753_all_dai[] = { | 1343 | static struct snd_soc_dai_driver wm8753_dai[] = { |
1322 | /* DAI HiFi mode 1 */ | 1344 | /* DAI HiFi mode 1 */ |
1323 | { .name = "wm8753-hifi", | 1345 | { .name = "wm8753-hifi", |
1324 | .playback = { | 1346 | .playback = { |
@@ -1326,14 +1348,16 @@ static struct snd_soc_dai_driver wm8753_all_dai[] = { | |||
1326 | .channels_min = 1, | 1348 | .channels_min = 1, |
1327 | .channels_max = 2, | 1349 | .channels_max = 2, |
1328 | .rates = WM8753_RATES, | 1350 | .rates = WM8753_RATES, |
1329 | .formats = WM8753_FORMATS}, | 1351 | .formats = WM8753_FORMATS |
1352 | }, | ||
1330 | .capture = { /* dummy for fast DAI switching */ | 1353 | .capture = { /* dummy for fast DAI switching */ |
1331 | .stream_name = "Capture", | 1354 | .stream_name = "Capture", |
1332 | .channels_min = 1, | 1355 | .channels_min = 1, |
1333 | .channels_max = 2, | 1356 | .channels_max = 2, |
1334 | .rates = WM8753_RATES, | 1357 | .rates = WM8753_RATES, |
1335 | .formats = WM8753_FORMATS}, | 1358 | .formats = WM8753_FORMATS |
1336 | .ops = &wm8753_dai_ops_hifi_mode1, | 1359 | }, |
1360 | .ops = &wm8753_dai_ops_hifi_mode, | ||
1337 | }, | 1361 | }, |
1338 | /* DAI Voice mode 1 */ | 1362 | /* DAI Voice mode 1 */ |
1339 | { .name = "wm8753-voice", | 1363 | { .name = "wm8753-voice", |
@@ -1342,97 +1366,19 @@ static struct snd_soc_dai_driver wm8753_all_dai[] = { | |||
1342 | .channels_min = 1, | 1366 | .channels_min = 1, |
1343 | .channels_max = 1, | 1367 | .channels_max = 1, |
1344 | .rates = WM8753_RATES, | 1368 | .rates = WM8753_RATES, |
1345 | .formats = WM8753_FORMATS,}, | 1369 | .formats = WM8753_FORMATS, |
1346 | .capture = { | 1370 | }, |
1347 | .stream_name = "Capture", | ||
1348 | .channels_min = 1, | ||
1349 | .channels_max = 2, | ||
1350 | .rates = WM8753_RATES, | ||
1351 | .formats = WM8753_FORMATS,}, | ||
1352 | .ops = &wm8753_dai_ops_voice_mode1, | ||
1353 | }, | ||
1354 | /* DAI HiFi mode 2 - dummy */ | ||
1355 | { .name = "wm8753-hifi", | ||
1356 | }, | ||
1357 | /* DAI Voice mode 2 */ | ||
1358 | { .name = "wm8753-voice", | ||
1359 | .playback = { | ||
1360 | .stream_name = "Voice Playback", | ||
1361 | .channels_min = 1, | ||
1362 | .channels_max = 1, | ||
1363 | .rates = WM8753_RATES, | ||
1364 | .formats = WM8753_FORMATS,}, | ||
1365 | .capture = { | ||
1366 | .stream_name = "Capture", | ||
1367 | .channels_min = 1, | ||
1368 | .channels_max = 2, | ||
1369 | .rates = WM8753_RATES, | ||
1370 | .formats = WM8753_FORMATS,}, | ||
1371 | .ops = &wm8753_dai_ops_voice_mode2, | ||
1372 | }, | ||
1373 | /* DAI HiFi mode 3 */ | ||
1374 | { .name = "wm8753-hifi", | ||
1375 | .playback = { | ||
1376 | .stream_name = "HiFi Playback", | ||
1377 | .channels_min = 1, | ||
1378 | .channels_max = 2, | ||
1379 | .rates = WM8753_RATES, | ||
1380 | .formats = WM8753_FORMATS,}, | ||
1381 | .capture = { | ||
1382 | .stream_name = "Capture", | ||
1383 | .channels_min = 1, | ||
1384 | .channels_max = 2, | ||
1385 | .rates = WM8753_RATES, | ||
1386 | .formats = WM8753_FORMATS,}, | ||
1387 | .ops = &wm8753_dai_ops_hifi_mode3, | ||
1388 | }, | ||
1389 | /* DAI Voice mode 3 - dummy */ | ||
1390 | { .name = "wm8753-voice", | ||
1391 | }, | ||
1392 | /* DAI HiFi mode 4 */ | ||
1393 | { .name = "wm8753-hifi", | ||
1394 | .playback = { | ||
1395 | .stream_name = "HiFi Playback", | ||
1396 | .channels_min = 1, | ||
1397 | .channels_max = 2, | ||
1398 | .rates = WM8753_RATES, | ||
1399 | .formats = WM8753_FORMATS,}, | ||
1400 | .capture = { | 1371 | .capture = { |
1401 | .stream_name = "Capture", | 1372 | .stream_name = "Capture", |
1402 | .channels_min = 1, | 1373 | .channels_min = 1, |
1403 | .channels_max = 2, | 1374 | .channels_max = 2, |
1404 | .rates = WM8753_RATES, | 1375 | .rates = WM8753_RATES, |
1405 | .formats = WM8753_FORMATS,}, | 1376 | .formats = WM8753_FORMATS, |
1406 | .ops = &wm8753_dai_ops_hifi_mode4, | ||
1407 | }, | ||
1408 | /* DAI Voice mode 4 - dummy */ | ||
1409 | { .name = "wm8753-voice", | ||
1410 | }, | ||
1411 | }; | ||
1412 | |||
1413 | static struct snd_soc_dai_driver wm8753_dai[] = { | ||
1414 | { | ||
1415 | .name = "wm8753-aif0", | ||
1416 | }, | ||
1417 | { | ||
1418 | .name = "wm8753-aif1", | ||
1419 | }, | 1377 | }, |
1378 | .ops = &wm8753_dai_ops_voice_mode, | ||
1379 | }, | ||
1420 | }; | 1380 | }; |
1421 | 1381 | ||
1422 | static void wm8753_set_dai_mode(struct snd_soc_codec *codec, | ||
1423 | struct snd_soc_dai *dai, unsigned int hifi) | ||
1424 | { | ||
1425 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1426 | |||
1427 | if (wm8753->dai_func < 4) { | ||
1428 | if (hifi) | ||
1429 | dai->driver = &wm8753_all_dai[wm8753->dai_func << 1]; | ||
1430 | else | ||
1431 | dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1]; | ||
1432 | } | ||
1433 | snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func); | ||
1434 | } | ||
1435 | |||
1436 | static void wm8753_work(struct work_struct *work) | 1382 | static void wm8753_work(struct work_struct *work) |
1437 | { | 1383 | { |
1438 | struct snd_soc_dapm_context *dapm = | 1384 | struct snd_soc_dapm_context *dapm = |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 6dae1b40c9f7..6785688f8806 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -175,7 +175,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol, | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static int wm8804_volatile(unsigned int reg) | 178 | static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg) |
179 | { | 179 | { |
180 | switch (reg) { | 180 | switch (reg) { |
181 | case WM8804_RST_DEVID1: | 181 | case WM8804_RST_DEVID1: |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index cd0959926d12..449ea09a193d 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -180,7 +180,7 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { | |||
180 | /* Remaining registers all zero */ | 180 | /* Remaining registers all zero */ |
181 | }; | 181 | }; |
182 | 182 | ||
183 | static int wm8900_volatile_register(unsigned int reg) | 183 | static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
184 | { | 184 | { |
185 | switch (reg) { | 185 | switch (reg) { |
186 | case WM8900_REG_ID: | 186 | case WM8900_REG_ID: |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 017d99ceb42e..ae1cadfae84c 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * wm8903.c -- WM8903 ALSA SoC Audio driver | 2 | * wm8903.c -- WM8903 ALSA SoC Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008 Wolfson Microelectronics | 4 | * Copyright 2008 Wolfson Microelectronics |
5 | * Copyright 2011 NVIDIA, Inc. | ||
5 | * | 6 | * |
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 7 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7 | * | 8 | * |
@@ -19,6 +20,7 @@ | |||
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/completion.h> | 21 | #include <linux/completion.h> |
21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/gpio.h> | ||
22 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
23 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
24 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
@@ -213,6 +215,7 @@ static u16 wm8903_reg_defaults[] = { | |||
213 | }; | 215 | }; |
214 | 216 | ||
215 | struct wm8903_priv { | 217 | struct wm8903_priv { |
218 | struct snd_soc_codec *codec; | ||
216 | 219 | ||
217 | int sysclk; | 220 | int sysclk; |
218 | int irq; | 221 | int irq; |
@@ -220,25 +223,36 @@ struct wm8903_priv { | |||
220 | int fs; | 223 | int fs; |
221 | int deemph; | 224 | int deemph; |
222 | 225 | ||
226 | int dcs_pending; | ||
227 | int dcs_cache[4]; | ||
228 | |||
223 | /* Reference count */ | 229 | /* Reference count */ |
224 | int class_w_users; | 230 | int class_w_users; |
225 | 231 | ||
226 | struct completion wseq; | ||
227 | |||
228 | struct snd_soc_jack *mic_jack; | 232 | struct snd_soc_jack *mic_jack; |
229 | int mic_det; | 233 | int mic_det; |
230 | int mic_short; | 234 | int mic_short; |
231 | int mic_last_report; | 235 | int mic_last_report; |
232 | int mic_delay; | 236 | int mic_delay; |
237 | |||
238 | #ifdef CONFIG_GPIOLIB | ||
239 | struct gpio_chip gpio_chip; | ||
240 | #endif | ||
233 | }; | 241 | }; |
234 | 242 | ||
235 | static int wm8903_volatile_register(unsigned int reg) | 243 | static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
236 | { | 244 | { |
237 | switch (reg) { | 245 | switch (reg) { |
238 | case WM8903_SW_RESET_AND_ID: | 246 | case WM8903_SW_RESET_AND_ID: |
239 | case WM8903_REVISION_NUMBER: | 247 | case WM8903_REVISION_NUMBER: |
240 | case WM8903_INTERRUPT_STATUS_1: | 248 | case WM8903_INTERRUPT_STATUS_1: |
241 | case WM8903_WRITE_SEQUENCER_4: | 249 | case WM8903_WRITE_SEQUENCER_4: |
250 | case WM8903_POWER_MANAGEMENT_3: | ||
251 | case WM8903_POWER_MANAGEMENT_2: | ||
252 | case WM8903_DC_SERVO_READBACK_1: | ||
253 | case WM8903_DC_SERVO_READBACK_2: | ||
254 | case WM8903_DC_SERVO_READBACK_3: | ||
255 | case WM8903_DC_SERVO_READBACK_4: | ||
242 | return 1; | 256 | return 1; |
243 | 257 | ||
244 | default: | 258 | default: |
@@ -246,50 +260,6 @@ static int wm8903_volatile_register(unsigned int reg) | |||
246 | } | 260 | } |
247 | } | 261 | } |
248 | 262 | ||
249 | static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | ||
250 | { | ||
251 | u16 reg[5]; | ||
252 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
253 | |||
254 | BUG_ON(start > 48); | ||
255 | |||
256 | /* Enable the sequencer if it's not already on */ | ||
257 | reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0); | ||
258 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, | ||
259 | reg[0] | WM8903_WSEQ_ENA); | ||
260 | |||
261 | dev_dbg(codec->dev, "Starting sequence at %d\n", start); | ||
262 | |||
263 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, | ||
264 | start | WM8903_WSEQ_START); | ||
265 | |||
266 | /* Wait for it to complete. If we have the interrupt wired up then | ||
267 | * that will break us out of the poll early. | ||
268 | */ | ||
269 | do { | ||
270 | wait_for_completion_timeout(&wm8903->wseq, | ||
271 | msecs_to_jiffies(10)); | ||
272 | |||
273 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); | ||
274 | } while (reg[4] & WM8903_WSEQ_BUSY); | ||
275 | |||
276 | dev_dbg(codec->dev, "Sequence complete\n"); | ||
277 | |||
278 | /* Disable the sequencer again if we enabled it */ | ||
279 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache) | ||
285 | { | ||
286 | int i; | ||
287 | |||
288 | /* There really ought to be something better we can do here :/ */ | ||
289 | for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++) | ||
290 | cache[i] = codec->hw_read(codec, i); | ||
291 | } | ||
292 | |||
293 | static void wm8903_reset(struct snd_soc_codec *codec) | 263 | static void wm8903_reset(struct snd_soc_codec *codec) |
294 | { | 264 | { |
295 | snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0); | 265 | snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0); |
@@ -297,11 +267,6 @@ static void wm8903_reset(struct snd_soc_codec *codec) | |||
297 | sizeof(wm8903_reg_defaults)); | 267 | sizeof(wm8903_reg_defaults)); |
298 | } | 268 | } |
299 | 269 | ||
300 | #define WM8903_OUTPUT_SHORT 0x8 | ||
301 | #define WM8903_OUTPUT_OUT 0x4 | ||
302 | #define WM8903_OUTPUT_INT 0x2 | ||
303 | #define WM8903_OUTPUT_IN 0x1 | ||
304 | |||
305 | static int wm8903_cp_event(struct snd_soc_dapm_widget *w, | 270 | static int wm8903_cp_event(struct snd_soc_dapm_widget *w, |
306 | struct snd_kcontrol *kcontrol, int event) | 271 | struct snd_kcontrol *kcontrol, int event) |
307 | { | 272 | { |
@@ -311,97 +276,101 @@ static int wm8903_cp_event(struct snd_soc_dapm_widget *w, | |||
311 | return 0; | 276 | return 0; |
312 | } | 277 | } |
313 | 278 | ||
314 | /* | 279 | static int wm8903_dcs_event(struct snd_soc_dapm_widget *w, |
315 | * Event for headphone and line out amplifier power changes. Special | 280 | struct snd_kcontrol *kcontrol, int event) |
316 | * power up/down sequences are required in order to maximise pop/click | ||
317 | * performance. | ||
318 | */ | ||
319 | static int wm8903_output_event(struct snd_soc_dapm_widget *w, | ||
320 | struct snd_kcontrol *kcontrol, int event) | ||
321 | { | 281 | { |
322 | struct snd_soc_codec *codec = w->codec; | 282 | struct snd_soc_codec *codec = w->codec; |
323 | u16 val; | 283 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
324 | u16 reg; | ||
325 | u16 dcs_reg; | ||
326 | u16 dcs_bit; | ||
327 | int shift; | ||
328 | 284 | ||
329 | switch (w->reg) { | 285 | switch (event) { |
330 | case WM8903_POWER_MANAGEMENT_2: | 286 | case SND_SOC_DAPM_POST_PMU: |
331 | reg = WM8903_ANALOGUE_HP_0; | 287 | wm8903->dcs_pending |= 1 << w->shift; |
332 | dcs_bit = 0 + w->shift; | ||
333 | break; | 288 | break; |
334 | case WM8903_POWER_MANAGEMENT_3: | 289 | case SND_SOC_DAPM_PRE_PMD: |
335 | reg = WM8903_ANALOGUE_LINEOUT_0; | 290 | snd_soc_update_bits(codec, WM8903_DC_SERVO_0, |
336 | dcs_bit = 2 + w->shift; | 291 | 1 << w->shift, 0); |
337 | break; | 292 | break; |
338 | default: | ||
339 | BUG(); | ||
340 | return -EINVAL; /* Spurious warning from some compilers */ | ||
341 | } | 293 | } |
342 | 294 | ||
343 | switch (w->shift) { | 295 | return 0; |
344 | case 0: | 296 | } |
345 | shift = 0; | ||
346 | break; | ||
347 | case 1: | ||
348 | shift = 4; | ||
349 | break; | ||
350 | default: | ||
351 | BUG(); | ||
352 | return -EINVAL; /* Spurious warning from some compilers */ | ||
353 | } | ||
354 | 297 | ||
355 | if (event & SND_SOC_DAPM_PRE_PMU) { | 298 | #define WM8903_DCS_MODE_WRITE_STOP 0 |
356 | val = snd_soc_read(codec, reg); | 299 | #define WM8903_DCS_MODE_START_STOP 2 |
357 | 300 | ||
358 | /* Short the output */ | 301 | static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm, |
359 | val &= ~(WM8903_OUTPUT_SHORT << shift); | 302 | enum snd_soc_dapm_type event, int subseq) |
360 | snd_soc_write(codec, reg, val); | 303 | { |
361 | } | 304 | struct snd_soc_codec *codec = container_of(dapm, |
305 | struct snd_soc_codec, dapm); | ||
306 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
307 | int dcs_mode = WM8903_DCS_MODE_WRITE_STOP; | ||
308 | int i, val; | ||
362 | 309 | ||
363 | if (event & SND_SOC_DAPM_POST_PMU) { | 310 | /* Complete any pending DC servo starts */ |
364 | val = snd_soc_read(codec, reg); | 311 | if (wm8903->dcs_pending) { |
312 | dev_dbg(codec->dev, "Starting DC servo for %x\n", | ||
313 | wm8903->dcs_pending); | ||
365 | 314 | ||
366 | val |= (WM8903_OUTPUT_IN << shift); | 315 | /* If we've no cached values then we need to do startup */ |
367 | snd_soc_write(codec, reg, val); | 316 | for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) { |
317 | if (!(wm8903->dcs_pending & (1 << i))) | ||
318 | continue; | ||
368 | 319 | ||
369 | val |= (WM8903_OUTPUT_INT << shift); | 320 | if (wm8903->dcs_cache[i]) { |
370 | snd_soc_write(codec, reg, val); | 321 | dev_dbg(codec->dev, |
322 | "Restore DC servo %d value %x\n", | ||
323 | 3 - i, wm8903->dcs_cache[i]); | ||
324 | |||
325 | snd_soc_write(codec, WM8903_DC_SERVO_4 + i, | ||
326 | wm8903->dcs_cache[i] & 0xff); | ||
327 | } else { | ||
328 | dev_dbg(codec->dev, | ||
329 | "Calibrate DC servo %d\n", 3 - i); | ||
330 | dcs_mode = WM8903_DCS_MODE_START_STOP; | ||
331 | } | ||
332 | } | ||
371 | 333 | ||
372 | /* Turn on the output ENA_OUTP */ | 334 | /* Don't trust the cache for analogue */ |
373 | val |= (WM8903_OUTPUT_OUT << shift); | 335 | if (wm8903->class_w_users) |
374 | snd_soc_write(codec, reg, val); | 336 | dcs_mode = WM8903_DCS_MODE_START_STOP; |
375 | 337 | ||
376 | /* Enable the DC servo */ | 338 | snd_soc_update_bits(codec, WM8903_DC_SERVO_2, |
377 | dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0); | 339 | WM8903_DCS_MODE_MASK, dcs_mode); |
378 | dcs_reg |= dcs_bit; | ||
379 | snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg); | ||
380 | 340 | ||
381 | /* Remove the short */ | 341 | snd_soc_update_bits(codec, WM8903_DC_SERVO_0, |
382 | val |= (WM8903_OUTPUT_SHORT << shift); | 342 | WM8903_DCS_ENA_MASK, wm8903->dcs_pending); |
383 | snd_soc_write(codec, reg, val); | ||
384 | } | ||
385 | 343 | ||
386 | if (event & SND_SOC_DAPM_PRE_PMD) { | 344 | switch (dcs_mode) { |
387 | val = snd_soc_read(codec, reg); | 345 | case WM8903_DCS_MODE_WRITE_STOP: |
346 | break; | ||
388 | 347 | ||
389 | /* Short the output */ | 348 | case WM8903_DCS_MODE_START_STOP: |
390 | val &= ~(WM8903_OUTPUT_SHORT << shift); | 349 | msleep(270); |
391 | snd_soc_write(codec, reg, val); | ||
392 | 350 | ||
393 | /* Disable the DC servo */ | 351 | /* Cache the measured offsets for digital */ |
394 | dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0); | 352 | if (wm8903->class_w_users) |
395 | dcs_reg &= ~dcs_bit; | 353 | break; |
396 | snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg); | ||
397 | 354 | ||
398 | /* Then disable the intermediate and output stages */ | 355 | for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) { |
399 | val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT | | 356 | if (!(wm8903->dcs_pending & (1 << i))) |
400 | WM8903_OUTPUT_IN) << shift); | 357 | continue; |
401 | snd_soc_write(codec, reg, val); | ||
402 | } | ||
403 | 358 | ||
404 | return 0; | 359 | val = snd_soc_read(codec, |
360 | WM8903_DC_SERVO_READBACK_1 + i); | ||
361 | dev_dbg(codec->dev, "DC servo %d: %x\n", | ||
362 | 3 - i, val); | ||
363 | wm8903->dcs_cache[i] = val; | ||
364 | } | ||
365 | break; | ||
366 | |||
367 | default: | ||
368 | pr_warn("DCS mode %d delay not set\n", dcs_mode); | ||
369 | break; | ||
370 | } | ||
371 | |||
372 | wm8903->dcs_pending = 0; | ||
373 | } | ||
405 | } | 374 | } |
406 | 375 | ||
407 | /* | 376 | /* |
@@ -667,6 +636,22 @@ static const struct soc_enum lsidetone_enum = | |||
667 | static const struct soc_enum rsidetone_enum = | 636 | static const struct soc_enum rsidetone_enum = |
668 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); | 637 | SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text); |
669 | 638 | ||
639 | static const char *aif_text[] = { | ||
640 | "Left", "Right" | ||
641 | }; | ||
642 | |||
643 | static const struct soc_enum lcapture_enum = | ||
644 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text); | ||
645 | |||
646 | static const struct soc_enum rcapture_enum = | ||
647 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text); | ||
648 | |||
649 | static const struct soc_enum lplay_enum = | ||
650 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text); | ||
651 | |||
652 | static const struct soc_enum rplay_enum = | ||
653 | SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text); | ||
654 | |||
670 | static const struct snd_kcontrol_new wm8903_snd_controls[] = { | 655 | static const struct snd_kcontrol_new wm8903_snd_controls[] = { |
671 | 656 | ||
672 | /* Input PGAs - No TLV since the scale depends on PGA mode */ | 657 | /* Input PGAs - No TLV since the scale depends on PGA mode */ |
@@ -784,6 +769,18 @@ static const struct snd_kcontrol_new lsidetone_mux = | |||
784 | static const struct snd_kcontrol_new rsidetone_mux = | 769 | static const struct snd_kcontrol_new rsidetone_mux = |
785 | SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum); | 770 | SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum); |
786 | 771 | ||
772 | static const struct snd_kcontrol_new lcapture_mux = | ||
773 | SOC_DAPM_ENUM("Left Capture Mux", lcapture_enum); | ||
774 | |||
775 | static const struct snd_kcontrol_new rcapture_mux = | ||
776 | SOC_DAPM_ENUM("Right Capture Mux", rcapture_enum); | ||
777 | |||
778 | static const struct snd_kcontrol_new lplay_mux = | ||
779 | SOC_DAPM_ENUM("Left Playback Mux", lplay_enum); | ||
780 | |||
781 | static const struct snd_kcontrol_new rplay_mux = | ||
782 | SOC_DAPM_ENUM("Right Playback Mux", rplay_enum); | ||
783 | |||
787 | static const struct snd_kcontrol_new left_output_mixer[] = { | 784 | static const struct snd_kcontrol_new left_output_mixer[] = { |
788 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), | 785 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), |
789 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), | 786 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), |
@@ -847,14 +844,26 @@ SND_SOC_DAPM_MUX("Right Input Mode Mux", SND_SOC_NOPM, 0, 0, &rinput_mode_mux), | |||
847 | SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), | 844 | SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0), |
848 | SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), | 845 | SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0), |
849 | 846 | ||
850 | SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0), | 847 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8903_POWER_MANAGEMENT_6, 1, 0), |
851 | SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0), | 848 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8903_POWER_MANAGEMENT_6, 0, 0), |
849 | |||
850 | SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lcapture_mux), | ||
851 | SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rcapture_mux), | ||
852 | |||
853 | SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0), | ||
854 | SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0), | ||
852 | 855 | ||
853 | SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux), | 856 | SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux), |
854 | SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux), | 857 | SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux), |
855 | 858 | ||
856 | SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0), | 859 | SND_SOC_DAPM_AIF_IN("AIFRXL", "Left Playback", 0, SND_SOC_NOPM, 0, 0), |
857 | SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0), | 860 | SND_SOC_DAPM_AIF_IN("AIFRXR", "Right Playback", 0, SND_SOC_NOPM, 0, 0), |
861 | |||
862 | SND_SOC_DAPM_MUX("Left Playback Mux", SND_SOC_NOPM, 0, 0, &lplay_mux), | ||
863 | SND_SOC_DAPM_MUX("Right Playback Mux", SND_SOC_NOPM, 0, 0, &rplay_mux), | ||
864 | |||
865 | SND_SOC_DAPM_DAC("DACL", NULL, WM8903_POWER_MANAGEMENT_6, 3, 0), | ||
866 | SND_SOC_DAPM_DAC("DACR", NULL, WM8903_POWER_MANAGEMENT_6, 2, 0), | ||
858 | 867 | ||
859 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0, | 868 | SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0, |
860 | left_output_mixer, ARRAY_SIZE(left_output_mixer)), | 869 | left_output_mixer, ARRAY_SIZE(left_output_mixer)), |
@@ -866,23 +875,45 @@ SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0, | |||
866 | SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, | 875 | SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0, |
867 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), | 876 | right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), |
868 | 877 | ||
869 | SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, | 878 | SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, |
870 | 1, 0, NULL, 0, wm8903_output_event, | 879 | 4, 0, NULL, 0), |
871 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 880 | SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0, |
872 | SND_SOC_DAPM_PRE_PMD), | 881 | 0, 0, NULL, 0), |
873 | SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2, | 882 | |
874 | 0, 0, NULL, 0, wm8903_output_event, | 883 | SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 4, 0, |
875 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 884 | NULL, 0), |
876 | SND_SOC_DAPM_PRE_PMD), | 885 | SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 0, 0, |
877 | 886 | NULL, 0), | |
878 | SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0, | 887 | |
879 | NULL, 0, wm8903_output_event, | 888 | SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0), |
880 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 889 | SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0), |
881 | SND_SOC_DAPM_PRE_PMD), | 890 | SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0), |
882 | SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0, | 891 | SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0), |
883 | NULL, 0, wm8903_output_event, | 892 | SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0), |
884 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | | 893 | SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0), |
885 | SND_SOC_DAPM_PRE_PMD), | 894 | |
895 | SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0, | ||
896 | NULL, 0), | ||
897 | SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0, | ||
898 | NULL, 0), | ||
899 | SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 5, 0, | ||
900 | NULL, 0), | ||
901 | SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0, | ||
902 | NULL, 0), | ||
903 | SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0, | ||
904 | NULL, 0), | ||
905 | SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 1, 0, | ||
906 | NULL, 0), | ||
907 | |||
908 | SND_SOC_DAPM_SUPPLY("DCS Master", WM8903_DC_SERVO_0, 4, 0, NULL, 0), | ||
909 | SND_SOC_DAPM_PGA_S("HPL_DCS", 3, SND_SOC_NOPM, 3, 0, wm8903_dcs_event, | ||
910 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
911 | SND_SOC_DAPM_PGA_S("HPR_DCS", 3, SND_SOC_NOPM, 2, 0, wm8903_dcs_event, | ||
912 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
913 | SND_SOC_DAPM_PGA_S("LINEOUTL_DCS", 3, SND_SOC_NOPM, 1, 0, wm8903_dcs_event, | ||
914 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
915 | SND_SOC_DAPM_PGA_S("LINEOUTR_DCS", 3, SND_SOC_NOPM, 0, 0, wm8903_dcs_event, | ||
916 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
886 | 917 | ||
887 | SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, | 918 | SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0, |
888 | NULL, 0), | 919 | NULL, 0), |
@@ -892,10 +923,18 @@ SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0, | |||
892 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0, | 923 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0, |
893 | wm8903_cp_event, SND_SOC_DAPM_POST_PMU), | 924 | wm8903_cp_event, SND_SOC_DAPM_POST_PMU), |
894 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0), | 925 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0), |
926 | SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0), | ||
895 | }; | 927 | }; |
896 | 928 | ||
897 | static const struct snd_soc_dapm_route intercon[] = { | 929 | static const struct snd_soc_dapm_route intercon[] = { |
898 | 930 | ||
931 | { "CLK_DSP", NULL, "CLK_SYS" }, | ||
932 | { "Mic Bias", NULL, "CLK_SYS" }, | ||
933 | { "HPL_DCS", NULL, "CLK_SYS" }, | ||
934 | { "HPR_DCS", NULL, "CLK_SYS" }, | ||
935 | { "LINEOUTL_DCS", NULL, "CLK_SYS" }, | ||
936 | { "LINEOUTR_DCS", NULL, "CLK_SYS" }, | ||
937 | |||
899 | { "Left Input Mux", "IN1L", "IN1L" }, | 938 | { "Left Input Mux", "IN1L", "IN1L" }, |
900 | { "Left Input Mux", "IN2L", "IN2L" }, | 939 | { "Left Input Mux", "IN2L", "IN2L" }, |
901 | { "Left Input Mux", "IN3L", "IN3L" }, | 940 | { "Left Input Mux", "IN3L", "IN3L" }, |
@@ -936,18 +975,36 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
936 | { "Left Input PGA", NULL, "Left Input Mode Mux" }, | 975 | { "Left Input PGA", NULL, "Left Input Mode Mux" }, |
937 | { "Right Input PGA", NULL, "Right Input Mode Mux" }, | 976 | { "Right Input PGA", NULL, "Right Input Mode Mux" }, |
938 | 977 | ||
978 | { "Left Capture Mux", "Left", "ADCL" }, | ||
979 | { "Left Capture Mux", "Right", "ADCR" }, | ||
980 | |||
981 | { "Right Capture Mux", "Left", "ADCL" }, | ||
982 | { "Right Capture Mux", "Right", "ADCR" }, | ||
983 | |||
984 | { "AIFTXL", NULL, "Left Capture Mux" }, | ||
985 | { "AIFTXR", NULL, "Right Capture Mux" }, | ||
986 | |||
939 | { "ADCL", NULL, "Left Input PGA" }, | 987 | { "ADCL", NULL, "Left Input PGA" }, |
940 | { "ADCL", NULL, "CLK_DSP" }, | 988 | { "ADCL", NULL, "CLK_DSP" }, |
941 | { "ADCR", NULL, "Right Input PGA" }, | 989 | { "ADCR", NULL, "Right Input PGA" }, |
942 | { "ADCR", NULL, "CLK_DSP" }, | 990 | { "ADCR", NULL, "CLK_DSP" }, |
943 | 991 | ||
992 | { "Left Playback Mux", "Left", "AIFRXL" }, | ||
993 | { "Left Playback Mux", "Right", "AIFRXR" }, | ||
994 | |||
995 | { "Right Playback Mux", "Left", "AIFRXL" }, | ||
996 | { "Right Playback Mux", "Right", "AIFRXR" }, | ||
997 | |||
944 | { "DACL Sidetone", "Left", "ADCL" }, | 998 | { "DACL Sidetone", "Left", "ADCL" }, |
945 | { "DACL Sidetone", "Right", "ADCR" }, | 999 | { "DACL Sidetone", "Right", "ADCR" }, |
946 | { "DACR Sidetone", "Left", "ADCL" }, | 1000 | { "DACR Sidetone", "Left", "ADCL" }, |
947 | { "DACR Sidetone", "Right", "ADCR" }, | 1001 | { "DACR Sidetone", "Right", "ADCR" }, |
948 | 1002 | ||
1003 | { "DACL", NULL, "Left Playback Mux" }, | ||
949 | { "DACL", NULL, "DACL Sidetone" }, | 1004 | { "DACL", NULL, "DACL Sidetone" }, |
950 | { "DACL", NULL, "CLK_DSP" }, | 1005 | { "DACL", NULL, "CLK_DSP" }, |
1006 | |||
1007 | { "DACR", NULL, "Right Playback Mux" }, | ||
951 | { "DACR", NULL, "DACR Sidetone" }, | 1008 | { "DACR", NULL, "DACR Sidetone" }, |
952 | { "DACR", NULL, "CLK_DSP" }, | 1009 | { "DACR", NULL, "CLK_DSP" }, |
953 | 1010 | ||
@@ -980,11 +1037,35 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
980 | { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, | 1037 | { "Left Speaker PGA", NULL, "Left Speaker Mixer" }, |
981 | { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, | 1038 | { "Right Speaker PGA", NULL, "Right Speaker Mixer" }, |
982 | 1039 | ||
983 | { "HPOUTL", NULL, "Left Headphone Output PGA" }, | 1040 | { "HPL_ENA_DLY", NULL, "Left Headphone Output PGA" }, |
984 | { "HPOUTR", NULL, "Right Headphone Output PGA" }, | 1041 | { "HPR_ENA_DLY", NULL, "Right Headphone Output PGA" }, |
1042 | { "LINEOUTL_ENA_DLY", NULL, "Left Line Output PGA" }, | ||
1043 | { "LINEOUTR_ENA_DLY", NULL, "Right Line Output PGA" }, | ||
1044 | |||
1045 | { "HPL_DCS", NULL, "DCS Master" }, | ||
1046 | { "HPR_DCS", NULL, "DCS Master" }, | ||
1047 | { "LINEOUTL_DCS", NULL, "DCS Master" }, | ||
1048 | { "LINEOUTR_DCS", NULL, "DCS Master" }, | ||
1049 | |||
1050 | { "HPL_DCS", NULL, "HPL_ENA_DLY" }, | ||
1051 | { "HPR_DCS", NULL, "HPR_ENA_DLY" }, | ||
1052 | { "LINEOUTL_DCS", NULL, "LINEOUTL_ENA_DLY" }, | ||
1053 | { "LINEOUTR_DCS", NULL, "LINEOUTR_ENA_DLY" }, | ||
985 | 1054 | ||
986 | { "LINEOUTL", NULL, "Left Line Output PGA" }, | 1055 | { "HPL_ENA_OUTP", NULL, "HPL_DCS" }, |
987 | { "LINEOUTR", NULL, "Right Line Output PGA" }, | 1056 | { "HPR_ENA_OUTP", NULL, "HPR_DCS" }, |
1057 | { "LINEOUTL_ENA_OUTP", NULL, "LINEOUTL_DCS" }, | ||
1058 | { "LINEOUTR_ENA_OUTP", NULL, "LINEOUTR_DCS" }, | ||
1059 | |||
1060 | { "HPL_RMV_SHORT", NULL, "HPL_ENA_OUTP" }, | ||
1061 | { "HPR_RMV_SHORT", NULL, "HPR_ENA_OUTP" }, | ||
1062 | { "LINEOUTL_RMV_SHORT", NULL, "LINEOUTL_ENA_OUTP" }, | ||
1063 | { "LINEOUTR_RMV_SHORT", NULL, "LINEOUTR_ENA_OUTP" }, | ||
1064 | |||
1065 | { "HPOUTL", NULL, "HPL_RMV_SHORT" }, | ||
1066 | { "HPOUTR", NULL, "HPR_RMV_SHORT" }, | ||
1067 | { "LINEOUTL", NULL, "LINEOUTL_RMV_SHORT" }, | ||
1068 | { "LINEOUTR", NULL, "LINEOUTR_RMV_SHORT" }, | ||
988 | 1069 | ||
989 | { "LOP", NULL, "Left Speaker PGA" }, | 1070 | { "LOP", NULL, "Left Speaker PGA" }, |
990 | { "LON", NULL, "Left Speaker PGA" }, | 1071 | { "LON", NULL, "Left Speaker PGA" }, |
@@ -1012,29 +1093,71 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec) | |||
1012 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, | 1093 | static int wm8903_set_bias_level(struct snd_soc_codec *codec, |
1013 | enum snd_soc_bias_level level) | 1094 | enum snd_soc_bias_level level) |
1014 | { | 1095 | { |
1015 | u16 reg; | ||
1016 | |||
1017 | switch (level) { | 1096 | switch (level) { |
1018 | case SND_SOC_BIAS_ON: | 1097 | case SND_SOC_BIAS_ON: |
1098 | break; | ||
1099 | |||
1019 | case SND_SOC_BIAS_PREPARE: | 1100 | case SND_SOC_BIAS_PREPARE: |
1020 | reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0); | 1101 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, |
1021 | reg &= ~(WM8903_VMID_RES_MASK); | 1102 | WM8903_VMID_RES_MASK, |
1022 | reg |= WM8903_VMID_RES_50K; | 1103 | WM8903_VMID_RES_50K); |
1023 | snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg); | ||
1024 | break; | 1104 | break; |
1025 | 1105 | ||
1026 | case SND_SOC_BIAS_STANDBY: | 1106 | case SND_SOC_BIAS_STANDBY: |
1027 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1107 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1028 | snd_soc_write(codec, WM8903_CLOCK_RATES_2, | 1108 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, |
1029 | WM8903_CLK_SYS_ENA); | 1109 | WM8903_POBCTRL | WM8903_ISEL_MASK | |
1030 | 1110 | WM8903_STARTUP_BIAS_ENA | | |
1031 | /* Change DC servo dither level in startup sequence */ | 1111 | WM8903_BIAS_ENA, |
1032 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11); | 1112 | WM8903_POBCTRL | |
1033 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257); | 1113 | (2 << WM8903_ISEL_SHIFT) | |
1034 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2); | 1114 | WM8903_STARTUP_BIAS_ENA); |
1035 | 1115 | ||
1036 | wm8903_run_sequence(codec, 0); | 1116 | snd_soc_update_bits(codec, |
1037 | wm8903_sync_reg_cache(codec, codec->reg_cache); | 1117 | WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, |
1118 | WM8903_SPK_DISCHARGE, | ||
1119 | WM8903_SPK_DISCHARGE); | ||
1120 | |||
1121 | msleep(33); | ||
1122 | |||
1123 | snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, | ||
1124 | WM8903_SPKL_ENA | WM8903_SPKR_ENA, | ||
1125 | WM8903_SPKL_ENA | WM8903_SPKR_ENA); | ||
1126 | |||
1127 | snd_soc_update_bits(codec, | ||
1128 | WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0, | ||
1129 | WM8903_SPK_DISCHARGE, 0); | ||
1130 | |||
1131 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1132 | WM8903_VMID_TIE_ENA | | ||
1133 | WM8903_BUFIO_ENA | | ||
1134 | WM8903_VMID_IO_ENA | | ||
1135 | WM8903_VMID_SOFT_MASK | | ||
1136 | WM8903_VMID_RES_MASK | | ||
1137 | WM8903_VMID_BUF_ENA, | ||
1138 | WM8903_VMID_TIE_ENA | | ||
1139 | WM8903_BUFIO_ENA | | ||
1140 | WM8903_VMID_IO_ENA | | ||
1141 | (2 << WM8903_VMID_SOFT_SHIFT) | | ||
1142 | WM8903_VMID_RES_250K | | ||
1143 | WM8903_VMID_BUF_ENA); | ||
1144 | |||
1145 | msleep(129); | ||
1146 | |||
1147 | snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5, | ||
1148 | WM8903_SPKL_ENA | WM8903_SPKR_ENA, | ||
1149 | 0); | ||
1150 | |||
1151 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1152 | WM8903_VMID_SOFT_MASK, 0); | ||
1153 | |||
1154 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1155 | WM8903_VMID_RES_MASK, | ||
1156 | WM8903_VMID_RES_50K); | ||
1157 | |||
1158 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, | ||
1159 | WM8903_BIAS_ENA | WM8903_POBCTRL, | ||
1160 | WM8903_BIAS_ENA); | ||
1038 | 1161 | ||
1039 | /* By default no bypass paths are enabled so | 1162 | /* By default no bypass paths are enabled so |
1040 | * enable Class W support. | 1163 | * enable Class W support. |
@@ -1047,17 +1170,32 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
1047 | WM8903_CP_DYN_V); | 1170 | WM8903_CP_DYN_V); |
1048 | } | 1171 | } |
1049 | 1172 | ||
1050 | reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0); | 1173 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, |
1051 | reg &= ~(WM8903_VMID_RES_MASK); | 1174 | WM8903_VMID_RES_MASK, |
1052 | reg |= WM8903_VMID_RES_250K; | 1175 | WM8903_VMID_RES_250K); |
1053 | snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg); | ||
1054 | break; | 1176 | break; |
1055 | 1177 | ||
1056 | case SND_SOC_BIAS_OFF: | 1178 | case SND_SOC_BIAS_OFF: |
1057 | wm8903_run_sequence(codec, 32); | 1179 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, |
1058 | reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2); | 1180 | WM8903_BIAS_ENA, 0); |
1059 | reg &= ~WM8903_CLK_SYS_ENA; | 1181 | |
1060 | snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg); | 1182 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, |
1183 | WM8903_VMID_SOFT_MASK, | ||
1184 | 2 << WM8903_VMID_SOFT_SHIFT); | ||
1185 | |||
1186 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1187 | WM8903_VMID_BUF_ENA, 0); | ||
1188 | |||
1189 | msleep(290); | ||
1190 | |||
1191 | snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0, | ||
1192 | WM8903_VMID_TIE_ENA | WM8903_BUFIO_ENA | | ||
1193 | WM8903_VMID_IO_ENA | WM8903_VMID_RES_MASK | | ||
1194 | WM8903_VMID_SOFT_MASK | | ||
1195 | WM8903_VMID_BUF_ENA, 0); | ||
1196 | |||
1197 | snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0, | ||
1198 | WM8903_STARTUP_BIAS_ENA, 0); | ||
1061 | break; | 1199 | break; |
1062 | } | 1200 | } |
1063 | 1201 | ||
@@ -1510,8 +1648,7 @@ static irqreturn_t wm8903_irq(int irq, void *data) | |||
1510 | int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; | 1648 | int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; |
1511 | 1649 | ||
1512 | if (int_val & WM8903_WSEQ_BUSY_EINT) { | 1650 | if (int_val & WM8903_WSEQ_BUSY_EINT) { |
1513 | dev_dbg(codec->dev, "Write sequencer done\n"); | 1651 | dev_warn(codec->dev, "Write sequencer done\n"); |
1514 | complete(&wm8903->wseq); | ||
1515 | } | 1652 | } |
1516 | 1653 | ||
1517 | /* | 1654 | /* |
@@ -1635,6 +1772,120 @@ static int wm8903_resume(struct snd_soc_codec *codec) | |||
1635 | return 0; | 1772 | return 0; |
1636 | } | 1773 | } |
1637 | 1774 | ||
1775 | #ifdef CONFIG_GPIOLIB | ||
1776 | static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip) | ||
1777 | { | ||
1778 | return container_of(chip, struct wm8903_priv, gpio_chip); | ||
1779 | } | ||
1780 | |||
1781 | static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
1782 | { | ||
1783 | if (offset >= WM8903_NUM_GPIO) | ||
1784 | return -EINVAL; | ||
1785 | |||
1786 | return 0; | ||
1787 | } | ||
1788 | |||
1789 | static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset) | ||
1790 | { | ||
1791 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1792 | struct snd_soc_codec *codec = wm8903->codec; | ||
1793 | unsigned int mask, val; | ||
1794 | |||
1795 | mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK; | ||
1796 | val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) | | ||
1797 | WM8903_GP1_DIR; | ||
1798 | |||
1799 | return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | ||
1800 | mask, val); | ||
1801 | } | ||
1802 | |||
1803 | static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
1804 | { | ||
1805 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1806 | struct snd_soc_codec *codec = wm8903->codec; | ||
1807 | int reg; | ||
1808 | |||
1809 | reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset); | ||
1810 | |||
1811 | return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT; | ||
1812 | } | ||
1813 | |||
1814 | static int wm8903_gpio_direction_out(struct gpio_chip *chip, | ||
1815 | unsigned offset, int value) | ||
1816 | { | ||
1817 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1818 | struct snd_soc_codec *codec = wm8903->codec; | ||
1819 | unsigned int mask, val; | ||
1820 | |||
1821 | mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK | WM8903_GP1_LVL_MASK; | ||
1822 | val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) | | ||
1823 | (value << WM8903_GP2_LVL_SHIFT); | ||
1824 | |||
1825 | return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | ||
1826 | mask, val); | ||
1827 | } | ||
1828 | |||
1829 | static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
1830 | { | ||
1831 | struct wm8903_priv *wm8903 = gpio_to_wm8903(chip); | ||
1832 | struct snd_soc_codec *codec = wm8903->codec; | ||
1833 | |||
1834 | snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset, | ||
1835 | WM8903_GP1_LVL_MASK, | ||
1836 | !!value << WM8903_GP1_LVL_SHIFT); | ||
1837 | } | ||
1838 | |||
1839 | static struct gpio_chip wm8903_template_chip = { | ||
1840 | .label = "wm8903", | ||
1841 | .owner = THIS_MODULE, | ||
1842 | .request = wm8903_gpio_request, | ||
1843 | .direction_input = wm8903_gpio_direction_in, | ||
1844 | .get = wm8903_gpio_get, | ||
1845 | .direction_output = wm8903_gpio_direction_out, | ||
1846 | .set = wm8903_gpio_set, | ||
1847 | .can_sleep = 1, | ||
1848 | }; | ||
1849 | |||
1850 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | ||
1851 | { | ||
1852 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1853 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); | ||
1854 | int ret; | ||
1855 | |||
1856 | wm8903->gpio_chip = wm8903_template_chip; | ||
1857 | wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO; | ||
1858 | wm8903->gpio_chip.dev = codec->dev; | ||
1859 | |||
1860 | if (pdata && pdata->gpio_base) | ||
1861 | wm8903->gpio_chip.base = pdata->gpio_base; | ||
1862 | else | ||
1863 | wm8903->gpio_chip.base = -1; | ||
1864 | |||
1865 | ret = gpiochip_add(&wm8903->gpio_chip); | ||
1866 | if (ret != 0) | ||
1867 | dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret); | ||
1868 | } | ||
1869 | |||
1870 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | ||
1871 | { | ||
1872 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1873 | int ret; | ||
1874 | |||
1875 | ret = gpiochip_remove(&wm8903->gpio_chip); | ||
1876 | if (ret != 0) | ||
1877 | dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret); | ||
1878 | } | ||
1879 | #else | ||
1880 | static void wm8903_init_gpio(struct snd_soc_codec *codec) | ||
1881 | { | ||
1882 | } | ||
1883 | |||
1884 | static void wm8903_free_gpio(struct snd_soc_codec *codec) | ||
1885 | { | ||
1886 | } | ||
1887 | #endif | ||
1888 | |||
1638 | static int wm8903_probe(struct snd_soc_codec *codec) | 1889 | static int wm8903_probe(struct snd_soc_codec *codec) |
1639 | { | 1890 | { |
1640 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); | 1891 | struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev); |
@@ -1643,7 +1894,7 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1643 | int trigger, irq_pol; | 1894 | int trigger, irq_pol; |
1644 | u16 val; | 1895 | u16 val; |
1645 | 1896 | ||
1646 | init_completion(&wm8903->wseq); | 1897 | wm8903->codec = codec; |
1647 | 1898 | ||
1648 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1899 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
1649 | if (ret != 0) { | 1900 | if (ret != 0) { |
@@ -1659,19 +1910,33 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1659 | } | 1910 | } |
1660 | 1911 | ||
1661 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); | 1912 | val = snd_soc_read(codec, WM8903_REVISION_NUMBER); |
1662 | dev_info(codec->dev, "WM8903 revision %d\n", | 1913 | dev_info(codec->dev, "WM8903 revision %c\n", |
1663 | val & WM8903_CHIP_REV_MASK); | 1914 | (val & WM8903_CHIP_REV_MASK) + 'A'); |
1664 | 1915 | ||
1665 | wm8903_reset(codec); | 1916 | wm8903_reset(codec); |
1666 | 1917 | ||
1667 | /* Set up GPIOs and microphone detection */ | 1918 | /* Set up GPIOs and microphone detection */ |
1668 | if (pdata) { | 1919 | if (pdata) { |
1920 | bool mic_gpio = false; | ||
1921 | |||
1669 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | 1922 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { |
1670 | if (!pdata->gpio_cfg[i]) | 1923 | if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG) |
1671 | continue; | 1924 | continue; |
1672 | 1925 | ||
1673 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, | 1926 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, |
1674 | pdata->gpio_cfg[i] & 0xffff); | 1927 | pdata->gpio_cfg[i] & 0xffff); |
1928 | |||
1929 | val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK) | ||
1930 | >> WM8903_GP1_FN_SHIFT; | ||
1931 | |||
1932 | switch (val) { | ||
1933 | case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT: | ||
1934 | case WM8903_GPn_FN_MICBIAS_SHORT_DETECT: | ||
1935 | mic_gpio = true; | ||
1936 | break; | ||
1937 | default: | ||
1938 | break; | ||
1939 | } | ||
1675 | } | 1940 | } |
1676 | 1941 | ||
1677 | snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, | 1942 | snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, |
@@ -1682,6 +1947,14 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1682 | snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, | 1947 | snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, |
1683 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | 1948 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); |
1684 | 1949 | ||
1950 | /* If microphone detection is enabled by pdata but | ||
1951 | * detected via IRQ then interrupts can be lost before | ||
1952 | * the machine driver has set up microphone detection | ||
1953 | * IRQs as the IRQs are clear on read. The detection | ||
1954 | * will be enabled when the machine driver configures. | ||
1955 | */ | ||
1956 | WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA)); | ||
1957 | |||
1685 | wm8903->mic_delay = pdata->micdet_delay; | 1958 | wm8903->mic_delay = pdata->micdet_delay; |
1686 | } | 1959 | } |
1687 | 1960 | ||
@@ -1741,20 +2014,23 @@ static int wm8903_probe(struct snd_soc_codec *codec) | |||
1741 | snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); | 2014 | snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); |
1742 | 2015 | ||
1743 | /* Enable DAC soft mute by default */ | 2016 | /* Enable DAC soft mute by default */ |
1744 | val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); | 2017 | snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1, |
1745 | val |= WM8903_DAC_MUTEMODE; | 2018 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE, |
1746 | snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); | 2019 | WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE); |
1747 | 2020 | ||
1748 | snd_soc_add_controls(codec, wm8903_snd_controls, | 2021 | snd_soc_add_controls(codec, wm8903_snd_controls, |
1749 | ARRAY_SIZE(wm8903_snd_controls)); | 2022 | ARRAY_SIZE(wm8903_snd_controls)); |
1750 | wm8903_add_widgets(codec); | 2023 | wm8903_add_widgets(codec); |
1751 | 2024 | ||
2025 | wm8903_init_gpio(codec); | ||
2026 | |||
1752 | return ret; | 2027 | return ret; |
1753 | } | 2028 | } |
1754 | 2029 | ||
1755 | /* power down chip */ | 2030 | /* power down chip */ |
1756 | static int wm8903_remove(struct snd_soc_codec *codec) | 2031 | static int wm8903_remove(struct snd_soc_codec *codec) |
1757 | { | 2032 | { |
2033 | wm8903_free_gpio(codec); | ||
1758 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2034 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1759 | return 0; | 2035 | return 0; |
1760 | } | 2036 | } |
@@ -1769,6 +2045,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = { | |||
1769 | .reg_word_size = sizeof(u16), | 2045 | .reg_word_size = sizeof(u16), |
1770 | .reg_cache_default = wm8903_reg_defaults, | 2046 | .reg_cache_default = wm8903_reg_defaults, |
1771 | .volatile_register = wm8903_volatile_register, | 2047 | .volatile_register = wm8903_volatile_register, |
2048 | .seq_notifier = wm8903_seq_notifier, | ||
1772 | }; | 2049 | }; |
1773 | 2050 | ||
1774 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 2051 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
@@ -1807,7 +2084,7 @@ MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); | |||
1807 | 2084 | ||
1808 | static struct i2c_driver wm8903_i2c_driver = { | 2085 | static struct i2c_driver wm8903_i2c_driver = { |
1809 | .driver = { | 2086 | .driver = { |
1810 | .name = "wm8903-codec", | 2087 | .name = "wm8903", |
1811 | .owner = THIS_MODULE, | 2088 | .owner = THIS_MODULE, |
1812 | }, | 2089 | }, |
1813 | .probe = wm8903_i2c_probe, | 2090 | .probe = wm8903_i2c_probe, |
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h index e3ec2433b215..db949311c0f2 100644 --- a/sound/soc/codecs/wm8903.h +++ b/sound/soc/codecs/wm8903.h | |||
@@ -75,6 +75,14 @@ extern int wm8903_mic_detect(struct snd_soc_codec *codec, | |||
75 | #define WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0 0x41 | 75 | #define WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0 0x41 |
76 | #define WM8903_DC_SERVO_0 0x43 | 76 | #define WM8903_DC_SERVO_0 0x43 |
77 | #define WM8903_DC_SERVO_2 0x45 | 77 | #define WM8903_DC_SERVO_2 0x45 |
78 | #define WM8903_DC_SERVO_4 0x47 | ||
79 | #define WM8903_DC_SERVO_5 0x48 | ||
80 | #define WM8903_DC_SERVO_6 0x49 | ||
81 | #define WM8903_DC_SERVO_7 0x4A | ||
82 | #define WM8903_DC_SERVO_READBACK_1 0x51 | ||
83 | #define WM8903_DC_SERVO_READBACK_2 0x52 | ||
84 | #define WM8903_DC_SERVO_READBACK_3 0x53 | ||
85 | #define WM8903_DC_SERVO_READBACK_4 0x54 | ||
78 | #define WM8903_ANALOGUE_HP_0 0x5A | 86 | #define WM8903_ANALOGUE_HP_0 0x5A |
79 | #define WM8903_ANALOGUE_LINEOUT_0 0x5E | 87 | #define WM8903_ANALOGUE_LINEOUT_0 0x5E |
80 | #define WM8903_CHARGE_PUMP_0 0x62 | 88 | #define WM8903_CHARGE_PUMP_0 0x62 |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 9de44a4c05c0..443ae580445c 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -596,7 +596,7 @@ static struct { | |||
596 | { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */ | 596 | { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */ |
597 | }; | 597 | }; |
598 | 598 | ||
599 | static int wm8904_volatile_register(unsigned int reg) | 599 | static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
600 | { | 600 | { |
601 | return wm8904_access[reg].vol; | 601 | return wm8904_access[reg].vol; |
602 | } | 602 | } |
@@ -2436,19 +2436,28 @@ static int wm8904_probe(struct snd_soc_codec *codec) | |||
2436 | } | 2436 | } |
2437 | 2437 | ||
2438 | /* Change some default settings - latch VU and enable ZC */ | 2438 | /* Change some default settings - latch VU and enable ZC */ |
2439 | reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; | 2439 | snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT, |
2440 | reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; | 2440 | WM8904_ADC_VU, WM8904_ADC_VU); |
2441 | reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU; | 2441 | snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT, |
2442 | reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU; | 2442 | WM8904_ADC_VU, WM8904_ADC_VU); |
2443 | reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU | | 2443 | snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT, |
2444 | WM8904_HPOUTLZC; | 2444 | WM8904_DAC_VU, WM8904_DAC_VU); |
2445 | reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU | | 2445 | snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT, |
2446 | WM8904_HPOUTRZC; | 2446 | WM8904_DAC_VU, WM8904_DAC_VU); |
2447 | reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU | | 2447 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT, |
2448 | WM8904_LINEOUTLZC; | 2448 | WM8904_HPOUT_VU | WM8904_HPOUTLZC, |
2449 | reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU | | 2449 | WM8904_HPOUT_VU | WM8904_HPOUTLZC); |
2450 | WM8904_LINEOUTRZC; | 2450 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT, |
2451 | reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE; | 2451 | WM8904_HPOUT_VU | WM8904_HPOUTRZC, |
2452 | WM8904_HPOUT_VU | WM8904_HPOUTRZC); | ||
2453 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT, | ||
2454 | WM8904_LINEOUT_VU | WM8904_LINEOUTLZC, | ||
2455 | WM8904_LINEOUT_VU | WM8904_LINEOUTLZC); | ||
2456 | snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT, | ||
2457 | WM8904_LINEOUT_VU | WM8904_LINEOUTRZC, | ||
2458 | WM8904_LINEOUT_VU | WM8904_LINEOUTRZC); | ||
2459 | snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0, | ||
2460 | WM8904_SR_MODE, 0); | ||
2452 | 2461 | ||
2453 | /* Apply configuration from the platform data. */ | 2462 | /* Apply configuration from the platform data. */ |
2454 | if (wm8904->pdata) { | 2463 | if (wm8904->pdata) { |
@@ -2469,10 +2478,12 @@ static int wm8904_probe(struct snd_soc_codec *codec) | |||
2469 | /* Set Class W by default - this will be managed by the Class | 2478 | /* Set Class W by default - this will be managed by the Class |
2470 | * G widget at runtime where bypass paths are available. | 2479 | * G widget at runtime where bypass paths are available. |
2471 | */ | 2480 | */ |
2472 | reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR; | 2481 | snd_soc_update_bits(codec, WM8904_CLASS_W_0, |
2482 | WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR); | ||
2473 | 2483 | ||
2474 | /* Use normal bias source */ | 2484 | /* Use normal bias source */ |
2475 | reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL; | 2485 | snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0, |
2486 | WM8904_POBCTRL, 0); | ||
2476 | 2487 | ||
2477 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 2488 | wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
2478 | 2489 | ||
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 7167dfc96aa7..5e0214d6293e 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -934,16 +934,27 @@ static int wm8955_probe(struct snd_soc_codec *codec) | |||
934 | } | 934 | } |
935 | 935 | ||
936 | /* Change some default settings - latch VU and enable ZC */ | 936 | /* Change some default settings - latch VU and enable ZC */ |
937 | reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; | 937 | snd_soc_update_bits(codec, WM8955_LEFT_DAC_VOLUME, |
938 | reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; | 938 | WM8955_LDVU, WM8955_LDVU); |
939 | reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC; | 939 | snd_soc_update_bits(codec, WM8955_RIGHT_DAC_VOLUME, |
940 | reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC; | 940 | WM8955_RDVU, WM8955_RDVU); |
941 | reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC; | 941 | snd_soc_update_bits(codec, WM8955_LOUT1_VOLUME, |
942 | reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC; | 942 | WM8955_LO1VU | WM8955_LO1ZC, |
943 | reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC; | 943 | WM8955_LO1VU | WM8955_LO1ZC); |
944 | snd_soc_update_bits(codec, WM8955_ROUT1_VOLUME, | ||
945 | WM8955_RO1VU | WM8955_RO1ZC, | ||
946 | WM8955_RO1VU | WM8955_RO1ZC); | ||
947 | snd_soc_update_bits(codec, WM8955_LOUT2_VOLUME, | ||
948 | WM8955_LO2VU | WM8955_LO2ZC, | ||
949 | WM8955_LO2VU | WM8955_LO2ZC); | ||
950 | snd_soc_update_bits(codec, WM8955_ROUT2_VOLUME, | ||
951 | WM8955_RO2VU | WM8955_RO2ZC, | ||
952 | WM8955_RO2VU | WM8955_RO2ZC); | ||
953 | snd_soc_update_bits(codec, WM8955_MONOOUT_VOLUME, | ||
954 | WM8955_MOZC, WM8955_MOZC); | ||
944 | 955 | ||
945 | /* Also enable adaptive bass boost by default */ | 956 | /* Also enable adaptive bass boost by default */ |
946 | reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; | 957 | snd_soc_update_bits(codec, WM8955_BASS_CONTROL, WM8955_BB, WM8955_BB); |
947 | 958 | ||
948 | /* Set platform data values */ | 959 | /* Set platform data values */ |
949 | if (pdata) { | 960 | if (pdata) { |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 55252e7d02c9..cdee8103d09b 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -291,7 +291,7 @@ struct wm8961_priv { | |||
291 | int sysclk; | 291 | int sysclk; |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static int wm8961_volatile_register(unsigned int reg) | 294 | static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
295 | { | 295 | { |
296 | switch (reg) { | 296 | switch (reg) { |
297 | case WM8961_SOFTWARE_RESET: | 297 | case WM8961_SOFTWARE_RESET: |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index b9cb1fcf8c92..3b71dd65c966 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -1938,7 +1938,7 @@ static const struct wm8962_reg_access { | |||
1938 | [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */ | 1938 | [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */ |
1939 | }; | 1939 | }; |
1940 | 1940 | ||
1941 | static int wm8962_volatile_register(unsigned int reg) | 1941 | static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
1942 | { | 1942 | { |
1943 | if (wm8962_reg_access[reg].vol) | 1943 | if (wm8962_reg_access[reg].vol) |
1944 | return 1; | 1944 | return 1; |
@@ -1946,7 +1946,7 @@ static int wm8962_volatile_register(unsigned int reg) | |||
1946 | return 0; | 1946 | return 0; |
1947 | } | 1947 | } |
1948 | 1948 | ||
1949 | static int wm8962_readable_register(unsigned int reg) | 1949 | static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int reg) |
1950 | { | 1950 | { |
1951 | if (wm8962_reg_access[reg].read) | 1951 | if (wm8962_reg_access[reg].read) |
1952 | return 1; | 1952 | return 1; |
@@ -3635,7 +3635,7 @@ static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
3635 | struct snd_soc_codec *codec = wm8962->codec; | 3635 | struct snd_soc_codec *codec = wm8962->codec; |
3636 | 3636 | ||
3637 | snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, | 3637 | snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset, |
3638 | WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT); | 3638 | WM8962_GP2_LVL, !!value << WM8962_GP2_LVL_SHIFT); |
3639 | } | 3639 | } |
3640 | 3640 | ||
3641 | static int wm8962_gpio_direction_out(struct gpio_chip *chip, | 3641 | static int wm8962_gpio_direction_out(struct gpio_chip *chip, |
@@ -3822,16 +3822,26 @@ static int wm8962_probe(struct snd_soc_codec *codec) | |||
3822 | } | 3822 | } |
3823 | 3823 | ||
3824 | /* Latch volume update bits */ | 3824 | /* Latch volume update bits */ |
3825 | reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU; | 3825 | snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME, |
3826 | reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU; | 3826 | WM8962_IN_VU, WM8962_IN_VU); |
3827 | reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU; | 3827 | snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME, |
3828 | reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU; | 3828 | WM8962_IN_VU, WM8962_IN_VU); |
3829 | reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU; | 3829 | snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME, |
3830 | reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU; | 3830 | WM8962_ADC_VU, WM8962_ADC_VU); |
3831 | reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU; | 3831 | snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME, |
3832 | reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU; | 3832 | WM8962_ADC_VU, WM8962_ADC_VU); |
3833 | reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU; | 3833 | snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME, |
3834 | reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU; | 3834 | WM8962_DAC_VU, WM8962_DAC_VU); |
3835 | snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME, | ||
3836 | WM8962_DAC_VU, WM8962_DAC_VU); | ||
3837 | snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME, | ||
3838 | WM8962_SPKOUT_VU, WM8962_SPKOUT_VU); | ||
3839 | snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME, | ||
3840 | WM8962_SPKOUT_VU, WM8962_SPKOUT_VU); | ||
3841 | snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME, | ||
3842 | WM8962_HPOUT_VU, WM8962_HPOUT_VU); | ||
3843 | snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME, | ||
3844 | WM8962_HPOUT_VU, WM8962_HPOUT_VU); | ||
3835 | 3845 | ||
3836 | wm8962_add_widgets(codec); | 3846 | wm8962_add_widgets(codec); |
3837 | 3847 | ||
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 8dfb0a0da673..85e3e630e763 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -93,6 +93,7 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | |||
93 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); | 93 | static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); |
94 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); | 94 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); |
95 | static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1); | 95 | static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1); |
96 | static const DECLARE_TLV_DB_SCALE(limiter_tlv, 0, 100, 0); | ||
96 | 97 | ||
97 | static const struct snd_kcontrol_new wm8978_snd_controls[] = { | 98 | static const struct snd_kcontrol_new wm8978_snd_controls[] = { |
98 | 99 | ||
@@ -144,8 +145,8 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = { | |||
144 | 145 | ||
145 | SOC_SINGLE("DAC Playback Limiter Threshold", | 146 | SOC_SINGLE("DAC Playback Limiter Threshold", |
146 | WM8978_DAC_LIMITER_2, 4, 7, 0), | 147 | WM8978_DAC_LIMITER_2, 4, 7, 0), |
147 | SOC_SINGLE("DAC Playback Limiter Boost", | 148 | SOC_SINGLE_TLV("DAC Playback Limiter Volume", |
148 | WM8978_DAC_LIMITER_2, 0, 12, 0), | 149 | WM8978_DAC_LIMITER_2, 0, 12, 0, limiter_tlv), |
149 | 150 | ||
150 | SOC_ENUM("ALC Enable Switch", alc1), | 151 | SOC_ENUM("ALC Enable Switch", alc1), |
151 | SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), | 152 | SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0), |
@@ -967,7 +968,7 @@ static int wm8978_probe(struct snd_soc_codec *codec) | |||
967 | * written. | 968 | * written. |
968 | */ | 969 | */ |
969 | for (i = 0; i < ARRAY_SIZE(update_reg); i++) | 970 | for (i = 0; i < ARRAY_SIZE(update_reg); i++) |
970 | ((u16 *)codec->reg_cache)[update_reg[i]] |= 0x100; | 971 | snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100); |
971 | 972 | ||
972 | /* Reset the codec */ | 973 | /* Reset the codec */ |
973 | ret = snd_soc_write(codec, WM8978_RESET, 0); | 974 | ret = snd_soc_write(codec, WM8978_RESET, 0); |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c new file mode 100644 index 000000000000..28fdfd66661d --- /dev/null +++ b/sound/soc/codecs/wm8991.c | |||
@@ -0,0 +1,1427 @@ | |||
1 | /* | ||
2 | * wm8991.c -- WM8991 ALSA Soc Audio driver | ||
3 | * | ||
4 | * Copyright 2007-2010 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/version.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/pm.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | ||
28 | #include <sound/soc-dapm.h> | ||
29 | #include <sound/initval.h> | ||
30 | #include <sound/tlv.h> | ||
31 | #include <asm/div64.h> | ||
32 | |||
33 | #include "wm8991.h" | ||
34 | |||
35 | struct wm8991_priv { | ||
36 | enum snd_soc_control_type control_type; | ||
37 | unsigned int pcmclk; | ||
38 | }; | ||
39 | |||
40 | static const u16 wm8991_reg_defs[] = { | ||
41 | 0x8991, /* R0 - Reset */ | ||
42 | 0x0000, /* R1 - Power Management (1) */ | ||
43 | 0x6000, /* R2 - Power Management (2) */ | ||
44 | 0x0000, /* R3 - Power Management (3) */ | ||
45 | 0x4050, /* R4 - Audio Interface (1) */ | ||
46 | 0x4000, /* R5 - Audio Interface (2) */ | ||
47 | 0x01C8, /* R6 - Clocking (1) */ | ||
48 | 0x0000, /* R7 - Clocking (2) */ | ||
49 | 0x0040, /* R8 - Audio Interface (3) */ | ||
50 | 0x0040, /* R9 - Audio Interface (4) */ | ||
51 | 0x0004, /* R10 - DAC CTRL */ | ||
52 | 0x00C0, /* R11 - Left DAC Digital Volume */ | ||
53 | 0x00C0, /* R12 - Right DAC Digital Volume */ | ||
54 | 0x0000, /* R13 - Digital Side Tone */ | ||
55 | 0x0100, /* R14 - ADC CTRL */ | ||
56 | 0x00C0, /* R15 - Left ADC Digital Volume */ | ||
57 | 0x00C0, /* R16 - Right ADC Digital Volume */ | ||
58 | 0x0000, /* R17 */ | ||
59 | 0x0000, /* R18 - GPIO CTRL 1 */ | ||
60 | 0x1000, /* R19 - GPIO1 & GPIO2 */ | ||
61 | 0x1010, /* R20 - GPIO3 & GPIO4 */ | ||
62 | 0x1010, /* R21 - GPIO5 & GPIO6 */ | ||
63 | 0x8000, /* R22 - GPIOCTRL 2 */ | ||
64 | 0x0800, /* R23 - GPIO_POL */ | ||
65 | 0x008B, /* R24 - Left Line Input 1&2 Volume */ | ||
66 | 0x008B, /* R25 - Left Line Input 3&4 Volume */ | ||
67 | 0x008B, /* R26 - Right Line Input 1&2 Volume */ | ||
68 | 0x008B, /* R27 - Right Line Input 3&4 Volume */ | ||
69 | 0x0000, /* R28 - Left Output Volume */ | ||
70 | 0x0000, /* R29 - Right Output Volume */ | ||
71 | 0x0066, /* R30 - Line Outputs Volume */ | ||
72 | 0x0022, /* R31 - Out3/4 Volume */ | ||
73 | 0x0079, /* R32 - Left OPGA Volume */ | ||
74 | 0x0079, /* R33 - Right OPGA Volume */ | ||
75 | 0x0003, /* R34 - Speaker Volume */ | ||
76 | 0x0003, /* R35 - ClassD1 */ | ||
77 | 0x0000, /* R36 */ | ||
78 | 0x0100, /* R37 - ClassD3 */ | ||
79 | 0x0000, /* R38 */ | ||
80 | 0x0000, /* R39 - Input Mixer1 */ | ||
81 | 0x0000, /* R40 - Input Mixer2 */ | ||
82 | 0x0000, /* R41 - Input Mixer3 */ | ||
83 | 0x0000, /* R42 - Input Mixer4 */ | ||
84 | 0x0000, /* R43 - Input Mixer5 */ | ||
85 | 0x0000, /* R44 - Input Mixer6 */ | ||
86 | 0x0000, /* R45 - Output Mixer1 */ | ||
87 | 0x0000, /* R46 - Output Mixer2 */ | ||
88 | 0x0000, /* R47 - Output Mixer3 */ | ||
89 | 0x0000, /* R48 - Output Mixer4 */ | ||
90 | 0x0000, /* R49 - Output Mixer5 */ | ||
91 | 0x0000, /* R50 - Output Mixer6 */ | ||
92 | 0x0180, /* R51 - Out3/4 Mixer */ | ||
93 | 0x0000, /* R52 - Line Mixer1 */ | ||
94 | 0x0000, /* R53 - Line Mixer2 */ | ||
95 | 0x0000, /* R54 - Speaker Mixer */ | ||
96 | 0x0000, /* R55 - Additional Control */ | ||
97 | 0x0000, /* R56 - AntiPOP1 */ | ||
98 | 0x0000, /* R57 - AntiPOP2 */ | ||
99 | 0x0000, /* R58 - MICBIAS */ | ||
100 | 0x0000, /* R59 */ | ||
101 | 0x0008, /* R60 - PLL1 */ | ||
102 | 0x0031, /* R61 - PLL2 */ | ||
103 | 0x0026, /* R62 - PLL3 */ | ||
104 | }; | ||
105 | |||
106 | #define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0) | ||
107 | |||
108 | static const unsigned int rec_mix_tlv[] = { | ||
109 | TLV_DB_RANGE_HEAD(1), | ||
110 | 0, 7, TLV_DB_LINEAR_ITEM(-1500, 600), | ||
111 | }; | ||
112 | |||
113 | static const unsigned int in_pga_tlv[] = { | ||
114 | TLV_DB_RANGE_HEAD(1), | ||
115 | 0, 0x1F, TLV_DB_LINEAR_ITEM(-1650, 3000), | ||
116 | }; | ||
117 | |||
118 | static const unsigned int out_mix_tlv[] = { | ||
119 | TLV_DB_RANGE_HEAD(1), | ||
120 | 0, 7, TLV_DB_LINEAR_ITEM(0, -2100), | ||
121 | }; | ||
122 | |||
123 | static const unsigned int out_pga_tlv[] = { | ||
124 | TLV_DB_RANGE_HEAD(1), | ||
125 | 0, 127, TLV_DB_LINEAR_ITEM(-7300, 600), | ||
126 | }; | ||
127 | |||
128 | static const unsigned int out_omix_tlv[] = { | ||
129 | TLV_DB_RANGE_HEAD(1), | ||
130 | 0, 7, TLV_DB_LINEAR_ITEM(-600, 0), | ||
131 | }; | ||
132 | |||
133 | static const unsigned int out_dac_tlv[] = { | ||
134 | TLV_DB_RANGE_HEAD(1), | ||
135 | 0, 255, TLV_DB_LINEAR_ITEM(-7163, 0), | ||
136 | }; | ||
137 | |||
138 | static const unsigned int in_adc_tlv[] = { | ||
139 | TLV_DB_RANGE_HEAD(1), | ||
140 | 0, 255, TLV_DB_LINEAR_ITEM(-7163, 1763), | ||
141 | }; | ||
142 | |||
143 | static const unsigned int out_sidetone_tlv[] = { | ||
144 | TLV_DB_RANGE_HEAD(1), | ||
145 | 0, 31, TLV_DB_LINEAR_ITEM(-3600, 0), | ||
146 | }; | ||
147 | |||
148 | static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | ||
149 | struct snd_ctl_elem_value *ucontrol) | ||
150 | { | ||
151 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
152 | int reg = kcontrol->private_value & 0xff; | ||
153 | int ret; | ||
154 | u16 val; | ||
155 | |||
156 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | ||
157 | if (ret < 0) | ||
158 | return ret; | ||
159 | |||
160 | /* now hit the volume update bits (always bit 8) */ | ||
161 | val = snd_soc_read(codec, reg); | ||
162 | return snd_soc_write(codec, reg, val | 0x0100); | ||
163 | } | ||
164 | |||
165 | static const char *wm8991_digital_sidetone[] = | ||
166 | {"None", "Left ADC", "Right ADC", "Reserved"}; | ||
167 | |||
168 | static const struct soc_enum wm8991_left_digital_sidetone_enum = | ||
169 | SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, | ||
170 | WM8991_ADC_TO_DACL_SHIFT, | ||
171 | WM8991_ADC_TO_DACL_MASK, | ||
172 | wm8991_digital_sidetone); | ||
173 | |||
174 | static const struct soc_enum wm8991_right_digital_sidetone_enum = | ||
175 | SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE, | ||
176 | WM8991_ADC_TO_DACR_SHIFT, | ||
177 | WM8991_ADC_TO_DACR_MASK, | ||
178 | wm8991_digital_sidetone); | ||
179 | |||
180 | static const char *wm8991_adcmode[] = | ||
181 | {"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"}; | ||
182 | |||
183 | static const struct soc_enum wm8991_right_adcmode_enum = | ||
184 | SOC_ENUM_SINGLE(WM8991_ADC_CTRL, | ||
185 | WM8991_ADC_HPF_CUT_SHIFT, | ||
186 | WM8991_ADC_HPF_CUT_MASK, | ||
187 | wm8991_adcmode); | ||
188 | |||
189 | static const struct snd_kcontrol_new wm8991_snd_controls[] = { | ||
190 | /* INMIXL */ | ||
191 | SOC_SINGLE("LIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L12MNBST_BIT, 1, 0), | ||
192 | SOC_SINGLE("LIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L34MNBST_BIT, 1, 0), | ||
193 | /* INMIXR */ | ||
194 | SOC_SINGLE("RIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R12MNBST_BIT, 1, 0), | ||
195 | SOC_SINGLE("RIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R34MNBST_BIT, 1, 0), | ||
196 | |||
197 | /* LOMIX */ | ||
198 | SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER3, | ||
199 | WM8991_LLI3LOVOL_SHIFT, WM8991_LLI3LOVOL_MASK, 1, out_mix_tlv), | ||
200 | SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3, | ||
201 | WM8991_LR12LOVOL_SHIFT, WM8991_LR12LOVOL_MASK, 1, out_mix_tlv), | ||
202 | SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3, | ||
203 | WM8991_LL12LOVOL_SHIFT, WM8991_LL12LOVOL_MASK, 1, out_mix_tlv), | ||
204 | SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER5, | ||
205 | WM8991_LRI3LOVOL_SHIFT, WM8991_LRI3LOVOL_MASK, 1, out_mix_tlv), | ||
206 | SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER5, | ||
207 | WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv), | ||
208 | SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER5, | ||
209 | WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv), | ||
210 | |||
211 | /* ROMIX */ | ||
212 | SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER4, | ||
213 | WM8991_RRI3ROVOL_SHIFT, WM8991_RRI3ROVOL_MASK, 1, out_mix_tlv), | ||
214 | SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4, | ||
215 | WM8991_RL12ROVOL_SHIFT, WM8991_RL12ROVOL_MASK, 1, out_mix_tlv), | ||
216 | SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4, | ||
217 | WM8991_RR12ROVOL_SHIFT, WM8991_RR12ROVOL_MASK, 1, out_mix_tlv), | ||
218 | SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER6, | ||
219 | WM8991_RLI3ROVOL_SHIFT, WM8991_RLI3ROVOL_MASK, 1, out_mix_tlv), | ||
220 | SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER6, | ||
221 | WM8991_RLBROVOL_SHIFT, WM8991_RLBROVOL_MASK, 1, out_mix_tlv), | ||
222 | SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER6, | ||
223 | WM8991_RRBROVOL_SHIFT, WM8991_RRBROVOL_MASK, 1, out_mix_tlv), | ||
224 | |||
225 | /* LOUT */ | ||
226 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8991_LEFT_OUTPUT_VOLUME, | ||
227 | WM8991_LOUTVOL_SHIFT, WM8991_LOUTVOL_MASK, 0, out_pga_tlv), | ||
228 | SOC_SINGLE("LOUT ZC", WM8991_LEFT_OUTPUT_VOLUME, WM8991_LOZC_BIT, 1, 0), | ||
229 | |||
230 | /* ROUT */ | ||
231 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8991_RIGHT_OUTPUT_VOLUME, | ||
232 | WM8991_ROUTVOL_SHIFT, WM8991_ROUTVOL_MASK, 0, out_pga_tlv), | ||
233 | SOC_SINGLE("ROUT ZC", WM8991_RIGHT_OUTPUT_VOLUME, WM8991_ROZC_BIT, 1, 0), | ||
234 | |||
235 | /* LOPGA */ | ||
236 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8991_LEFT_OPGA_VOLUME, | ||
237 | WM8991_LOPGAVOL_SHIFT, WM8991_LOPGAVOL_MASK, 0, out_pga_tlv), | ||
238 | SOC_SINGLE("LOPGA ZC Switch", WM8991_LEFT_OPGA_VOLUME, | ||
239 | WM8991_LOPGAZC_BIT, 1, 0), | ||
240 | |||
241 | /* ROPGA */ | ||
242 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8991_RIGHT_OPGA_VOLUME, | ||
243 | WM8991_ROPGAVOL_SHIFT, WM8991_ROPGAVOL_MASK, 0, out_pga_tlv), | ||
244 | SOC_SINGLE("ROPGA ZC Switch", WM8991_RIGHT_OPGA_VOLUME, | ||
245 | WM8991_ROPGAZC_BIT, 1, 0), | ||
246 | |||
247 | SOC_SINGLE("LON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, | ||
248 | WM8991_LONMUTE_BIT, 1, 0), | ||
249 | SOC_SINGLE("LOP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, | ||
250 | WM8991_LOPMUTE_BIT, 1, 0), | ||
251 | SOC_SINGLE("LOP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME, | ||
252 | WM8991_LOATTN_BIT, 1, 0), | ||
253 | SOC_SINGLE("RON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, | ||
254 | WM8991_RONMUTE_BIT, 1, 0), | ||
255 | SOC_SINGLE("ROP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME, | ||
256 | WM8991_ROPMUTE_BIT, 1, 0), | ||
257 | SOC_SINGLE("ROP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME, | ||
258 | WM8991_ROATTN_BIT, 1, 0), | ||
259 | |||
260 | SOC_SINGLE("OUT3 Mute Switch", WM8991_OUT3_4_VOLUME, | ||
261 | WM8991_OUT3MUTE_BIT, 1, 0), | ||
262 | SOC_SINGLE("OUT3 Attenuation Switch", WM8991_OUT3_4_VOLUME, | ||
263 | WM8991_OUT3ATTN_BIT, 1, 0), | ||
264 | |||
265 | SOC_SINGLE("OUT4 Mute Switch", WM8991_OUT3_4_VOLUME, | ||
266 | WM8991_OUT4MUTE_BIT, 1, 0), | ||
267 | SOC_SINGLE("OUT4 Attenuation Switch", WM8991_OUT3_4_VOLUME, | ||
268 | WM8991_OUT4ATTN_BIT, 1, 0), | ||
269 | |||
270 | SOC_SINGLE("Speaker Mode Switch", WM8991_CLASSD1, | ||
271 | WM8991_CDMODE_BIT, 1, 0), | ||
272 | |||
273 | SOC_SINGLE("Speaker Output Attenuation Volume", WM8991_SPEAKER_VOLUME, | ||
274 | WM8991_SPKVOL_SHIFT, WM8991_SPKVOL_MASK, 0), | ||
275 | SOC_SINGLE("Speaker DC Boost Volume", WM8991_CLASSD3, | ||
276 | WM8991_DCGAIN_SHIFT, WM8991_DCGAIN_MASK, 0), | ||
277 | SOC_SINGLE("Speaker AC Boost Volume", WM8991_CLASSD3, | ||
278 | WM8991_ACGAIN_SHIFT, WM8991_ACGAIN_MASK, 0), | ||
279 | |||
280 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume", | ||
281 | WM8991_LEFT_DAC_DIGITAL_VOLUME, | ||
282 | WM8991_DACL_VOL_SHIFT, | ||
283 | WM8991_DACL_VOL_MASK, | ||
284 | 0, | ||
285 | out_dac_tlv), | ||
286 | |||
287 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume", | ||
288 | WM8991_RIGHT_DAC_DIGITAL_VOLUME, | ||
289 | WM8991_DACR_VOL_SHIFT, | ||
290 | WM8991_DACR_VOL_MASK, | ||
291 | 0, | ||
292 | out_dac_tlv), | ||
293 | |||
294 | SOC_ENUM("Left Digital Sidetone", wm8991_left_digital_sidetone_enum), | ||
295 | SOC_ENUM("Right Digital Sidetone", wm8991_right_digital_sidetone_enum), | ||
296 | |||
297 | SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE, | ||
298 | WM8991_ADCL_DAC_SVOL_SHIFT, WM8991_ADCL_DAC_SVOL_MASK, 0, | ||
299 | out_sidetone_tlv), | ||
300 | SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE, | ||
301 | WM8991_ADCR_DAC_SVOL_SHIFT, WM8991_ADCR_DAC_SVOL_MASK, 0, | ||
302 | out_sidetone_tlv), | ||
303 | |||
304 | SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8991_ADC_CTRL, | ||
305 | WM8991_ADC_HPF_ENA_BIT, 1, 0), | ||
306 | |||
307 | SOC_ENUM("ADC HPF Mode", wm8991_right_adcmode_enum), | ||
308 | |||
309 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume", | ||
310 | WM8991_LEFT_ADC_DIGITAL_VOLUME, | ||
311 | WM8991_ADCL_VOL_SHIFT, | ||
312 | WM8991_ADCL_VOL_MASK, | ||
313 | 0, | ||
314 | in_adc_tlv), | ||
315 | |||
316 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume", | ||
317 | WM8991_RIGHT_ADC_DIGITAL_VOLUME, | ||
318 | WM8991_ADCR_VOL_SHIFT, | ||
319 | WM8991_ADCR_VOL_MASK, | ||
320 | 0, | ||
321 | in_adc_tlv), | ||
322 | |||
323 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume", | ||
324 | WM8991_LEFT_LINE_INPUT_1_2_VOLUME, | ||
325 | WM8991_LIN12VOL_SHIFT, | ||
326 | WM8991_LIN12VOL_MASK, | ||
327 | 0, | ||
328 | in_pga_tlv), | ||
329 | |||
330 | SOC_SINGLE("LIN12 ZC Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME, | ||
331 | WM8991_LI12ZC_BIT, 1, 0), | ||
332 | |||
333 | SOC_SINGLE("LIN12 Mute Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME, | ||
334 | WM8991_LI12MUTE_BIT, 1, 0), | ||
335 | |||
336 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume", | ||
337 | WM8991_LEFT_LINE_INPUT_3_4_VOLUME, | ||
338 | WM8991_LIN34VOL_SHIFT, | ||
339 | WM8991_LIN34VOL_MASK, | ||
340 | 0, | ||
341 | in_pga_tlv), | ||
342 | |||
343 | SOC_SINGLE("LIN34 ZC Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME, | ||
344 | WM8991_LI34ZC_BIT, 1, 0), | ||
345 | |||
346 | SOC_SINGLE("LIN34 Mute Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME, | ||
347 | WM8991_LI34MUTE_BIT, 1, 0), | ||
348 | |||
349 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume", | ||
350 | WM8991_RIGHT_LINE_INPUT_1_2_VOLUME, | ||
351 | WM8991_RIN12VOL_SHIFT, | ||
352 | WM8991_RIN12VOL_MASK, | ||
353 | 0, | ||
354 | in_pga_tlv), | ||
355 | |||
356 | SOC_SINGLE("RIN12 ZC Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME, | ||
357 | WM8991_RI12ZC_BIT, 1, 0), | ||
358 | |||
359 | SOC_SINGLE("RIN12 Mute Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME, | ||
360 | WM8991_RI12MUTE_BIT, 1, 0), | ||
361 | |||
362 | SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume", | ||
363 | WM8991_RIGHT_LINE_INPUT_3_4_VOLUME, | ||
364 | WM8991_RIN34VOL_SHIFT, | ||
365 | WM8991_RIN34VOL_MASK, | ||
366 | 0, | ||
367 | in_pga_tlv), | ||
368 | |||
369 | SOC_SINGLE("RIN34 ZC Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME, | ||
370 | WM8991_RI34ZC_BIT, 1, 0), | ||
371 | |||
372 | SOC_SINGLE("RIN34 Mute Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME, | ||
373 | WM8991_RI34MUTE_BIT, 1, 0), | ||
374 | }; | ||
375 | |||
376 | /* | ||
377 | * _DAPM_ Controls | ||
378 | */ | ||
379 | static int inmixer_event(struct snd_soc_dapm_widget *w, | ||
380 | struct snd_kcontrol *kcontrol, int event) | ||
381 | { | ||
382 | u16 reg, fakepower; | ||
383 | |||
384 | reg = snd_soc_read(w->codec, WM8991_POWER_MANAGEMENT_2); | ||
385 | fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS); | ||
386 | |||
387 | if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) | | ||
388 | (1 << WM8991_AINLMUX_PWR_BIT))) | ||
389 | reg |= WM8991_AINL_ENA; | ||
390 | else | ||
391 | reg &= ~WM8991_AINL_ENA; | ||
392 | |||
393 | if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) | | ||
394 | (1 << WM8991_AINRMUX_PWR_BIT))) | ||
395 | reg |= WM8991_AINR_ENA; | ||
396 | else | ||
397 | reg &= ~WM8991_AINL_ENA; | ||
398 | |||
399 | snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg); | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int outmixer_event(struct snd_soc_dapm_widget *w, | ||
404 | struct snd_kcontrol *kcontrol, int event) | ||
405 | { | ||
406 | u32 reg_shift = kcontrol->private_value & 0xfff; | ||
407 | int ret = 0; | ||
408 | u16 reg; | ||
409 | |||
410 | switch (reg_shift) { | ||
411 | case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8): | ||
412 | reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER1); | ||
413 | if (reg & WM8991_LDLO) { | ||
414 | printk(KERN_WARNING | ||
415 | "Cannot set as Output Mixer 1 LDLO Set\n"); | ||
416 | ret = -1; | ||
417 | } | ||
418 | break; | ||
419 | |||
420 | case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8): | ||
421 | reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER2); | ||
422 | if (reg & WM8991_RDRO) { | ||
423 | printk(KERN_WARNING | ||
424 | "Cannot set as Output Mixer 2 RDRO Set\n"); | ||
425 | ret = -1; | ||
426 | } | ||
427 | break; | ||
428 | |||
429 | case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8): | ||
430 | reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER); | ||
431 | if (reg & WM8991_LDSPK) { | ||
432 | printk(KERN_WARNING | ||
433 | "Cannot set as Speaker Mixer LDSPK Set\n"); | ||
434 | ret = -1; | ||
435 | } | ||
436 | break; | ||
437 | |||
438 | case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8): | ||
439 | reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER); | ||
440 | if (reg & WM8991_RDSPK) { | ||
441 | printk(KERN_WARNING | ||
442 | "Cannot set as Speaker Mixer RDSPK Set\n"); | ||
443 | ret = -1; | ||
444 | } | ||
445 | break; | ||
446 | } | ||
447 | |||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | /* INMIX dB values */ | ||
452 | static const unsigned int in_mix_tlv[] = { | ||
453 | TLV_DB_RANGE_HEAD(1), | ||
454 | 0, 7, TLV_DB_LINEAR_ITEM(-1200, 600), | ||
455 | }; | ||
456 | |||
457 | /* Left In PGA Connections */ | ||
458 | static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = { | ||
459 | SOC_DAPM_SINGLE("LIN1 Switch", WM8991_INPUT_MIXER2, WM8991_LMN1_BIT, 1, 0), | ||
460 | SOC_DAPM_SINGLE("LIN2 Switch", WM8991_INPUT_MIXER2, WM8991_LMP2_BIT, 1, 0), | ||
461 | }; | ||
462 | |||
463 | static const struct snd_kcontrol_new wm8991_dapm_lin34_pga_controls[] = { | ||
464 | SOC_DAPM_SINGLE("LIN3 Switch", WM8991_INPUT_MIXER2, WM8991_LMN3_BIT, 1, 0), | ||
465 | SOC_DAPM_SINGLE("LIN4 Switch", WM8991_INPUT_MIXER2, WM8991_LMP4_BIT, 1, 0), | ||
466 | }; | ||
467 | |||
468 | /* Right In PGA Connections */ | ||
469 | static const struct snd_kcontrol_new wm8991_dapm_rin12_pga_controls[] = { | ||
470 | SOC_DAPM_SINGLE("RIN1 Switch", WM8991_INPUT_MIXER2, WM8991_RMN1_BIT, 1, 0), | ||
471 | SOC_DAPM_SINGLE("RIN2 Switch", WM8991_INPUT_MIXER2, WM8991_RMP2_BIT, 1, 0), | ||
472 | }; | ||
473 | |||
474 | static const struct snd_kcontrol_new wm8991_dapm_rin34_pga_controls[] = { | ||
475 | SOC_DAPM_SINGLE("RIN3 Switch", WM8991_INPUT_MIXER2, WM8991_RMN3_BIT, 1, 0), | ||
476 | SOC_DAPM_SINGLE("RIN4 Switch", WM8991_INPUT_MIXER2, WM8991_RMP4_BIT, 1, 0), | ||
477 | }; | ||
478 | |||
479 | /* INMIXL */ | ||
480 | static const struct snd_kcontrol_new wm8991_dapm_inmixl_controls[] = { | ||
481 | SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8991_INPUT_MIXER3, | ||
482 | WM8991_LDBVOL_SHIFT, WM8991_LDBVOL_MASK, 0, in_mix_tlv), | ||
483 | SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8991_INPUT_MIXER5, WM8991_LI2BVOL_SHIFT, | ||
484 | 7, 0, in_mix_tlv), | ||
485 | SOC_DAPM_SINGLE("LINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT, | ||
486 | 1, 0), | ||
487 | SOC_DAPM_SINGLE("LINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT, | ||
488 | 1, 0), | ||
489 | }; | ||
490 | |||
491 | /* INMIXR */ | ||
492 | static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = { | ||
493 | SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8991_INPUT_MIXER4, | ||
494 | WM8991_RDBVOL_SHIFT, WM8991_RDBVOL_MASK, 0, in_mix_tlv), | ||
495 | SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8991_INPUT_MIXER6, WM8991_RI2BVOL_SHIFT, | ||
496 | 7, 0, in_mix_tlv), | ||
497 | SOC_DAPM_SINGLE("RINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT, | ||
498 | 1, 0), | ||
499 | SOC_DAPM_SINGLE("RINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT, | ||
500 | 1, 0), | ||
501 | }; | ||
502 | |||
503 | /* AINLMUX */ | ||
504 | static const char *wm8991_ainlmux[] = | ||
505 | {"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"}; | ||
506 | |||
507 | static const struct soc_enum wm8991_ainlmux_enum = | ||
508 | SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT, | ||
509 | ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux); | ||
510 | |||
511 | static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls = | ||
512 | SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum); | ||
513 | |||
514 | /* DIFFINL */ | ||
515 | |||
516 | /* AINRMUX */ | ||
517 | static const char *wm8991_ainrmux[] = | ||
518 | {"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"}; | ||
519 | |||
520 | static const struct soc_enum wm8991_ainrmux_enum = | ||
521 | SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT, | ||
522 | ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux); | ||
523 | |||
524 | static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls = | ||
525 | SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum); | ||
526 | |||
527 | /* RXVOICE */ | ||
528 | static const struct snd_kcontrol_new wm8991_dapm_rxvoice_controls[] = { | ||
529 | SOC_DAPM_SINGLE_TLV("LIN4RXN", WM8991_INPUT_MIXER5, WM8991_LR4BVOL_SHIFT, | ||
530 | WM8991_LR4BVOL_MASK, 0, in_mix_tlv), | ||
531 | SOC_DAPM_SINGLE_TLV("RIN4RXP", WM8991_INPUT_MIXER6, WM8991_RL4BVOL_SHIFT, | ||
532 | WM8991_RL4BVOL_MASK, 0, in_mix_tlv), | ||
533 | }; | ||
534 | |||
535 | /* LOMIX */ | ||
536 | static const struct snd_kcontrol_new wm8991_dapm_lomix_controls[] = { | ||
537 | SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER1, | ||
538 | WM8991_LRBLO_BIT, 1, 0), | ||
539 | SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER1, | ||
540 | WM8991_LLBLO_BIT, 1, 0), | ||
541 | SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER1, | ||
542 | WM8991_LRI3LO_BIT, 1, 0), | ||
543 | SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER1, | ||
544 | WM8991_LLI3LO_BIT, 1, 0), | ||
545 | SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1, | ||
546 | WM8991_LR12LO_BIT, 1, 0), | ||
547 | SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1, | ||
548 | WM8991_LL12LO_BIT, 1, 0), | ||
549 | SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8991_OUTPUT_MIXER1, | ||
550 | WM8991_LDLO_BIT, 1, 0), | ||
551 | }; | ||
552 | |||
553 | /* ROMIX */ | ||
554 | static const struct snd_kcontrol_new wm8991_dapm_romix_controls[] = { | ||
555 | SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER2, | ||
556 | WM8991_RLBRO_BIT, 1, 0), | ||
557 | SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER2, | ||
558 | WM8991_RRBRO_BIT, 1, 0), | ||
559 | SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER2, | ||
560 | WM8991_RLI3RO_BIT, 1, 0), | ||
561 | SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER2, | ||
562 | WM8991_RRI3RO_BIT, 1, 0), | ||
563 | SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2, | ||
564 | WM8991_RL12RO_BIT, 1, 0), | ||
565 | SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2, | ||
566 | WM8991_RR12RO_BIT, 1, 0), | ||
567 | SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8991_OUTPUT_MIXER2, | ||
568 | WM8991_RDRO_BIT, 1, 0), | ||
569 | }; | ||
570 | |||
571 | /* LONMIX */ | ||
572 | static const struct snd_kcontrol_new wm8991_dapm_lonmix_controls[] = { | ||
573 | SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1, | ||
574 | WM8991_LLOPGALON_BIT, 1, 0), | ||
575 | SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER1, | ||
576 | WM8991_LROPGALON_BIT, 1, 0), | ||
577 | SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8991_LINE_MIXER1, | ||
578 | WM8991_LOPLON_BIT, 1, 0), | ||
579 | }; | ||
580 | |||
581 | /* LOPMIX */ | ||
582 | static const struct snd_kcontrol_new wm8991_dapm_lopmix_controls[] = { | ||
583 | SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER1, | ||
584 | WM8991_LR12LOP_BIT, 1, 0), | ||
585 | SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER1, | ||
586 | WM8991_LL12LOP_BIT, 1, 0), | ||
587 | SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1, | ||
588 | WM8991_LLOPGALOP_BIT, 1, 0), | ||
589 | }; | ||
590 | |||
591 | /* RONMIX */ | ||
592 | static const struct snd_kcontrol_new wm8991_dapm_ronmix_controls[] = { | ||
593 | SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2, | ||
594 | WM8991_RROPGARON_BIT, 1, 0), | ||
595 | SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER2, | ||
596 | WM8991_RLOPGARON_BIT, 1, 0), | ||
597 | SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8991_LINE_MIXER2, | ||
598 | WM8991_ROPRON_BIT, 1, 0), | ||
599 | }; | ||
600 | |||
601 | /* ROPMIX */ | ||
602 | static const struct snd_kcontrol_new wm8991_dapm_ropmix_controls[] = { | ||
603 | SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER2, | ||
604 | WM8991_RL12ROP_BIT, 1, 0), | ||
605 | SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER2, | ||
606 | WM8991_RR12ROP_BIT, 1, 0), | ||
607 | SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2, | ||
608 | WM8991_RROPGAROP_BIT, 1, 0), | ||
609 | }; | ||
610 | |||
611 | /* OUT3MIX */ | ||
612 | static const struct snd_kcontrol_new wm8991_dapm_out3mix_controls[] = { | ||
613 | SOC_DAPM_SINGLE("OUT3MIX LIN4RXN Bypass Switch", WM8991_OUT3_4_MIXER, | ||
614 | WM8991_LI4O3_BIT, 1, 0), | ||
615 | SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8991_OUT3_4_MIXER, | ||
616 | WM8991_LPGAO3_BIT, 1, 0), | ||
617 | }; | ||
618 | |||
619 | /* OUT4MIX */ | ||
620 | static const struct snd_kcontrol_new wm8991_dapm_out4mix_controls[] = { | ||
621 | SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8991_OUT3_4_MIXER, | ||
622 | WM8991_RPGAO4_BIT, 1, 0), | ||
623 | SOC_DAPM_SINGLE("OUT4MIX RIN4RXP Bypass Switch", WM8991_OUT3_4_MIXER, | ||
624 | WM8991_RI4O4_BIT, 1, 0), | ||
625 | }; | ||
626 | |||
627 | /* SPKMIX */ | ||
628 | static const struct snd_kcontrol_new wm8991_dapm_spkmix_controls[] = { | ||
629 | SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8991_SPEAKER_MIXER, | ||
630 | WM8991_LI2SPK_BIT, 1, 0), | ||
631 | SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8991_SPEAKER_MIXER, | ||
632 | WM8991_LB2SPK_BIT, 1, 0), | ||
633 | SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8991_SPEAKER_MIXER, | ||
634 | WM8991_LOPGASPK_BIT, 1, 0), | ||
635 | SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8991_SPEAKER_MIXER, | ||
636 | WM8991_LDSPK_BIT, 1, 0), | ||
637 | SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8991_SPEAKER_MIXER, | ||
638 | WM8991_RDSPK_BIT, 1, 0), | ||
639 | SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8991_SPEAKER_MIXER, | ||
640 | WM8991_ROPGASPK_BIT, 1, 0), | ||
641 | SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8991_SPEAKER_MIXER, | ||
642 | WM8991_RL12ROP_BIT, 1, 0), | ||
643 | SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8991_SPEAKER_MIXER, | ||
644 | WM8991_RI2SPK_BIT, 1, 0), | ||
645 | }; | ||
646 | |||
647 | static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { | ||
648 | /* Input Side */ | ||
649 | /* Input Lines */ | ||
650 | SND_SOC_DAPM_INPUT("LIN1"), | ||
651 | SND_SOC_DAPM_INPUT("LIN2"), | ||
652 | SND_SOC_DAPM_INPUT("LIN3"), | ||
653 | SND_SOC_DAPM_INPUT("LIN4RXN"), | ||
654 | SND_SOC_DAPM_INPUT("RIN3"), | ||
655 | SND_SOC_DAPM_INPUT("RIN4RXP"), | ||
656 | SND_SOC_DAPM_INPUT("RIN1"), | ||
657 | SND_SOC_DAPM_INPUT("RIN2"), | ||
658 | SND_SOC_DAPM_INPUT("Internal ADC Source"), | ||
659 | |||
660 | /* DACs */ | ||
661 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2, | ||
662 | WM8991_ADCL_ENA_BIT, 0), | ||
663 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8991_POWER_MANAGEMENT_2, | ||
664 | WM8991_ADCR_ENA_BIT, 0), | ||
665 | |||
666 | /* Input PGAs */ | ||
667 | SND_SOC_DAPM_MIXER("LIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN12_ENA_BIT, | ||
668 | 0, &wm8991_dapm_lin12_pga_controls[0], | ||
669 | ARRAY_SIZE(wm8991_dapm_lin12_pga_controls)), | ||
670 | SND_SOC_DAPM_MIXER("LIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN34_ENA_BIT, | ||
671 | 0, &wm8991_dapm_lin34_pga_controls[0], | ||
672 | ARRAY_SIZE(wm8991_dapm_lin34_pga_controls)), | ||
673 | SND_SOC_DAPM_MIXER("RIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN12_ENA_BIT, | ||
674 | 0, &wm8991_dapm_rin12_pga_controls[0], | ||
675 | ARRAY_SIZE(wm8991_dapm_rin12_pga_controls)), | ||
676 | SND_SOC_DAPM_MIXER("RIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN34_ENA_BIT, | ||
677 | 0, &wm8991_dapm_rin34_pga_controls[0], | ||
678 | ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)), | ||
679 | |||
680 | /* INMIXL */ | ||
681 | SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0, | ||
682 | &wm8991_dapm_inmixl_controls[0], | ||
683 | ARRAY_SIZE(wm8991_dapm_inmixl_controls), | ||
684 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
685 | |||
686 | /* AINLMUX */ | ||
687 | SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0, | ||
688 | &wm8991_dapm_ainlmux_controls, inmixer_event, | ||
689 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
690 | |||
691 | /* INMIXR */ | ||
692 | SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0, | ||
693 | &wm8991_dapm_inmixr_controls[0], | ||
694 | ARRAY_SIZE(wm8991_dapm_inmixr_controls), | ||
695 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
696 | |||
697 | /* AINRMUX */ | ||
698 | SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0, | ||
699 | &wm8991_dapm_ainrmux_controls, inmixer_event, | ||
700 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
701 | |||
702 | /* Output Side */ | ||
703 | /* DACs */ | ||
704 | SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8991_POWER_MANAGEMENT_3, | ||
705 | WM8991_DACL_ENA_BIT, 0), | ||
706 | SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8991_POWER_MANAGEMENT_3, | ||
707 | WM8991_DACR_ENA_BIT, 0), | ||
708 | |||
709 | /* LOMIX */ | ||
710 | SND_SOC_DAPM_MIXER_E("LOMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOMIX_ENA_BIT, | ||
711 | 0, &wm8991_dapm_lomix_controls[0], | ||
712 | ARRAY_SIZE(wm8991_dapm_lomix_controls), | ||
713 | outmixer_event, SND_SOC_DAPM_PRE_REG), | ||
714 | |||
715 | /* LONMIX */ | ||
716 | SND_SOC_DAPM_MIXER("LONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LON_ENA_BIT, 0, | ||
717 | &wm8991_dapm_lonmix_controls[0], | ||
718 | ARRAY_SIZE(wm8991_dapm_lonmix_controls)), | ||
719 | |||
720 | /* LOPMIX */ | ||
721 | SND_SOC_DAPM_MIXER("LOPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOP_ENA_BIT, 0, | ||
722 | &wm8991_dapm_lopmix_controls[0], | ||
723 | ARRAY_SIZE(wm8991_dapm_lopmix_controls)), | ||
724 | |||
725 | /* OUT3MIX */ | ||
726 | SND_SOC_DAPM_MIXER("OUT3MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT3_ENA_BIT, 0, | ||
727 | &wm8991_dapm_out3mix_controls[0], | ||
728 | ARRAY_SIZE(wm8991_dapm_out3mix_controls)), | ||
729 | |||
730 | /* SPKMIX */ | ||
731 | SND_SOC_DAPM_MIXER_E("SPKMIX", WM8991_POWER_MANAGEMENT_1, WM8991_SPK_ENA_BIT, 0, | ||
732 | &wm8991_dapm_spkmix_controls[0], | ||
733 | ARRAY_SIZE(wm8991_dapm_spkmix_controls), outmixer_event, | ||
734 | SND_SOC_DAPM_PRE_REG), | ||
735 | |||
736 | /* OUT4MIX */ | ||
737 | SND_SOC_DAPM_MIXER("OUT4MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT4_ENA_BIT, 0, | ||
738 | &wm8991_dapm_out4mix_controls[0], | ||
739 | ARRAY_SIZE(wm8991_dapm_out4mix_controls)), | ||
740 | |||
741 | /* ROPMIX */ | ||
742 | SND_SOC_DAPM_MIXER("ROPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROP_ENA_BIT, 0, | ||
743 | &wm8991_dapm_ropmix_controls[0], | ||
744 | ARRAY_SIZE(wm8991_dapm_ropmix_controls)), | ||
745 | |||
746 | /* RONMIX */ | ||
747 | SND_SOC_DAPM_MIXER("RONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_RON_ENA_BIT, 0, | ||
748 | &wm8991_dapm_ronmix_controls[0], | ||
749 | ARRAY_SIZE(wm8991_dapm_ronmix_controls)), | ||
750 | |||
751 | /* ROMIX */ | ||
752 | SND_SOC_DAPM_MIXER_E("ROMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROMIX_ENA_BIT, | ||
753 | 0, &wm8991_dapm_romix_controls[0], | ||
754 | ARRAY_SIZE(wm8991_dapm_romix_controls), | ||
755 | outmixer_event, SND_SOC_DAPM_PRE_REG), | ||
756 | |||
757 | /* LOUT PGA */ | ||
758 | SND_SOC_DAPM_PGA("LOUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_LOUT_ENA_BIT, 0, | ||
759 | NULL, 0), | ||
760 | |||
761 | /* ROUT PGA */ | ||
762 | SND_SOC_DAPM_PGA("ROUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_ROUT_ENA_BIT, 0, | ||
763 | NULL, 0), | ||
764 | |||
765 | /* LOPGA */ | ||
766 | SND_SOC_DAPM_PGA("LOPGA", WM8991_POWER_MANAGEMENT_3, WM8991_LOPGA_ENA_BIT, 0, | ||
767 | NULL, 0), | ||
768 | |||
769 | /* ROPGA */ | ||
770 | SND_SOC_DAPM_PGA("ROPGA", WM8991_POWER_MANAGEMENT_3, WM8991_ROPGA_ENA_BIT, 0, | ||
771 | NULL, 0), | ||
772 | |||
773 | /* MICBIAS */ | ||
774 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8991_POWER_MANAGEMENT_1, | ||
775 | WM8991_MICBIAS_ENA_BIT, 0), | ||
776 | |||
777 | SND_SOC_DAPM_OUTPUT("LON"), | ||
778 | SND_SOC_DAPM_OUTPUT("LOP"), | ||
779 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
780 | SND_SOC_DAPM_OUTPUT("LOUT"), | ||
781 | SND_SOC_DAPM_OUTPUT("SPKN"), | ||
782 | SND_SOC_DAPM_OUTPUT("SPKP"), | ||
783 | SND_SOC_DAPM_OUTPUT("ROUT"), | ||
784 | SND_SOC_DAPM_OUTPUT("OUT4"), | ||
785 | SND_SOC_DAPM_OUTPUT("ROP"), | ||
786 | SND_SOC_DAPM_OUTPUT("RON"), | ||
787 | SND_SOC_DAPM_OUTPUT("OUT"), | ||
788 | |||
789 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), | ||
790 | }; | ||
791 | |||
792 | static const struct snd_soc_dapm_route audio_map[] = { | ||
793 | /* Make DACs turn on when playing even if not mixed into any outputs */ | ||
794 | {"Internal DAC Sink", NULL, "Left DAC"}, | ||
795 | {"Internal DAC Sink", NULL, "Right DAC"}, | ||
796 | |||
797 | /* Make ADCs turn on when recording even if not mixed from any inputs */ | ||
798 | {"Left ADC", NULL, "Internal ADC Source"}, | ||
799 | {"Right ADC", NULL, "Internal ADC Source"}, | ||
800 | |||
801 | /* Input Side */ | ||
802 | /* LIN12 PGA */ | ||
803 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, | ||
804 | {"LIN12 PGA", "LIN2 Switch", "LIN2"}, | ||
805 | /* LIN34 PGA */ | ||
806 | {"LIN34 PGA", "LIN3 Switch", "LIN3"}, | ||
807 | {"LIN34 PGA", "LIN4 Switch", "LIN4RXN"}, | ||
808 | /* INMIXL */ | ||
809 | {"INMIXL", "Record Left Volume", "LOMIX"}, | ||
810 | {"INMIXL", "LIN2 Volume", "LIN2"}, | ||
811 | {"INMIXL", "LINPGA12 Switch", "LIN12 PGA"}, | ||
812 | {"INMIXL", "LINPGA34 Switch", "LIN34 PGA"}, | ||
813 | /* AINLMUX */ | ||
814 | {"AINLMUX", "INMIXL Mix", "INMIXL"}, | ||
815 | {"AINLMUX", "DIFFINL Mix", "LIN12 PGA"}, | ||
816 | {"AINLMUX", "DIFFINL Mix", "LIN34 PGA"}, | ||
817 | {"AINLMUX", "RXVOICE Mix", "LIN4RXN"}, | ||
818 | {"AINLMUX", "RXVOICE Mix", "RIN4RXP"}, | ||
819 | /* ADC */ | ||
820 | {"Left ADC", NULL, "AINLMUX"}, | ||
821 | |||
822 | /* RIN12 PGA */ | ||
823 | {"RIN12 PGA", "RIN1 Switch", "RIN1"}, | ||
824 | {"RIN12 PGA", "RIN2 Switch", "RIN2"}, | ||
825 | /* RIN34 PGA */ | ||
826 | {"RIN34 PGA", "RIN3 Switch", "RIN3"}, | ||
827 | {"RIN34 PGA", "RIN4 Switch", "RIN4RXP"}, | ||
828 | /* INMIXL */ | ||
829 | {"INMIXR", "Record Right Volume", "ROMIX"}, | ||
830 | {"INMIXR", "RIN2 Volume", "RIN2"}, | ||
831 | {"INMIXR", "RINPGA12 Switch", "RIN12 PGA"}, | ||
832 | {"INMIXR", "RINPGA34 Switch", "RIN34 PGA"}, | ||
833 | /* AINRMUX */ | ||
834 | {"AINRMUX", "INMIXR Mix", "INMIXR"}, | ||
835 | {"AINRMUX", "DIFFINR Mix", "RIN12 PGA"}, | ||
836 | {"AINRMUX", "DIFFINR Mix", "RIN34 PGA"}, | ||
837 | {"AINRMUX", "RXVOICE Mix", "LIN4RXN"}, | ||
838 | {"AINRMUX", "RXVOICE Mix", "RIN4RXP"}, | ||
839 | /* ADC */ | ||
840 | {"Right ADC", NULL, "AINRMUX"}, | ||
841 | |||
842 | /* LOMIX */ | ||
843 | {"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"}, | ||
844 | {"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"}, | ||
845 | {"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, | ||
846 | {"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, | ||
847 | {"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"}, | ||
848 | {"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"}, | ||
849 | {"LOMIX", "LOMIX Left DAC Switch", "Left DAC"}, | ||
850 | |||
851 | /* ROMIX */ | ||
852 | {"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"}, | ||
853 | {"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"}, | ||
854 | {"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"}, | ||
855 | {"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"}, | ||
856 | {"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"}, | ||
857 | {"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"}, | ||
858 | {"ROMIX", "ROMIX Right DAC Switch", "Right DAC"}, | ||
859 | |||
860 | /* SPKMIX */ | ||
861 | {"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"}, | ||
862 | {"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"}, | ||
863 | {"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"}, | ||
864 | {"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"}, | ||
865 | {"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"}, | ||
866 | {"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"}, | ||
867 | {"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"}, | ||
868 | {"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"}, | ||
869 | |||
870 | /* LONMIX */ | ||
871 | {"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"}, | ||
872 | {"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"}, | ||
873 | {"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"}, | ||
874 | |||
875 | /* LOPMIX */ | ||
876 | {"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"}, | ||
877 | {"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"}, | ||
878 | {"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"}, | ||
879 | |||
880 | /* OUT3MIX */ | ||
881 | {"OUT3MIX", "OUT3MIX LIN4RXN Bypass Switch", "LIN4RXN"}, | ||
882 | {"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"}, | ||
883 | |||
884 | /* OUT4MIX */ | ||
885 | {"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"}, | ||
886 | {"OUT4MIX", "OUT4MIX RIN4RXP Bypass Switch", "RIN4RXP"}, | ||
887 | |||
888 | /* RONMIX */ | ||
889 | {"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"}, | ||
890 | {"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"}, | ||
891 | {"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"}, | ||
892 | |||
893 | /* ROPMIX */ | ||
894 | {"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"}, | ||
895 | {"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"}, | ||
896 | {"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"}, | ||
897 | |||
898 | /* Out Mixer PGAs */ | ||
899 | {"LOPGA", NULL, "LOMIX"}, | ||
900 | {"ROPGA", NULL, "ROMIX"}, | ||
901 | |||
902 | {"LOUT PGA", NULL, "LOMIX"}, | ||
903 | {"ROUT PGA", NULL, "ROMIX"}, | ||
904 | |||
905 | /* Output Pins */ | ||
906 | {"LON", NULL, "LONMIX"}, | ||
907 | {"LOP", NULL, "LOPMIX"}, | ||
908 | {"OUT", NULL, "OUT3MIX"}, | ||
909 | {"LOUT", NULL, "LOUT PGA"}, | ||
910 | {"SPKN", NULL, "SPKMIX"}, | ||
911 | {"ROUT", NULL, "ROUT PGA"}, | ||
912 | {"OUT4", NULL, "OUT4MIX"}, | ||
913 | {"ROP", NULL, "ROPMIX"}, | ||
914 | {"RON", NULL, "RONMIX"}, | ||
915 | }; | ||
916 | |||
917 | /* PLL divisors */ | ||
918 | struct _pll_div { | ||
919 | u32 div2; | ||
920 | u32 n; | ||
921 | u32 k; | ||
922 | }; | ||
923 | |||
924 | /* The size in bits of the pll divide multiplied by 10 | ||
925 | * to allow rounding later */ | ||
926 | #define FIXED_PLL_SIZE ((1 << 16) * 10) | ||
927 | |||
928 | static void pll_factors(struct _pll_div *pll_div, unsigned int target, | ||
929 | unsigned int source) | ||
930 | { | ||
931 | u64 Kpart; | ||
932 | unsigned int K, Ndiv, Nmod; | ||
933 | |||
934 | |||
935 | Ndiv = target / source; | ||
936 | if (Ndiv < 6) { | ||
937 | source >>= 1; | ||
938 | pll_div->div2 = 1; | ||
939 | Ndiv = target / source; | ||
940 | } else | ||
941 | pll_div->div2 = 0; | ||
942 | |||
943 | if ((Ndiv < 6) || (Ndiv > 12)) | ||
944 | printk(KERN_WARNING | ||
945 | "WM8991 N value outwith recommended range! N = %d\n", Ndiv); | ||
946 | |||
947 | pll_div->n = Ndiv; | ||
948 | Nmod = target % source; | ||
949 | Kpart = FIXED_PLL_SIZE * (long long)Nmod; | ||
950 | |||
951 | do_div(Kpart, source); | ||
952 | |||
953 | K = Kpart & 0xFFFFFFFF; | ||
954 | |||
955 | /* Check if we need to round */ | ||
956 | if ((K % 10) >= 5) | ||
957 | K += 5; | ||
958 | |||
959 | /* Move down to proper range now rounding is done */ | ||
960 | K /= 10; | ||
961 | |||
962 | pll_div->k = K; | ||
963 | } | ||
964 | |||
965 | static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai, | ||
966 | int pll_id, int src, unsigned int freq_in, unsigned int freq_out) | ||
967 | { | ||
968 | u16 reg; | ||
969 | struct snd_soc_codec *codec = codec_dai->codec; | ||
970 | struct _pll_div pll_div; | ||
971 | |||
972 | if (freq_in && freq_out) { | ||
973 | pll_factors(&pll_div, freq_out * 4, freq_in); | ||
974 | |||
975 | /* Turn on PLL */ | ||
976 | reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2); | ||
977 | reg |= WM8991_PLL_ENA; | ||
978 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg); | ||
979 | |||
980 | /* sysclk comes from PLL */ | ||
981 | reg = snd_soc_read(codec, WM8991_CLOCKING_2); | ||
982 | snd_soc_write(codec, WM8991_CLOCKING_2, reg | WM8991_SYSCLK_SRC); | ||
983 | |||
984 | /* set up N , fractional mode and pre-divisor if neccessary */ | ||
985 | snd_soc_write(codec, WM8991_PLL1, pll_div.n | WM8991_SDM | | ||
986 | (pll_div.div2 ? WM8991_PRESCALE : 0)); | ||
987 | snd_soc_write(codec, WM8991_PLL2, (u8)(pll_div.k>>8)); | ||
988 | snd_soc_write(codec, WM8991_PLL3, (u8)(pll_div.k & 0xFF)); | ||
989 | } else { | ||
990 | /* Turn on PLL */ | ||
991 | reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2); | ||
992 | reg &= ~WM8991_PLL_ENA; | ||
993 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg); | ||
994 | } | ||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | /* | ||
999 | * Set's ADC and Voice DAC format. | ||
1000 | */ | ||
1001 | static int wm8991_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
1002 | unsigned int fmt) | ||
1003 | { | ||
1004 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1005 | u16 audio1, audio3; | ||
1006 | |||
1007 | audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1); | ||
1008 | audio3 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_3); | ||
1009 | |||
1010 | /* set master/slave audio interface */ | ||
1011 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1012 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1013 | audio3 &= ~WM8991_AIF_MSTR1; | ||
1014 | break; | ||
1015 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1016 | audio3 |= WM8991_AIF_MSTR1; | ||
1017 | break; | ||
1018 | default: | ||
1019 | return -EINVAL; | ||
1020 | } | ||
1021 | |||
1022 | audio1 &= ~WM8991_AIF_FMT_MASK; | ||
1023 | |||
1024 | /* interface format */ | ||
1025 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1026 | case SND_SOC_DAIFMT_I2S: | ||
1027 | audio1 |= WM8991_AIF_TMF_I2S; | ||
1028 | audio1 &= ~WM8991_AIF_LRCLK_INV; | ||
1029 | break; | ||
1030 | case SND_SOC_DAIFMT_RIGHT_J: | ||
1031 | audio1 |= WM8991_AIF_TMF_RIGHTJ; | ||
1032 | audio1 &= ~WM8991_AIF_LRCLK_INV; | ||
1033 | break; | ||
1034 | case SND_SOC_DAIFMT_LEFT_J: | ||
1035 | audio1 |= WM8991_AIF_TMF_LEFTJ; | ||
1036 | audio1 &= ~WM8991_AIF_LRCLK_INV; | ||
1037 | break; | ||
1038 | case SND_SOC_DAIFMT_DSP_A: | ||
1039 | audio1 |= WM8991_AIF_TMF_DSP; | ||
1040 | audio1 &= ~WM8991_AIF_LRCLK_INV; | ||
1041 | break; | ||
1042 | case SND_SOC_DAIFMT_DSP_B: | ||
1043 | audio1 |= WM8991_AIF_TMF_DSP | WM8991_AIF_LRCLK_INV; | ||
1044 | break; | ||
1045 | default: | ||
1046 | return -EINVAL; | ||
1047 | } | ||
1048 | |||
1049 | snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1); | ||
1050 | snd_soc_write(codec, WM8991_AUDIO_INTERFACE_3, audio3); | ||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1054 | static int wm8991_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | ||
1055 | int div_id, int div) | ||
1056 | { | ||
1057 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1058 | u16 reg; | ||
1059 | |||
1060 | switch (div_id) { | ||
1061 | case WM8991_MCLK_DIV: | ||
1062 | reg = snd_soc_read(codec, WM8991_CLOCKING_2) & | ||
1063 | ~WM8991_MCLK_DIV_MASK; | ||
1064 | snd_soc_write(codec, WM8991_CLOCKING_2, reg | div); | ||
1065 | break; | ||
1066 | case WM8991_DACCLK_DIV: | ||
1067 | reg = snd_soc_read(codec, WM8991_CLOCKING_2) & | ||
1068 | ~WM8991_DAC_CLKDIV_MASK; | ||
1069 | snd_soc_write(codec, WM8991_CLOCKING_2, reg | div); | ||
1070 | break; | ||
1071 | case WM8991_ADCCLK_DIV: | ||
1072 | reg = snd_soc_read(codec, WM8991_CLOCKING_2) & | ||
1073 | ~WM8991_ADC_CLKDIV_MASK; | ||
1074 | snd_soc_write(codec, WM8991_CLOCKING_2, reg | div); | ||
1075 | break; | ||
1076 | case WM8991_BCLK_DIV: | ||
1077 | reg = snd_soc_read(codec, WM8991_CLOCKING_1) & | ||
1078 | ~WM8991_BCLK_DIV_MASK; | ||
1079 | snd_soc_write(codec, WM8991_CLOCKING_1, reg | div); | ||
1080 | break; | ||
1081 | default: | ||
1082 | return -EINVAL; | ||
1083 | } | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | /* | ||
1089 | * Set PCM DAI bit size and sample rate. | ||
1090 | */ | ||
1091 | static int wm8991_hw_params(struct snd_pcm_substream *substream, | ||
1092 | struct snd_pcm_hw_params *params, | ||
1093 | struct snd_soc_dai *dai) | ||
1094 | { | ||
1095 | struct snd_soc_codec *codec = dai->codec; | ||
1096 | u16 audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1); | ||
1097 | |||
1098 | audio1 &= ~WM8991_AIF_WL_MASK; | ||
1099 | /* bit size */ | ||
1100 | switch (params_format(params)) { | ||
1101 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1102 | break; | ||
1103 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
1104 | audio1 |= WM8991_AIF_WL_20BITS; | ||
1105 | break; | ||
1106 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1107 | audio1 |= WM8991_AIF_WL_24BITS; | ||
1108 | break; | ||
1109 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1110 | audio1 |= WM8991_AIF_WL_32BITS; | ||
1111 | break; | ||
1112 | } | ||
1113 | |||
1114 | snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1); | ||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | static int wm8991_mute(struct snd_soc_dai *dai, int mute) | ||
1119 | { | ||
1120 | struct snd_soc_codec *codec = dai->codec; | ||
1121 | u16 val; | ||
1122 | |||
1123 | val = snd_soc_read(codec, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE; | ||
1124 | if (mute) | ||
1125 | snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); | ||
1126 | else | ||
1127 | snd_soc_write(codec, WM8991_DAC_CTRL, val); | ||
1128 | return 0; | ||
1129 | } | ||
1130 | |||
1131 | static int wm8991_set_bias_level(struct snd_soc_codec *codec, | ||
1132 | enum snd_soc_bias_level level) | ||
1133 | { | ||
1134 | u16 val; | ||
1135 | |||
1136 | switch (level) { | ||
1137 | case SND_SOC_BIAS_ON: | ||
1138 | break; | ||
1139 | |||
1140 | case SND_SOC_BIAS_PREPARE: | ||
1141 | /* VMID=2*50k */ | ||
1142 | val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) & | ||
1143 | ~WM8991_VMID_MODE_MASK; | ||
1144 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x2); | ||
1145 | break; | ||
1146 | |||
1147 | case SND_SOC_BIAS_STANDBY: | ||
1148 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
1149 | snd_soc_cache_sync(codec); | ||
1150 | /* Enable all output discharge bits */ | ||
1151 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | | ||
1152 | WM8991_DIS_RLINE | WM8991_DIS_OUT3 | | ||
1153 | WM8991_DIS_OUT4 | WM8991_DIS_LOUT | | ||
1154 | WM8991_DIS_ROUT); | ||
1155 | |||
1156 | /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ | ||
1157 | snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | | ||
1158 | WM8991_BUFDCOPEN | WM8991_POBCTRL | | ||
1159 | WM8991_VMIDTOG); | ||
1160 | |||
1161 | /* Delay to allow output caps to discharge */ | ||
1162 | msleep(300); | ||
1163 | |||
1164 | /* Disable VMIDTOG */ | ||
1165 | snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | | ||
1166 | WM8991_BUFDCOPEN | WM8991_POBCTRL); | ||
1167 | |||
1168 | /* disable all output discharge bits */ | ||
1169 | snd_soc_write(codec, WM8991_ANTIPOP1, 0); | ||
1170 | |||
1171 | /* Enable outputs */ | ||
1172 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1b00); | ||
1173 | |||
1174 | msleep(50); | ||
1175 | |||
1176 | /* Enable VMID at 2x50k */ | ||
1177 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f02); | ||
1178 | |||
1179 | msleep(100); | ||
1180 | |||
1181 | /* Enable VREF */ | ||
1182 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03); | ||
1183 | |||
1184 | msleep(600); | ||
1185 | |||
1186 | /* Enable BUFIOEN */ | ||
1187 | snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | | ||
1188 | WM8991_BUFDCOPEN | WM8991_POBCTRL | | ||
1189 | WM8991_BUFIOEN); | ||
1190 | |||
1191 | /* Disable outputs */ | ||
1192 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x3); | ||
1193 | |||
1194 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | ||
1195 | snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_BUFIOEN); | ||
1196 | } | ||
1197 | |||
1198 | /* VMID=2*250k */ | ||
1199 | val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) & | ||
1200 | ~WM8991_VMID_MODE_MASK; | ||
1201 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x4); | ||
1202 | break; | ||
1203 | |||
1204 | case SND_SOC_BIAS_OFF: | ||
1205 | /* Enable POBCTRL and SOFT_ST */ | ||
1206 | snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | | ||
1207 | WM8991_POBCTRL | WM8991_BUFIOEN); | ||
1208 | |||
1209 | /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ | ||
1210 | snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST | | ||
1211 | WM8991_BUFDCOPEN | WM8991_POBCTRL | | ||
1212 | WM8991_BUFIOEN); | ||
1213 | |||
1214 | /* mute DAC */ | ||
1215 | val = snd_soc_read(codec, WM8991_DAC_CTRL); | ||
1216 | snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE); | ||
1217 | |||
1218 | /* Enable any disabled outputs */ | ||
1219 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03); | ||
1220 | |||
1221 | /* Disable VMID */ | ||
1222 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f01); | ||
1223 | |||
1224 | msleep(300); | ||
1225 | |||
1226 | /* Enable all output discharge bits */ | ||
1227 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | | ||
1228 | WM8991_DIS_RLINE | WM8991_DIS_OUT3 | | ||
1229 | WM8991_DIS_OUT4 | WM8991_DIS_LOUT | | ||
1230 | WM8991_DIS_ROUT); | ||
1231 | |||
1232 | /* Disable VREF */ | ||
1233 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x0); | ||
1234 | |||
1235 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | ||
1236 | snd_soc_write(codec, WM8991_ANTIPOP2, 0x0); | ||
1237 | codec->cache_sync = 1; | ||
1238 | break; | ||
1239 | } | ||
1240 | |||
1241 | codec->dapm.bias_level = level; | ||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | static int wm8991_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
1246 | { | ||
1247 | wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1248 | return 0; | ||
1249 | } | ||
1250 | |||
1251 | static int wm8991_resume(struct snd_soc_codec *codec) | ||
1252 | { | ||
1253 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1257 | /* power down chip */ | ||
1258 | static int wm8991_remove(struct snd_soc_codec *codec) | ||
1259 | { | ||
1260 | wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1261 | return 0; | ||
1262 | } | ||
1263 | |||
1264 | static int wm8991_probe(struct snd_soc_codec *codec) | ||
1265 | { | ||
1266 | struct wm8991_priv *wm8991; | ||
1267 | int ret; | ||
1268 | unsigned int reg; | ||
1269 | |||
1270 | wm8991 = snd_soc_codec_get_drvdata(codec); | ||
1271 | |||
1272 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type); | ||
1273 | if (ret < 0) { | ||
1274 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | ||
1275 | return ret; | ||
1276 | } | ||
1277 | |||
1278 | ret = wm8991_reset(codec); | ||
1279 | if (ret < 0) { | ||
1280 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
1281 | return ret; | ||
1282 | } | ||
1283 | |||
1284 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1285 | |||
1286 | reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4); | ||
1287 | snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1); | ||
1288 | |||
1289 | reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) & | ||
1290 | ~WM8991_GPIO1_SEL_MASK; | ||
1291 | snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1); | ||
1292 | |||
1293 | reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1); | ||
1294 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA| | ||
1295 | WM8991_VMID_MODE_MASK); | ||
1296 | |||
1297 | reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2); | ||
1298 | snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA); | ||
1299 | |||
1300 | snd_soc_write(codec, WM8991_DAC_CTRL, 0); | ||
1301 | snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1302 | snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1303 | |||
1304 | snd_soc_add_controls(codec, wm8991_snd_controls, | ||
1305 | ARRAY_SIZE(wm8991_snd_controls)); | ||
1306 | |||
1307 | snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets, | ||
1308 | ARRAY_SIZE(wm8991_dapm_widgets)); | ||
1309 | snd_soc_dapm_add_routes(&codec->dapm, audio_map, | ||
1310 | ARRAY_SIZE(audio_map)); | ||
1311 | return 0; | ||
1312 | } | ||
1313 | |||
1314 | #define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1315 | SNDRV_PCM_FMTBIT_S24_LE) | ||
1316 | |||
1317 | static struct snd_soc_dai_ops wm8991_ops = { | ||
1318 | .hw_params = wm8991_hw_params, | ||
1319 | .digital_mute = wm8991_mute, | ||
1320 | .set_fmt = wm8991_set_dai_fmt, | ||
1321 | .set_clkdiv = wm8991_set_dai_clkdiv, | ||
1322 | .set_pll = wm8991_set_dai_pll | ||
1323 | }; | ||
1324 | |||
1325 | /* | ||
1326 | * The WM8991 supports 2 different and mutually exclusive DAI | ||
1327 | * configurations. | ||
1328 | * | ||
1329 | * 1. ADC/DAC on Primary Interface | ||
1330 | * 2. ADC on Primary Interface/DAC on secondary | ||
1331 | */ | ||
1332 | static struct snd_soc_dai_driver wm8991_dai = { | ||
1333 | /* ADC/DAC on primary */ | ||
1334 | .name = "wm8991", | ||
1335 | .id = 1, | ||
1336 | .playback = { | ||
1337 | .stream_name = "Playback", | ||
1338 | .channels_min = 1, | ||
1339 | .channels_max = 2, | ||
1340 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
1341 | .formats = WM8991_FORMATS | ||
1342 | }, | ||
1343 | .capture = { | ||
1344 | .stream_name = "Capture", | ||
1345 | .channels_min = 1, | ||
1346 | .channels_max = 2, | ||
1347 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
1348 | .formats = WM8991_FORMATS | ||
1349 | }, | ||
1350 | .ops = &wm8991_ops | ||
1351 | }; | ||
1352 | |||
1353 | static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { | ||
1354 | .probe = wm8991_probe, | ||
1355 | .remove = wm8991_remove, | ||
1356 | .suspend = wm8991_suspend, | ||
1357 | .resume = wm8991_resume, | ||
1358 | .set_bias_level = wm8991_set_bias_level, | ||
1359 | .reg_cache_size = WM8991_MAX_REGISTER + 1, | ||
1360 | .reg_word_size = sizeof(u16), | ||
1361 | .reg_cache_default = wm8991_reg_defs | ||
1362 | }; | ||
1363 | |||
1364 | static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, | ||
1365 | const struct i2c_device_id *id) | ||
1366 | { | ||
1367 | struct wm8991_priv *wm8991; | ||
1368 | int ret; | ||
1369 | |||
1370 | wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL); | ||
1371 | if (!wm8991) | ||
1372 | return -ENOMEM; | ||
1373 | |||
1374 | wm8991->control_type = SND_SOC_I2C; | ||
1375 | i2c_set_clientdata(i2c, wm8991); | ||
1376 | |||
1377 | ret = snd_soc_register_codec(&i2c->dev, | ||
1378 | &soc_codec_dev_wm8991, &wm8991_dai, 1); | ||
1379 | if (ret < 0) | ||
1380 | kfree(wm8991); | ||
1381 | return ret; | ||
1382 | } | ||
1383 | |||
1384 | static __devexit int wm8991_i2c_remove(struct i2c_client *client) | ||
1385 | { | ||
1386 | snd_soc_unregister_codec(&client->dev); | ||
1387 | kfree(i2c_get_clientdata(client)); | ||
1388 | return 0; | ||
1389 | } | ||
1390 | |||
1391 | static const struct i2c_device_id wm8991_i2c_id[] = { | ||
1392 | { "wm8991", 0 }, | ||
1393 | { } | ||
1394 | }; | ||
1395 | MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id); | ||
1396 | |||
1397 | static struct i2c_driver wm8991_i2c_driver = { | ||
1398 | .driver = { | ||
1399 | .name = "wm8991", | ||
1400 | .owner = THIS_MODULE, | ||
1401 | }, | ||
1402 | .probe = wm8991_i2c_probe, | ||
1403 | .remove = __devexit_p(wm8991_i2c_remove), | ||
1404 | .id_table = wm8991_i2c_id, | ||
1405 | }; | ||
1406 | |||
1407 | static int __init wm8991_modinit(void) | ||
1408 | { | ||
1409 | int ret; | ||
1410 | ret = i2c_add_driver(&wm8991_i2c_driver); | ||
1411 | if (ret != 0) { | ||
1412 | printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n", | ||
1413 | ret); | ||
1414 | } | ||
1415 | return 0; | ||
1416 | } | ||
1417 | module_init(wm8991_modinit); | ||
1418 | |||
1419 | static void __exit wm8991_exit(void) | ||
1420 | { | ||
1421 | i2c_del_driver(&wm8991_i2c_driver); | ||
1422 | } | ||
1423 | module_exit(wm8991_exit); | ||
1424 | |||
1425 | MODULE_DESCRIPTION("ASoC WM8991 driver"); | ||
1426 | MODULE_AUTHOR("Graeme Gregory"); | ||
1427 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8991.h b/sound/soc/codecs/wm8991.h new file mode 100644 index 000000000000..8a942efd18a5 --- /dev/null +++ b/sound/soc/codecs/wm8991.h | |||
@@ -0,0 +1,833 @@ | |||
1 | /* | ||
2 | * wm8991.h -- audio driver for WM8991 | ||
3 | * | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef _WM8991_H | ||
15 | #define _WM8991_H | ||
16 | |||
17 | /* | ||
18 | * Register values. | ||
19 | */ | ||
20 | #define WM8991_RESET 0x00 | ||
21 | #define WM8991_POWER_MANAGEMENT_1 0x01 | ||
22 | #define WM8991_POWER_MANAGEMENT_2 0x02 | ||
23 | #define WM8991_POWER_MANAGEMENT_3 0x03 | ||
24 | #define WM8991_AUDIO_INTERFACE_1 0x04 | ||
25 | #define WM8991_AUDIO_INTERFACE_2 0x05 | ||
26 | #define WM8991_CLOCKING_1 0x06 | ||
27 | #define WM8991_CLOCKING_2 0x07 | ||
28 | #define WM8991_AUDIO_INTERFACE_3 0x08 | ||
29 | #define WM8991_AUDIO_INTERFACE_4 0x09 | ||
30 | #define WM8991_DAC_CTRL 0x0A | ||
31 | #define WM8991_LEFT_DAC_DIGITAL_VOLUME 0x0B | ||
32 | #define WM8991_RIGHT_DAC_DIGITAL_VOLUME 0x0C | ||
33 | #define WM8991_DIGITAL_SIDE_TONE 0x0D | ||
34 | #define WM8991_ADC_CTRL 0x0E | ||
35 | #define WM8991_LEFT_ADC_DIGITAL_VOLUME 0x0F | ||
36 | #define WM8991_RIGHT_ADC_DIGITAL_VOLUME 0x10 | ||
37 | #define WM8991_GPIO_CTRL_1 0x12 | ||
38 | #define WM8991_GPIO1_GPIO2 0x13 | ||
39 | #define WM8991_GPIO3_GPIO4 0x14 | ||
40 | #define WM8991_GPIO5_GPIO6 0x15 | ||
41 | #define WM8991_GPIOCTRL_2 0x16 | ||
42 | #define WM8991_GPIO_POL 0x17 | ||
43 | #define WM8991_LEFT_LINE_INPUT_1_2_VOLUME 0x18 | ||
44 | #define WM8991_LEFT_LINE_INPUT_3_4_VOLUME 0x19 | ||
45 | #define WM8991_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A | ||
46 | #define WM8991_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B | ||
47 | #define WM8991_LEFT_OUTPUT_VOLUME 0x1C | ||
48 | #define WM8991_RIGHT_OUTPUT_VOLUME 0x1D | ||
49 | #define WM8991_LINE_OUTPUTS_VOLUME 0x1E | ||
50 | #define WM8991_OUT3_4_VOLUME 0x1F | ||
51 | #define WM8991_LEFT_OPGA_VOLUME 0x20 | ||
52 | #define WM8991_RIGHT_OPGA_VOLUME 0x21 | ||
53 | #define WM8991_SPEAKER_VOLUME 0x22 | ||
54 | #define WM8991_CLASSD1 0x23 | ||
55 | #define WM8991_CLASSD3 0x25 | ||
56 | #define WM8991_INPUT_MIXER1 0x27 | ||
57 | #define WM8991_INPUT_MIXER2 0x28 | ||
58 | #define WM8991_INPUT_MIXER3 0x29 | ||
59 | #define WM8991_INPUT_MIXER4 0x2A | ||
60 | #define WM8991_INPUT_MIXER5 0x2B | ||
61 | #define WM8991_INPUT_MIXER6 0x2C | ||
62 | #define WM8991_OUTPUT_MIXER1 0x2D | ||
63 | #define WM8991_OUTPUT_MIXER2 0x2E | ||
64 | #define WM8991_OUTPUT_MIXER3 0x2F | ||
65 | #define WM8991_OUTPUT_MIXER4 0x30 | ||
66 | #define WM8991_OUTPUT_MIXER5 0x31 | ||
67 | #define WM8991_OUTPUT_MIXER6 0x32 | ||
68 | #define WM8991_OUT3_4_MIXER 0x33 | ||
69 | #define WM8991_LINE_MIXER1 0x34 | ||
70 | #define WM8991_LINE_MIXER2 0x35 | ||
71 | #define WM8991_SPEAKER_MIXER 0x36 | ||
72 | #define WM8991_ADDITIONAL_CONTROL 0x37 | ||
73 | #define WM8991_ANTIPOP1 0x38 | ||
74 | #define WM8991_ANTIPOP2 0x39 | ||
75 | #define WM8991_MICBIAS 0x3A | ||
76 | #define WM8991_PLL1 0x3C | ||
77 | #define WM8991_PLL2 0x3D | ||
78 | #define WM8991_PLL3 0x3E | ||
79 | #define WM8991_INTDRIVBITS 0x3F | ||
80 | |||
81 | #define WM8991_REGISTER_COUNT 60 | ||
82 | #define WM8991_MAX_REGISTER 0x3F | ||
83 | |||
84 | /* | ||
85 | * Field Definitions. | ||
86 | */ | ||
87 | |||
88 | /* | ||
89 | * R0 (0x00) - Reset | ||
90 | */ | ||
91 | #define WM8991_SW_RESET_CHIP_ID_MASK 0xFFFF /* SW_RESET_CHIP_ID - [15:0] */ | ||
92 | |||
93 | /* | ||
94 | * R1 (0x01) - Power Management (1) | ||
95 | */ | ||
96 | #define WM8991_SPK_ENA 0x1000 /* SPK_ENA */ | ||
97 | #define WM8991_SPK_ENA_BIT 12 | ||
98 | #define WM8991_OUT3_ENA 0x0800 /* OUT3_ENA */ | ||
99 | #define WM8991_OUT3_ENA_BIT 11 | ||
100 | #define WM8991_OUT4_ENA 0x0400 /* OUT4_ENA */ | ||
101 | #define WM8991_OUT4_ENA_BIT 10 | ||
102 | #define WM8991_LOUT_ENA 0x0200 /* LOUT_ENA */ | ||
103 | #define WM8991_LOUT_ENA_BIT 9 | ||
104 | #define WM8991_ROUT_ENA 0x0100 /* ROUT_ENA */ | ||
105 | #define WM8991_ROUT_ENA_BIT 8 | ||
106 | #define WM8991_MICBIAS_ENA 0x0010 /* MICBIAS_ENA */ | ||
107 | #define WM8991_MICBIAS_ENA_BIT 4 | ||
108 | #define WM8991_VMID_MODE_MASK 0x0006 /* VMID_MODE - [2:1] */ | ||
109 | #define WM8991_VREF_ENA 0x0001 /* VREF_ENA */ | ||
110 | #define WM8991_VREF_ENA_BIT 0 | ||
111 | |||
112 | /* | ||
113 | * R2 (0x02) - Power Management (2) | ||
114 | */ | ||
115 | #define WM8991_PLL_ENA 0x8000 /* PLL_ENA */ | ||
116 | #define WM8991_PLL_ENA_BIT 15 | ||
117 | #define WM8991_TSHUT_ENA 0x4000 /* TSHUT_ENA */ | ||
118 | #define WM8991_TSHUT_ENA_BIT 14 | ||
119 | #define WM8991_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */ | ||
120 | #define WM8991_TSHUT_OPDIS_BIT 13 | ||
121 | #define WM8991_OPCLK_ENA 0x0800 /* OPCLK_ENA */ | ||
122 | #define WM8991_OPCLK_ENA_BIT 11 | ||
123 | #define WM8991_AINL_ENA 0x0200 /* AINL_ENA */ | ||
124 | #define WM8991_AINL_ENA_BIT 9 | ||
125 | #define WM8991_AINR_ENA 0x0100 /* AINR_ENA */ | ||
126 | #define WM8991_AINR_ENA_BIT 8 | ||
127 | #define WM8991_LIN34_ENA 0x0080 /* LIN34_ENA */ | ||
128 | #define WM8991_LIN34_ENA_BIT 7 | ||
129 | #define WM8991_LIN12_ENA 0x0040 /* LIN12_ENA */ | ||
130 | #define WM8991_LIN12_ENA_BIT 6 | ||
131 | #define WM8991_RIN34_ENA 0x0020 /* RIN34_ENA */ | ||
132 | #define WM8991_RIN34_ENA_BIT 5 | ||
133 | #define WM8991_RIN12_ENA 0x0010 /* RIN12_ENA */ | ||
134 | #define WM8991_RIN12_ENA_BIT 4 | ||
135 | #define WM8991_ADCL_ENA 0x0002 /* ADCL_ENA */ | ||
136 | #define WM8991_ADCL_ENA_BIT 1 | ||
137 | #define WM8991_ADCR_ENA 0x0001 /* ADCR_ENA */ | ||
138 | #define WM8991_ADCR_ENA_BIT 0 | ||
139 | |||
140 | /* | ||
141 | * R3 (0x03) - Power Management (3) | ||
142 | */ | ||
143 | #define WM8991_LON_ENA 0x2000 /* LON_ENA */ | ||
144 | #define WM8991_LON_ENA_BIT 13 | ||
145 | #define WM8991_LOP_ENA 0x1000 /* LOP_ENA */ | ||
146 | #define WM8991_LOP_ENA_BIT 12 | ||
147 | #define WM8991_RON_ENA 0x0800 /* RON_ENA */ | ||
148 | #define WM8991_RON_ENA_BIT 11 | ||
149 | #define WM8991_ROP_ENA 0x0400 /* ROP_ENA */ | ||
150 | #define WM8991_ROP_ENA_BIT 10 | ||
151 | #define WM8991_LOPGA_ENA 0x0080 /* LOPGA_ENA */ | ||
152 | #define WM8991_LOPGA_ENA_BIT 7 | ||
153 | #define WM8991_ROPGA_ENA 0x0040 /* ROPGA_ENA */ | ||
154 | #define WM8991_ROPGA_ENA_BIT 6 | ||
155 | #define WM8991_LOMIX_ENA 0x0020 /* LOMIX_ENA */ | ||
156 | #define WM8991_LOMIX_ENA_BIT 5 | ||
157 | #define WM8991_ROMIX_ENA 0x0010 /* ROMIX_ENA */ | ||
158 | #define WM8991_ROMIX_ENA_BIT 4 | ||
159 | #define WM8991_DACL_ENA 0x0002 /* DACL_ENA */ | ||
160 | #define WM8991_DACL_ENA_BIT 1 | ||
161 | #define WM8991_DACR_ENA 0x0001 /* DACR_ENA */ | ||
162 | #define WM8991_DACR_ENA_BIT 0 | ||
163 | |||
164 | /* | ||
165 | * R4 (0x04) - Audio Interface (1) | ||
166 | */ | ||
167 | #define WM8991_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */ | ||
168 | #define WM8991_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */ | ||
169 | #define WM8991_AIFADC_TDM 0x2000 /* AIFADC_TDM */ | ||
170 | #define WM8991_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */ | ||
171 | #define WM8991_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */ | ||
172 | #define WM8991_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */ | ||
173 | #define WM8991_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */ | ||
174 | #define WM8991_AIF_WL_16BITS (0 << 5) | ||
175 | #define WM8991_AIF_WL_20BITS (1 << 5) | ||
176 | #define WM8991_AIF_WL_24BITS (2 << 5) | ||
177 | #define WM8991_AIF_WL_32BITS (3 << 5) | ||
178 | #define WM8991_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */ | ||
179 | #define WM8991_AIF_TMF_RIGHTJ (0 << 3) | ||
180 | #define WM8991_AIF_TMF_LEFTJ (1 << 3) | ||
181 | #define WM8991_AIF_TMF_I2S (2 << 3) | ||
182 | #define WM8991_AIF_TMF_DSP (3 << 3) | ||
183 | |||
184 | /* | ||
185 | * R5 (0x05) - Audio Interface (2) | ||
186 | */ | ||
187 | #define WM8991_DACL_SRC 0x8000 /* DACL_SRC */ | ||
188 | #define WM8991_DACR_SRC 0x4000 /* DACR_SRC */ | ||
189 | #define WM8991_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ | ||
190 | #define WM8991_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ | ||
191 | #define WM8991_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */ | ||
192 | #define WM8991_DAC_COMP 0x0010 /* DAC_COMP */ | ||
193 | #define WM8991_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ | ||
194 | #define WM8991_ADC_COMP 0x0004 /* ADC_COMP */ | ||
195 | #define WM8991_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ | ||
196 | #define WM8991_LOOPBACK 0x0001 /* LOOPBACK */ | ||
197 | |||
198 | /* | ||
199 | * R6 (0x06) - Clocking (1) | ||
200 | */ | ||
201 | #define WM8991_TOCLK_RATE 0x8000 /* TOCLK_RATE */ | ||
202 | #define WM8991_TOCLK_ENA 0x4000 /* TOCLK_ENA */ | ||
203 | #define WM8991_OPCLKDIV_MASK 0x1E00 /* OPCLKDIV - [12:9] */ | ||
204 | #define WM8991_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */ | ||
205 | #define WM8991_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */ | ||
206 | #define WM8991_BCLK_DIV_1 (0x0 << 1) | ||
207 | #define WM8991_BCLK_DIV_1_5 (0x1 << 1) | ||
208 | #define WM8991_BCLK_DIV_2 (0x2 << 1) | ||
209 | #define WM8991_BCLK_DIV_3 (0x3 << 1) | ||
210 | #define WM8991_BCLK_DIV_4 (0x4 << 1) | ||
211 | #define WM8991_BCLK_DIV_5_5 (0x5 << 1) | ||
212 | #define WM8991_BCLK_DIV_6 (0x6 << 1) | ||
213 | #define WM8991_BCLK_DIV_8 (0x7 << 1) | ||
214 | #define WM8991_BCLK_DIV_11 (0x8 << 1) | ||
215 | #define WM8991_BCLK_DIV_12 (0x9 << 1) | ||
216 | #define WM8991_BCLK_DIV_16 (0xA << 1) | ||
217 | #define WM8991_BCLK_DIV_22 (0xB << 1) | ||
218 | #define WM8991_BCLK_DIV_24 (0xC << 1) | ||
219 | #define WM8991_BCLK_DIV_32 (0xD << 1) | ||
220 | #define WM8991_BCLK_DIV_44 (0xE << 1) | ||
221 | #define WM8991_BCLK_DIV_48 (0xF << 1) | ||
222 | |||
223 | /* | ||
224 | * R7 (0x07) - Clocking (2) | ||
225 | */ | ||
226 | #define WM8991_MCLK_SRC 0x8000 /* MCLK_SRC */ | ||
227 | #define WM8991_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ | ||
228 | #define WM8991_CLK_FORCE 0x2000 /* CLK_FORCE */ | ||
229 | #define WM8991_MCLK_DIV_MASK 0x1800 /* MCLK_DIV - [12:11] */ | ||
230 | #define WM8991_MCLK_DIV_1 (0 << 11) | ||
231 | #define WM8991_MCLK_DIV_2 ( 2 << 11) | ||
232 | #define WM8991_MCLK_INV 0x0400 /* MCLK_INV */ | ||
233 | #define WM8991_ADC_CLKDIV_MASK 0x00E0 /* ADC_CLKDIV - [7:5] */ | ||
234 | #define WM8991_ADC_CLKDIV_1 (0 << 5) | ||
235 | #define WM8991_ADC_CLKDIV_1_5 (1 << 5) | ||
236 | #define WM8991_ADC_CLKDIV_2 (2 << 5) | ||
237 | #define WM8991_ADC_CLKDIV_3 (3 << 5) | ||
238 | #define WM8991_ADC_CLKDIV_4 (4 << 5) | ||
239 | #define WM8991_ADC_CLKDIV_5_5 (5 << 5) | ||
240 | #define WM8991_ADC_CLKDIV_6 (6 << 5) | ||
241 | #define WM8991_DAC_CLKDIV_MASK 0x001C /* DAC_CLKDIV - [4:2] */ | ||
242 | #define WM8991_DAC_CLKDIV_1 (0 << 2) | ||
243 | #define WM8991_DAC_CLKDIV_1_5 (1 << 2) | ||
244 | #define WM8991_DAC_CLKDIV_2 (2 << 2) | ||
245 | #define WM8991_DAC_CLKDIV_3 (3 << 2) | ||
246 | #define WM8991_DAC_CLKDIV_4 (4 << 2) | ||
247 | #define WM8991_DAC_CLKDIV_5_5 (5 << 2) | ||
248 | #define WM8991_DAC_CLKDIV_6 (6 << 2) | ||
249 | |||
250 | /* | ||
251 | * R8 (0x08) - Audio Interface (3) | ||
252 | */ | ||
253 | #define WM8991_AIF_MSTR1 0x8000 /* AIF_MSTR1 */ | ||
254 | #define WM8991_AIF_MSTR2 0x4000 /* AIF_MSTR2 */ | ||
255 | #define WM8991_AIF_SEL 0x2000 /* AIF_SEL */ | ||
256 | #define WM8991_ADCLRC_DIR 0x0800 /* ADCLRC_DIR */ | ||
257 | #define WM8991_ADCLRC_RATE_MASK 0x07FF /* ADCLRC_RATE - [10:0] */ | ||
258 | |||
259 | /* | ||
260 | * R9 (0x09) - Audio Interface (4) | ||
261 | */ | ||
262 | #define WM8991_ALRCGPIO1 0x8000 /* ALRCGPIO1 */ | ||
263 | #define WM8991_ALRCBGPIO6 0x4000 /* ALRCBGPIO6 */ | ||
264 | #define WM8991_AIF_TRIS 0x2000 /* AIF_TRIS */ | ||
265 | #define WM8991_DACLRC_DIR 0x0800 /* DACLRC_DIR */ | ||
266 | #define WM8991_DACLRC_RATE_MASK 0x07FF /* DACLRC_RATE - [10:0] */ | ||
267 | |||
268 | /* | ||
269 | * R10 (0x0A) - DAC CTRL | ||
270 | */ | ||
271 | #define WM8991_AIF_LRCLKRATE 0x0400 /* AIF_LRCLKRATE */ | ||
272 | #define WM8991_DAC_MONO 0x0200 /* DAC_MONO */ | ||
273 | #define WM8991_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */ | ||
274 | #define WM8991_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */ | ||
275 | #define WM8991_DAC_MUTEMODE 0x0040 /* DAC_MUTEMODE */ | ||
276 | #define WM8991_DEEMP_MASK 0x0030 /* DEEMP - [5:4] */ | ||
277 | #define WM8991_DAC_MUTE 0x0004 /* DAC_MUTE */ | ||
278 | #define WM8991_DACL_DATINV 0x0002 /* DACL_DATINV */ | ||
279 | #define WM8991_DACR_DATINV 0x0001 /* DACR_DATINV */ | ||
280 | |||
281 | /* | ||
282 | * R11 (0x0B) - Left DAC Digital Volume | ||
283 | */ | ||
284 | #define WM8991_DAC_VU 0x0100 /* DAC_VU */ | ||
285 | #define WM8991_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ | ||
286 | #define WM8991_DACL_VOL_SHIFT 0 | ||
287 | /* | ||
288 | * R12 (0x0C) - Right DAC Digital Volume | ||
289 | */ | ||
290 | #define WM8991_DAC_VU 0x0100 /* DAC_VU */ | ||
291 | #define WM8991_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ | ||
292 | #define WM8991_DACR_VOL_SHIFT 0 | ||
293 | /* | ||
294 | * R13 (0x0D) - Digital Side Tone | ||
295 | */ | ||
296 | #define WM8991_ADCL_DAC_SVOL_MASK 0x0F /* ADCL_DAC_SVOL - [12:9] */ | ||
297 | #define WM8991_ADCL_DAC_SVOL_SHIFT 9 | ||
298 | #define WM8991_ADCR_DAC_SVOL_MASK 0x0F /* ADCR_DAC_SVOL - [8:5] */ | ||
299 | #define WM8991_ADCR_DAC_SVOL_SHIFT 5 | ||
300 | #define WM8991_ADC_TO_DACL_MASK 0x03 /* ADC_TO_DACL - [3:2] */ | ||
301 | #define WM8991_ADC_TO_DACL_SHIFT 2 | ||
302 | #define WM8991_ADC_TO_DACR_MASK 0x03 /* ADC_TO_DACR - [1:0] */ | ||
303 | #define WM8991_ADC_TO_DACR_SHIFT 0 | ||
304 | |||
305 | /* | ||
306 | * R14 (0x0E) - ADC CTRL | ||
307 | */ | ||
308 | #define WM8991_ADC_HPF_ENA 0x0100 /* ADC_HPF_ENA */ | ||
309 | #define WM8991_ADC_HPF_ENA_BIT 8 | ||
310 | #define WM8991_ADC_HPF_CUT_MASK 0x03 /* ADC_HPF_CUT - [6:5] */ | ||
311 | #define WM8991_ADC_HPF_CUT_SHIFT 5 | ||
312 | #define WM8991_ADCL_DATINV 0x0002 /* ADCL_DATINV */ | ||
313 | #define WM8991_ADCL_DATINV_BIT 1 | ||
314 | #define WM8991_ADCR_DATINV 0x0001 /* ADCR_DATINV */ | ||
315 | #define WM8991_ADCR_DATINV_BIT 0 | ||
316 | |||
317 | /* | ||
318 | * R15 (0x0F) - Left ADC Digital Volume | ||
319 | */ | ||
320 | #define WM8991_ADC_VU 0x0100 /* ADC_VU */ | ||
321 | #define WM8991_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ | ||
322 | #define WM8991_ADCL_VOL_SHIFT 0 | ||
323 | |||
324 | /* | ||
325 | * R16 (0x10) - Right ADC Digital Volume | ||
326 | */ | ||
327 | #define WM8991_ADC_VU 0x0100 /* ADC_VU */ | ||
328 | #define WM8991_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ | ||
329 | #define WM8991_ADCR_VOL_SHIFT 0 | ||
330 | |||
331 | /* | ||
332 | * R18 (0x12) - GPIO CTRL 1 | ||
333 | */ | ||
334 | #define WM8991_IRQ 0x1000 /* IRQ */ | ||
335 | #define WM8991_TEMPOK 0x0800 /* TEMPOK */ | ||
336 | #define WM8991_MICSHRT 0x0400 /* MICSHRT */ | ||
337 | #define WM8991_MICDET 0x0200 /* MICDET */ | ||
338 | #define WM8991_PLL_LCK 0x0100 /* PLL_LCK */ | ||
339 | #define WM8991_GPI8_STATUS 0x0080 /* GPI8_STATUS */ | ||
340 | #define WM8991_GPI7_STATUS 0x0040 /* GPI7_STATUS */ | ||
341 | #define WM8991_GPIO6_STATUS 0x0020 /* GPIO6_STATUS */ | ||
342 | #define WM8991_GPIO5_STATUS 0x0010 /* GPIO5_STATUS */ | ||
343 | #define WM8991_GPIO4_STATUS 0x0008 /* GPIO4_STATUS */ | ||
344 | #define WM8991_GPIO3_STATUS 0x0004 /* GPIO3_STATUS */ | ||
345 | #define WM8991_GPIO2_STATUS 0x0002 /* GPIO2_STATUS */ | ||
346 | #define WM8991_GPIO1_STATUS 0x0001 /* GPIO1_STATUS */ | ||
347 | |||
348 | /* | ||
349 | * R19 (0x13) - GPIO1 & GPIO2 | ||
350 | */ | ||
351 | #define WM8991_GPIO2_DEB_ENA 0x8000 /* GPIO2_DEB_ENA */ | ||
352 | #define WM8991_GPIO2_IRQ_ENA 0x4000 /* GPIO2_IRQ_ENA */ | ||
353 | #define WM8991_GPIO2_PU 0x2000 /* GPIO2_PU */ | ||
354 | #define WM8991_GPIO2_PD 0x1000 /* GPIO2_PD */ | ||
355 | #define WM8991_GPIO2_SEL_MASK 0x0F00 /* GPIO2_SEL - [11:8] */ | ||
356 | #define WM8991_GPIO1_DEB_ENA 0x0080 /* GPIO1_DEB_ENA */ | ||
357 | #define WM8991_GPIO1_IRQ_ENA 0x0040 /* GPIO1_IRQ_ENA */ | ||
358 | #define WM8991_GPIO1_PU 0x0020 /* GPIO1_PU */ | ||
359 | #define WM8991_GPIO1_PD 0x0010 /* GPIO1_PD */ | ||
360 | #define WM8991_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */ | ||
361 | |||
362 | /* | ||
363 | * R20 (0x14) - GPIO3 & GPIO4 | ||
364 | */ | ||
365 | #define WM8991_GPIO4_DEB_ENA 0x8000 /* GPIO4_DEB_ENA */ | ||
366 | #define WM8991_GPIO4_IRQ_ENA 0x4000 /* GPIO4_IRQ_ENA */ | ||
367 | #define WM8991_GPIO4_PU 0x2000 /* GPIO4_PU */ | ||
368 | #define WM8991_GPIO4_PD 0x1000 /* GPIO4_PD */ | ||
369 | #define WM8991_GPIO4_SEL_MASK 0x0F00 /* GPIO4_SEL - [11:8] */ | ||
370 | #define WM8991_GPIO3_DEB_ENA 0x0080 /* GPIO3_DEB_ENA */ | ||
371 | #define WM8991_GPIO3_IRQ_ENA 0x0040 /* GPIO3_IRQ_ENA */ | ||
372 | #define WM8991_GPIO3_PU 0x0020 /* GPIO3_PU */ | ||
373 | #define WM8991_GPIO3_PD 0x0010 /* GPIO3_PD */ | ||
374 | #define WM8991_GPIO3_SEL_MASK 0x000F /* GPIO3_SEL - [3:0] */ | ||
375 | |||
376 | /* | ||
377 | * R21 (0x15) - GPIO5 & GPIO6 | ||
378 | */ | ||
379 | #define WM8991_GPIO6_DEB_ENA 0x8000 /* GPIO6_DEB_ENA */ | ||
380 | #define WM8991_GPIO6_IRQ_ENA 0x4000 /* GPIO6_IRQ_ENA */ | ||
381 | #define WM8991_GPIO6_PU 0x2000 /* GPIO6_PU */ | ||
382 | #define WM8991_GPIO6_PD 0x1000 /* GPIO6_PD */ | ||
383 | #define WM8991_GPIO6_SEL_MASK 0x0F00 /* GPIO6_SEL - [11:8] */ | ||
384 | #define WM8991_GPIO5_DEB_ENA 0x0080 /* GPIO5_DEB_ENA */ | ||
385 | #define WM8991_GPIO5_IRQ_ENA 0x0040 /* GPIO5_IRQ_ENA */ | ||
386 | #define WM8991_GPIO5_PU 0x0020 /* GPIO5_PU */ | ||
387 | #define WM8991_GPIO5_PD 0x0010 /* GPIO5_PD */ | ||
388 | #define WM8991_GPIO5_SEL_MASK 0x000F /* GPIO5_SEL - [3:0] */ | ||
389 | |||
390 | /* | ||
391 | * R22 (0x16) - GPIOCTRL 2 | ||
392 | */ | ||
393 | #define WM8991_RD_3W_ENA 0x8000 /* RD_3W_ENA */ | ||
394 | #define WM8991_MODE_3W4W 0x4000 /* MODE_3W4W */ | ||
395 | #define WM8991_TEMPOK_IRQ_ENA 0x0800 /* TEMPOK_IRQ_ENA */ | ||
396 | #define WM8991_MICSHRT_IRQ_ENA 0x0400 /* MICSHRT_IRQ_ENA */ | ||
397 | #define WM8991_MICDET_IRQ_ENA 0x0200 /* MICDET_IRQ_ENA */ | ||
398 | #define WM8991_PLL_LCK_IRQ_ENA 0x0100 /* PLL_LCK_IRQ_ENA */ | ||
399 | #define WM8991_GPI8_DEB_ENA 0x0080 /* GPI8_DEB_ENA */ | ||
400 | #define WM8991_GPI8_IRQ_ENA 0x0040 /* GPI8_IRQ_ENA */ | ||
401 | #define WM8991_GPI8_ENA 0x0010 /* GPI8_ENA */ | ||
402 | #define WM8991_GPI7_DEB_ENA 0x0008 /* GPI7_DEB_ENA */ | ||
403 | #define WM8991_GPI7_IRQ_ENA 0x0004 /* GPI7_IRQ_ENA */ | ||
404 | #define WM8991_GPI7_ENA 0x0001 /* GPI7_ENA */ | ||
405 | |||
406 | /* | ||
407 | * R23 (0x17) - GPIO_POL | ||
408 | */ | ||
409 | #define WM8991_IRQ_INV 0x1000 /* IRQ_INV */ | ||
410 | #define WM8991_TEMPOK_POL 0x0800 /* TEMPOK_POL */ | ||
411 | #define WM8991_MICSHRT_POL 0x0400 /* MICSHRT_POL */ | ||
412 | #define WM8991_MICDET_POL 0x0200 /* MICDET_POL */ | ||
413 | #define WM8991_PLL_LCK_POL 0x0100 /* PLL_LCK_POL */ | ||
414 | #define WM8991_GPI8_POL 0x0080 /* GPI8_POL */ | ||
415 | #define WM8991_GPI7_POL 0x0040 /* GPI7_POL */ | ||
416 | #define WM8991_GPIO6_POL 0x0020 /* GPIO6_POL */ | ||
417 | #define WM8991_GPIO5_POL 0x0010 /* GPIO5_POL */ | ||
418 | #define WM8991_GPIO4_POL 0x0008 /* GPIO4_POL */ | ||
419 | #define WM8991_GPIO3_POL 0x0004 /* GPIO3_POL */ | ||
420 | #define WM8991_GPIO2_POL 0x0002 /* GPIO2_POL */ | ||
421 | #define WM8991_GPIO1_POL 0x0001 /* GPIO1_POL */ | ||
422 | |||
423 | /* | ||
424 | * R24 (0x18) - Left Line Input 1&2 Volume | ||
425 | */ | ||
426 | #define WM8991_IPVU 0x0100 /* IPVU */ | ||
427 | #define WM8991_LI12MUTE 0x0080 /* LI12MUTE */ | ||
428 | #define WM8991_LI12MUTE_BIT 7 | ||
429 | #define WM8991_LI12ZC 0x0040 /* LI12ZC */ | ||
430 | #define WM8991_LI12ZC_BIT 6 | ||
431 | #define WM8991_LIN12VOL_MASK 0x001F /* LIN12VOL - [4:0] */ | ||
432 | #define WM8991_LIN12VOL_SHIFT 0 | ||
433 | /* | ||
434 | * R25 (0x19) - Left Line Input 3&4 Volume | ||
435 | */ | ||
436 | #define WM8991_IPVU 0x0100 /* IPVU */ | ||
437 | #define WM8991_LI34MUTE 0x0080 /* LI34MUTE */ | ||
438 | #define WM8991_LI34MUTE_BIT 7 | ||
439 | #define WM8991_LI34ZC 0x0040 /* LI34ZC */ | ||
440 | #define WM8991_LI34ZC_BIT 6 | ||
441 | #define WM8991_LIN34VOL_MASK 0x001F /* LIN34VOL - [4:0] */ | ||
442 | #define WM8991_LIN34VOL_SHIFT 0 | ||
443 | |||
444 | /* | ||
445 | * R26 (0x1A) - Right Line Input 1&2 Volume | ||
446 | */ | ||
447 | #define WM8991_IPVU 0x0100 /* IPVU */ | ||
448 | #define WM8991_RI12MUTE 0x0080 /* RI12MUTE */ | ||
449 | #define WM8991_RI12MUTE_BIT 7 | ||
450 | #define WM8991_RI12ZC 0x0040 /* RI12ZC */ | ||
451 | #define WM8991_RI12ZC_BIT 6 | ||
452 | #define WM8991_RIN12VOL_MASK 0x001F /* RIN12VOL - [4:0] */ | ||
453 | #define WM8991_RIN12VOL_SHIFT 0 | ||
454 | |||
455 | /* | ||
456 | * R27 (0x1B) - Right Line Input 3&4 Volume | ||
457 | */ | ||
458 | #define WM8991_IPVU 0x0100 /* IPVU */ | ||
459 | #define WM8991_RI34MUTE 0x0080 /* RI34MUTE */ | ||
460 | #define WM8991_RI34MUTE_BIT 7 | ||
461 | #define WM8991_RI34ZC 0x0040 /* RI34ZC */ | ||
462 | #define WM8991_RI34ZC_BIT 6 | ||
463 | #define WM8991_RIN34VOL_MASK 0x001F /* RIN34VOL - [4:0] */ | ||
464 | #define WM8991_RIN34VOL_SHIFT 0 | ||
465 | |||
466 | /* | ||
467 | * R28 (0x1C) - Left Output Volume | ||
468 | */ | ||
469 | #define WM8991_OPVU 0x0100 /* OPVU */ | ||
470 | #define WM8991_LOZC 0x0080 /* LOZC */ | ||
471 | #define WM8991_LOZC_BIT 7 | ||
472 | #define WM8991_LOUTVOL_MASK 0x007F /* LOUTVOL - [6:0] */ | ||
473 | #define WM8991_LOUTVOL_SHIFT 0 | ||
474 | /* | ||
475 | * R29 (0x1D) - Right Output Volume | ||
476 | */ | ||
477 | #define WM8991_OPVU 0x0100 /* OPVU */ | ||
478 | #define WM8991_ROZC 0x0080 /* ROZC */ | ||
479 | #define WM8991_ROZC_BIT 7 | ||
480 | #define WM8991_ROUTVOL_MASK 0x007F /* ROUTVOL - [6:0] */ | ||
481 | #define WM8991_ROUTVOL_SHIFT 0 | ||
482 | /* | ||
483 | * R30 (0x1E) - Line Outputs Volume | ||
484 | */ | ||
485 | #define WM8991_LONMUTE 0x0040 /* LONMUTE */ | ||
486 | #define WM8991_LONMUTE_BIT 6 | ||
487 | #define WM8991_LOPMUTE 0x0020 /* LOPMUTE */ | ||
488 | #define WM8991_LOPMUTE_BIT 5 | ||
489 | #define WM8991_LOATTN 0x0010 /* LOATTN */ | ||
490 | #define WM8991_LOATTN_BIT 4 | ||
491 | #define WM8991_RONMUTE 0x0004 /* RONMUTE */ | ||
492 | #define WM8991_RONMUTE_BIT 2 | ||
493 | #define WM8991_ROPMUTE 0x0002 /* ROPMUTE */ | ||
494 | #define WM8991_ROPMUTE_BIT 1 | ||
495 | #define WM8991_ROATTN 0x0001 /* ROATTN */ | ||
496 | #define WM8991_ROATTN_BIT 0 | ||
497 | |||
498 | /* | ||
499 | * R31 (0x1F) - Out3/4 Volume | ||
500 | */ | ||
501 | #define WM8991_OUT3MUTE 0x0020 /* OUT3MUTE */ | ||
502 | #define WM8991_OUT3MUTE_BIT 5 | ||
503 | #define WM8991_OUT3ATTN 0x0010 /* OUT3ATTN */ | ||
504 | #define WM8991_OUT3ATTN_BIT 4 | ||
505 | #define WM8991_OUT4MUTE 0x0002 /* OUT4MUTE */ | ||
506 | #define WM8991_OUT4MUTE_BIT 1 | ||
507 | #define WM8991_OUT4ATTN 0x0001 /* OUT4ATTN */ | ||
508 | #define WM8991_OUT4ATTN_BIT 0 | ||
509 | |||
510 | /* | ||
511 | * R32 (0x20) - Left OPGA Volume | ||
512 | */ | ||
513 | #define WM8991_OPVU 0x0100 /* OPVU */ | ||
514 | #define WM8991_LOPGAZC 0x0080 /* LOPGAZC */ | ||
515 | #define WM8991_LOPGAZC_BIT 7 | ||
516 | #define WM8991_LOPGAVOL_MASK 0x007F /* LOPGAVOL - [6:0] */ | ||
517 | #define WM8991_LOPGAVOL_SHIFT 0 | ||
518 | |||
519 | /* | ||
520 | * R33 (0x21) - Right OPGA Volume | ||
521 | */ | ||
522 | #define WM8991_OPVU 0x0100 /* OPVU */ | ||
523 | #define WM8991_ROPGAZC 0x0080 /* ROPGAZC */ | ||
524 | #define WM8991_ROPGAZC_BIT 7 | ||
525 | #define WM8991_ROPGAVOL_MASK 0x007F /* ROPGAVOL - [6:0] */ | ||
526 | #define WM8991_ROPGAVOL_SHIFT 0 | ||
527 | /* | ||
528 | * R34 (0x22) - Speaker Volume | ||
529 | */ | ||
530 | #define WM8991_SPKVOL_MASK 0x0003 /* SPKVOL - [1:0] */ | ||
531 | #define WM8991_SPKVOL_SHIFT 0 | ||
532 | |||
533 | /* | ||
534 | * R35 (0x23) - ClassD1 | ||
535 | */ | ||
536 | #define WM8991_CDMODE 0x0100 /* CDMODE */ | ||
537 | #define WM8991_CDMODE_BIT 8 | ||
538 | |||
539 | /* | ||
540 | * R37 (0x25) - ClassD3 | ||
541 | */ | ||
542 | #define WM8991_DCGAIN_MASK 0x0007 /* DCGAIN - [5:3] */ | ||
543 | #define WM8991_DCGAIN_SHIFT 3 | ||
544 | #define WM8991_ACGAIN_MASK 0x0007 /* ACGAIN - [2:0] */ | ||
545 | #define WM8991_ACGAIN_SHIFT 0 | ||
546 | /* | ||
547 | * R39 (0x27) - Input Mixer1 | ||
548 | */ | ||
549 | #define WM8991_AINLMODE_MASK 0x000C /* AINLMODE - [3:2] */ | ||
550 | #define WM8991_AINLMODE_SHIFT 2 | ||
551 | #define WM8991_AINRMODE_MASK 0x0003 /* AINRMODE - [1:0] */ | ||
552 | #define WM8991_AINRMODE_SHIFT 0 | ||
553 | |||
554 | /* | ||
555 | * R40 (0x28) - Input Mixer2 | ||
556 | */ | ||
557 | #define WM8991_LMP4 0x0080 /* LMP4 */ | ||
558 | #define WM8991_LMP4_BIT 7 /* LMP4 */ | ||
559 | #define WM8991_LMN3 0x0040 /* LMN3 */ | ||
560 | #define WM8991_LMN3_BIT 6 /* LMN3 */ | ||
561 | #define WM8991_LMP2 0x0020 /* LMP2 */ | ||
562 | #define WM8991_LMP2_BIT 5 /* LMP2 */ | ||
563 | #define WM8991_LMN1 0x0010 /* LMN1 */ | ||
564 | #define WM8991_LMN1_BIT 4 /* LMN1 */ | ||
565 | #define WM8991_RMP4 0x0008 /* RMP4 */ | ||
566 | #define WM8991_RMP4_BIT 3 /* RMP4 */ | ||
567 | #define WM8991_RMN3 0x0004 /* RMN3 */ | ||
568 | #define WM8991_RMN3_BIT 2 /* RMN3 */ | ||
569 | #define WM8991_RMP2 0x0002 /* RMP2 */ | ||
570 | #define WM8991_RMP2_BIT 1 /* RMP2 */ | ||
571 | #define WM8991_RMN1 0x0001 /* RMN1 */ | ||
572 | #define WM8991_RMN1_BIT 0 /* RMN1 */ | ||
573 | |||
574 | /* | ||
575 | * R41 (0x29) - Input Mixer3 | ||
576 | */ | ||
577 | #define WM8991_L34MNB 0x0100 /* L34MNB */ | ||
578 | #define WM8991_L34MNB_BIT 8 | ||
579 | #define WM8991_L34MNBST 0x0080 /* L34MNBST */ | ||
580 | #define WM8991_L34MNBST_BIT 7 | ||
581 | #define WM8991_L12MNB 0x0020 /* L12MNB */ | ||
582 | #define WM8991_L12MNB_BIT 5 | ||
583 | #define WM8991_L12MNBST 0x0010 /* L12MNBST */ | ||
584 | #define WM8991_L12MNBST_BIT 4 | ||
585 | #define WM8991_LDBVOL_MASK 0x0007 /* LDBVOL - [2:0] */ | ||
586 | #define WM8991_LDBVOL_SHIFT 0 | ||
587 | |||
588 | /* | ||
589 | * R42 (0x2A) - Input Mixer4 | ||
590 | */ | ||
591 | #define WM8991_R34MNB 0x0100 /* R34MNB */ | ||
592 | #define WM8991_R34MNB_BIT 8 | ||
593 | #define WM8991_R34MNBST 0x0080 /* R34MNBST */ | ||
594 | #define WM8991_R34MNBST_BIT 7 | ||
595 | #define WM8991_R12MNB 0x0020 /* R12MNB */ | ||
596 | #define WM8991_R12MNB_BIT 5 | ||
597 | #define WM8991_R12MNBST 0x0010 /* R12MNBST */ | ||
598 | #define WM8991_R12MNBST_BIT 4 | ||
599 | #define WM8991_RDBVOL_MASK 0x0007 /* RDBVOL - [2:0] */ | ||
600 | #define WM8991_RDBVOL_SHIFT 0 | ||
601 | |||
602 | /* | ||
603 | * R43 (0x2B) - Input Mixer5 | ||
604 | */ | ||
605 | #define WM8991_LI2BVOL_MASK 0x07 /* LI2BVOL - [8:6] */ | ||
606 | #define WM8991_LI2BVOL_SHIFT 6 | ||
607 | #define WM8991_LR4BVOL_MASK 0x07 /* LR4BVOL - [5:3] */ | ||
608 | #define WM8991_LR4BVOL_SHIFT 3 | ||
609 | #define WM8991_LL4BVOL_MASK 0x07 /* LL4BVOL - [2:0] */ | ||
610 | #define WM8991_LL4BVOL_SHIFT 0 | ||
611 | |||
612 | /* | ||
613 | * R44 (0x2C) - Input Mixer6 | ||
614 | */ | ||
615 | #define WM8991_RI2BVOL_MASK 0x07 /* RI2BVOL - [8:6] */ | ||
616 | #define WM8991_RI2BVOL_SHIFT 6 | ||
617 | #define WM8991_RL4BVOL_MASK 0x07 /* RL4BVOL - [5:3] */ | ||
618 | #define WM8991_RL4BVOL_SHIFT 3 | ||
619 | #define WM8991_RR4BVOL_MASK 0x07 /* RR4BVOL - [2:0] */ | ||
620 | #define WM8991_RR4BVOL_SHIFT 0 | ||
621 | |||
622 | /* | ||
623 | * R45 (0x2D) - Output Mixer1 | ||
624 | */ | ||
625 | #define WM8991_LRBLO 0x0080 /* LRBLO */ | ||
626 | #define WM8991_LRBLO_BIT 7 | ||
627 | #define WM8991_LLBLO 0x0040 /* LLBLO */ | ||
628 | #define WM8991_LLBLO_BIT 6 | ||
629 | #define WM8991_LRI3LO 0x0020 /* LRI3LO */ | ||
630 | #define WM8991_LRI3LO_BIT 5 | ||
631 | #define WM8991_LLI3LO 0x0010 /* LLI3LO */ | ||
632 | #define WM8991_LLI3LO_BIT 4 | ||
633 | #define WM8991_LR12LO 0x0008 /* LR12LO */ | ||
634 | #define WM8991_LR12LO_BIT 3 | ||
635 | #define WM8991_LL12LO 0x0004 /* LL12LO */ | ||
636 | #define WM8991_LL12LO_BIT 2 | ||
637 | #define WM8991_LDLO 0x0001 /* LDLO */ | ||
638 | #define WM8991_LDLO_BIT 0 | ||
639 | |||
640 | /* | ||
641 | * R46 (0x2E) - Output Mixer2 | ||
642 | */ | ||
643 | #define WM8991_RLBRO 0x0080 /* RLBRO */ | ||
644 | #define WM8991_RLBRO_BIT 7 | ||
645 | #define WM8991_RRBRO 0x0040 /* RRBRO */ | ||
646 | #define WM8991_RRBRO_BIT 6 | ||
647 | #define WM8991_RLI3RO 0x0020 /* RLI3RO */ | ||
648 | #define WM8991_RLI3RO_BIT 5 | ||
649 | #define WM8991_RRI3RO 0x0010 /* RRI3RO */ | ||
650 | #define WM8991_RRI3RO_BIT 4 | ||
651 | #define WM8991_RL12RO 0x0008 /* RL12RO */ | ||
652 | #define WM8991_RL12RO_BIT 3 | ||
653 | #define WM8991_RR12RO 0x0004 /* RR12RO */ | ||
654 | #define WM8991_RR12RO_BIT 2 | ||
655 | #define WM8991_RDRO 0x0001 /* RDRO */ | ||
656 | #define WM8991_RDRO_BIT 0 | ||
657 | |||
658 | /* | ||
659 | * R47 (0x2F) - Output Mixer3 | ||
660 | */ | ||
661 | #define WM8991_LLI3LOVOL_MASK 0x07 /* LLI3LOVOL - [8:6] */ | ||
662 | #define WM8991_LLI3LOVOL_SHIFT 6 | ||
663 | #define WM8991_LR12LOVOL_MASK 0x07 /* LR12LOVOL - [5:3] */ | ||
664 | #define WM8991_LR12LOVOL_SHIFT 3 | ||
665 | #define WM8991_LL12LOVOL_MASK 0x07 /* LL12LOVOL - [2:0] */ | ||
666 | #define WM8991_LL12LOVOL_SHIFT 0 | ||
667 | |||
668 | /* | ||
669 | * R48 (0x30) - Output Mixer4 | ||
670 | */ | ||
671 | #define WM8991_RRI3ROVOL_MASK 0x07 /* RRI3ROVOL - [8:6] */ | ||
672 | #define WM8991_RRI3ROVOL_SHIFT 6 | ||
673 | #define WM8991_RL12ROVOL_MASK 0x07 /* RL12ROVOL - [5:3] */ | ||
674 | #define WM8991_RL12ROVOL_SHIFT 3 | ||
675 | #define WM8991_RR12ROVOL_MASK 0x07 /* RR12ROVOL - [2:0] */ | ||
676 | #define WM8991_RR12ROVOL_SHIFT 0 | ||
677 | |||
678 | /* | ||
679 | * R49 (0x31) - Output Mixer5 | ||
680 | */ | ||
681 | #define WM8991_LRI3LOVOL_MASK 0x07 /* LRI3LOVOL - [8:6] */ | ||
682 | #define WM8991_LRI3LOVOL_SHIFT 6 | ||
683 | #define WM8991_LRBLOVOL_MASK 0x07 /* LRBLOVOL - [5:3] */ | ||
684 | #define WM8991_LRBLOVOL_SHIFT 3 | ||
685 | #define WM8991_LLBLOVOL_MASK 0x07 /* LLBLOVOL - [2:0] */ | ||
686 | #define WM8991_LLBLOVOL_SHIFT 0 | ||
687 | |||
688 | /* | ||
689 | * R50 (0x32) - Output Mixer6 | ||
690 | */ | ||
691 | #define WM8991_RLI3ROVOL_MASK 0x07 /* RLI3ROVOL - [8:6] */ | ||
692 | #define WM8991_RLI3ROVOL_SHIFT 6 | ||
693 | #define WM8991_RLBROVOL_MASK 0x07 /* RLBROVOL - [5:3] */ | ||
694 | #define WM8991_RLBROVOL_SHIFT 3 | ||
695 | #define WM8991_RRBROVOL_MASK 0x07 /* RRBROVOL - [2:0] */ | ||
696 | #define WM8991_RRBROVOL_SHIFT 0 | ||
697 | |||
698 | /* | ||
699 | * R51 (0x33) - Out3/4 Mixer | ||
700 | */ | ||
701 | #define WM8991_VSEL_MASK 0x0180 /* VSEL - [8:7] */ | ||
702 | #define WM8991_LI4O3 0x0020 /* LI4O3 */ | ||
703 | #define WM8991_LI4O3_BIT 5 | ||
704 | #define WM8991_LPGAO3 0x0010 /* LPGAO3 */ | ||
705 | #define WM8991_LPGAO3_BIT 4 | ||
706 | #define WM8991_RI4O4 0x0002 /* RI4O4 */ | ||
707 | #define WM8991_RI4O4_BIT 1 | ||
708 | #define WM8991_RPGAO4 0x0001 /* RPGAO4 */ | ||
709 | #define WM8991_RPGAO4_BIT 0 | ||
710 | /* | ||
711 | * R52 (0x34) - Line Mixer1 | ||
712 | */ | ||
713 | #define WM8991_LLOPGALON 0x0040 /* LLOPGALON */ | ||
714 | #define WM8991_LLOPGALON_BIT 6 | ||
715 | #define WM8991_LROPGALON 0x0020 /* LROPGALON */ | ||
716 | #define WM8991_LROPGALON_BIT 5 | ||
717 | #define WM8991_LOPLON 0x0010 /* LOPLON */ | ||
718 | #define WM8991_LOPLON_BIT 4 | ||
719 | #define WM8991_LR12LOP 0x0004 /* LR12LOP */ | ||
720 | #define WM8991_LR12LOP_BIT 2 | ||
721 | #define WM8991_LL12LOP 0x0002 /* LL12LOP */ | ||
722 | #define WM8991_LL12LOP_BIT 1 | ||
723 | #define WM8991_LLOPGALOP 0x0001 /* LLOPGALOP */ | ||
724 | #define WM8991_LLOPGALOP_BIT 0 | ||
725 | /* | ||
726 | * R53 (0x35) - Line Mixer2 | ||
727 | */ | ||
728 | #define WM8991_RROPGARON 0x0040 /* RROPGARON */ | ||
729 | #define WM8991_RROPGARON_BIT 6 | ||
730 | #define WM8991_RLOPGARON 0x0020 /* RLOPGARON */ | ||
731 | #define WM8991_RLOPGARON_BIT 5 | ||
732 | #define WM8991_ROPRON 0x0010 /* ROPRON */ | ||
733 | #define WM8991_ROPRON_BIT 4 | ||
734 | #define WM8991_RL12ROP 0x0004 /* RL12ROP */ | ||
735 | #define WM8991_RL12ROP_BIT 2 | ||
736 | #define WM8991_RR12ROP 0x0002 /* RR12ROP */ | ||
737 | #define WM8991_RR12ROP_BIT 1 | ||
738 | #define WM8991_RROPGAROP 0x0001 /* RROPGAROP */ | ||
739 | #define WM8991_RROPGAROP_BIT 0 | ||
740 | |||
741 | /* | ||
742 | * R54 (0x36) - Speaker Mixer | ||
743 | */ | ||
744 | #define WM8991_LB2SPK 0x0080 /* LB2SPK */ | ||
745 | #define WM8991_LB2SPK_BIT 7 | ||
746 | #define WM8991_RB2SPK 0x0040 /* RB2SPK */ | ||
747 | #define WM8991_RB2SPK_BIT 6 | ||
748 | #define WM8991_LI2SPK 0x0020 /* LI2SPK */ | ||
749 | #define WM8991_LI2SPK_BIT 5 | ||
750 | #define WM8991_RI2SPK 0x0010 /* RI2SPK */ | ||
751 | #define WM8991_RI2SPK_BIT 4 | ||
752 | #define WM8991_LOPGASPK 0x0008 /* LOPGASPK */ | ||
753 | #define WM8991_LOPGASPK_BIT 3 | ||
754 | #define WM8991_ROPGASPK 0x0004 /* ROPGASPK */ | ||
755 | #define WM8991_ROPGASPK_BIT 2 | ||
756 | #define WM8991_LDSPK 0x0002 /* LDSPK */ | ||
757 | #define WM8991_LDSPK_BIT 1 | ||
758 | #define WM8991_RDSPK 0x0001 /* RDSPK */ | ||
759 | #define WM8991_RDSPK_BIT 0 | ||
760 | |||
761 | /* | ||
762 | * R55 (0x37) - Additional Control | ||
763 | */ | ||
764 | #define WM8991_VROI 0x0001 /* VROI */ | ||
765 | |||
766 | /* | ||
767 | * R56 (0x38) - AntiPOP1 | ||
768 | */ | ||
769 | #define WM8991_DIS_LLINE 0x0020 /* DIS_LLINE */ | ||
770 | #define WM8991_DIS_RLINE 0x0010 /* DIS_RLINE */ | ||
771 | #define WM8991_DIS_OUT3 0x0008 /* DIS_OUT3 */ | ||
772 | #define WM8991_DIS_OUT4 0x0004 /* DIS_OUT4 */ | ||
773 | #define WM8991_DIS_LOUT 0x0002 /* DIS_LOUT */ | ||
774 | #define WM8991_DIS_ROUT 0x0001 /* DIS_ROUT */ | ||
775 | |||
776 | /* | ||
777 | * R57 (0x39) - AntiPOP2 | ||
778 | */ | ||
779 | #define WM8991_SOFTST 0x0040 /* SOFTST */ | ||
780 | #define WM8991_BUFIOEN 0x0008 /* BUFIOEN */ | ||
781 | #define WM8991_BUFDCOPEN 0x0004 /* BUFDCOPEN */ | ||
782 | #define WM8991_POBCTRL 0x0002 /* POBCTRL */ | ||
783 | #define WM8991_VMIDTOG 0x0001 /* VMIDTOG */ | ||
784 | |||
785 | /* | ||
786 | * R58 (0x3A) - MICBIAS | ||
787 | */ | ||
788 | #define WM8991_MCDSCTH_MASK 0x00C0 /* MCDSCTH - [7:6] */ | ||
789 | #define WM8991_MCDTHR_MASK 0x0038 /* MCDTHR - [5:3] */ | ||
790 | #define WM8991_MCD 0x0004 /* MCD */ | ||
791 | #define WM8991_MBSEL 0x0001 /* MBSEL */ | ||
792 | |||
793 | /* | ||
794 | * R60 (0x3C) - PLL1 | ||
795 | */ | ||
796 | #define WM8991_SDM 0x0080 /* SDM */ | ||
797 | #define WM8991_PRESCALE 0x0040 /* PRESCALE */ | ||
798 | #define WM8991_PLLN_MASK 0x000F /* PLLN - [3:0] */ | ||
799 | |||
800 | /* | ||
801 | * R61 (0x3D) - PLL2 | ||
802 | */ | ||
803 | #define WM8991_PLLK1_MASK 0x00FF /* PLLK1 - [7:0] */ | ||
804 | |||
805 | /* | ||
806 | * R62 (0x3E) - PLL3 | ||
807 | */ | ||
808 | #define WM8991_PLLK2_MASK 0x00FF /* PLLK2 - [7:0] */ | ||
809 | |||
810 | /* | ||
811 | * R63 (0x3F) - Internal Driver Bits | ||
812 | */ | ||
813 | #define WM8991_INMIXL_PWR_BIT 0 | ||
814 | #define WM8991_AINLMUX_PWR_BIT 1 | ||
815 | #define WM8991_INMIXR_PWR_BIT 2 | ||
816 | #define WM8991_AINRMUX_PWR_BIT 3 | ||
817 | |||
818 | #define WM8991_MCLK_DIV 0 | ||
819 | #define WM8991_DACCLK_DIV 1 | ||
820 | #define WM8991_ADCCLK_DIV 2 | ||
821 | #define WM8991_BCLK_DIV 3 | ||
822 | |||
823 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ | ||
824 | tlv_array) \ | ||
825 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
826 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
827 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
828 | .tlv.p = (tlv_array), \ | ||
829 | .info = snd_soc_info_volsw, \ | ||
830 | .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ | ||
831 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
832 | |||
833 | #endif /* _WM8991_H */ | ||
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 18c0d9ce7c32..379fa22c5b6c 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -242,7 +242,7 @@ struct wm8993_priv { | |||
242 | int fll_src; | 242 | int fll_src; |
243 | }; | 243 | }; |
244 | 244 | ||
245 | static int wm8993_volatile(unsigned int reg) | 245 | static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg) |
246 | { | 246 | { |
247 | switch (reg) { | 247 | switch (reg) { |
248 | case WM8993_SOFTWARE_RESET: | 248 | case WM8993_SOFTWARE_RESET: |
diff --git a/sound/soc/codecs/wm8994-tables.c b/sound/soc/codecs/wm8994-tables.c index 68e9b024dd48..a87adbd05ee1 100644 --- a/sound/soc/codecs/wm8994-tables.c +++ b/sound/soc/codecs/wm8994-tables.c | |||
@@ -62,8 +62,8 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { | |||
62 | { 0x00FF, 0x00FF }, /* R58 - MICBIAS */ | 62 | { 0x00FF, 0x00FF }, /* R58 - MICBIAS */ |
63 | { 0x000F, 0x000F }, /* R59 - LDO 1 */ | 63 | { 0x000F, 0x000F }, /* R59 - LDO 1 */ |
64 | { 0x0007, 0x0007 }, /* R60 - LDO 2 */ | 64 | { 0x0007, 0x0007 }, /* R60 - LDO 2 */ |
65 | { 0x0000, 0x0000 }, /* R61 */ | 65 | { 0xFFFF, 0xFFFF }, /* R61 */ |
66 | { 0x0000, 0x0000 }, /* R62 */ | 66 | { 0xFFFF, 0xFFFF }, /* R62 */ |
67 | { 0x0000, 0x0000 }, /* R63 */ | 67 | { 0x0000, 0x0000 }, /* R63 */ |
68 | { 0x0000, 0x0000 }, /* R64 */ | 68 | { 0x0000, 0x0000 }, /* R64 */ |
69 | { 0x0000, 0x0000 }, /* R65 */ | 69 | { 0x0000, 0x0000 }, /* R65 */ |
@@ -209,9 +209,9 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { | |||
209 | { 0x0000, 0x0000 }, /* R205 */ | 209 | { 0x0000, 0x0000 }, /* R205 */ |
210 | { 0x0000, 0x0000 }, /* R206 */ | 210 | { 0x0000, 0x0000 }, /* R206 */ |
211 | { 0x0000, 0x0000 }, /* R207 */ | 211 | { 0x0000, 0x0000 }, /* R207 */ |
212 | { 0x0000, 0x0000 }, /* R208 */ | 212 | { 0xFFFF, 0xFFFF }, /* R208 */ |
213 | { 0x0000, 0x0000 }, /* R209 */ | 213 | { 0xFFFF, 0xFFFF }, /* R209 */ |
214 | { 0x0000, 0x0000 }, /* R210 */ | 214 | { 0xFFFF, 0xFFFF }, /* R210 */ |
215 | { 0x0000, 0x0000 }, /* R211 */ | 215 | { 0x0000, 0x0000 }, /* R211 */ |
216 | { 0x0000, 0x0000 }, /* R212 */ | 216 | { 0x0000, 0x0000 }, /* R212 */ |
217 | { 0x0000, 0x0000 }, /* R213 */ | 217 | { 0x0000, 0x0000 }, /* R213 */ |
@@ -1573,7 +1573,7 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { | |||
1573 | { 0x03C3, 0x03C3 }, /* R1569 - Sidetone */ | 1573 | { 0x03C3, 0x03C3 }, /* R1569 - Sidetone */ |
1574 | }; | 1574 | }; |
1575 | 1575 | ||
1576 | const __devinitdata u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { | 1576 | const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { |
1577 | 0x8994, /* R0 - Software Reset */ | 1577 | 0x8994, /* R0 - Software Reset */ |
1578 | 0x0000, /* R1 - Power Management (1) */ | 1578 | 0x0000, /* R1 - Power Management (1) */ |
1579 | 0x6000, /* R2 - Power Management (2) */ | 1579 | 0x6000, /* R2 - Power Management (2) */ |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index c6c958ee5d59..3dc64c8b6a5c 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -102,8 +102,7 @@ struct wm8994_priv { | |||
102 | 102 | ||
103 | wm8958_micdet_cb jack_cb; | 103 | wm8958_micdet_cb jack_cb; |
104 | void *jack_cb_data; | 104 | void *jack_cb_data; |
105 | bool jack_is_mic; | 105 | int micdet_irq; |
106 | bool jack_is_video; | ||
107 | 106 | ||
108 | int revision; | 107 | int revision; |
109 | struct wm8994_pdata *pdata; | 108 | struct wm8994_pdata *pdata; |
@@ -115,7 +114,7 @@ struct wm8994_priv { | |||
115 | unsigned int aif2clk_disable:1; | 114 | unsigned int aif2clk_disable:1; |
116 | }; | 115 | }; |
117 | 116 | ||
118 | static int wm8994_readable(unsigned int reg) | 117 | static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg) |
119 | { | 118 | { |
120 | switch (reg) { | 119 | switch (reg) { |
121 | case WM8994_GPIO_1: | 120 | case WM8994_GPIO_1: |
@@ -142,7 +141,7 @@ static int wm8994_readable(unsigned int reg) | |||
142 | return wm8994_access_masks[reg].readable != 0; | 141 | return wm8994_access_masks[reg].readable != 0; |
143 | } | 142 | } |
144 | 143 | ||
145 | static int wm8994_volatile(unsigned int reg) | 144 | static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg) |
146 | { | 145 | { |
147 | if (reg >= WM8994_CACHE_SIZE) | 146 | if (reg >= WM8994_CACHE_SIZE) |
148 | return 1; | 147 | return 1; |
@@ -170,7 +169,7 @@ static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg, | |||
170 | 169 | ||
171 | BUG_ON(reg > WM8994_MAX_REGISTER); | 170 | BUG_ON(reg > WM8994_MAX_REGISTER); |
172 | 171 | ||
173 | if (!wm8994_volatile(reg)) { | 172 | if (!wm8994_volatile(codec, reg)) { |
174 | ret = snd_soc_cache_write(codec, reg, value); | 173 | ret = snd_soc_cache_write(codec, reg, value); |
175 | if (ret != 0) | 174 | if (ret != 0) |
176 | dev_err(codec->dev, "Cache write to %x failed: %d\n", | 175 | dev_err(codec->dev, "Cache write to %x failed: %d\n", |
@@ -188,7 +187,7 @@ static unsigned int wm8994_read(struct snd_soc_codec *codec, | |||
188 | 187 | ||
189 | BUG_ON(reg > WM8994_MAX_REGISTER); | 188 | BUG_ON(reg > WM8994_MAX_REGISTER); |
190 | 189 | ||
191 | if (!wm8994_volatile(reg) && wm8994_readable(reg) && | 190 | if (!wm8994_volatile(codec, reg) && wm8994_readable(codec, reg) && |
192 | reg < codec->driver->reg_cache_size) { | 191 | reg < codec->driver->reg_cache_size) { |
193 | ret = snd_soc_cache_read(codec, reg, &val); | 192 | ret = snd_soc_cache_read(codec, reg, &val); |
194 | if (ret >= 0) | 193 | if (ret >= 0) |
@@ -529,7 +528,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
529 | struct snd_ctl_elem_value *ucontrol) | 528 | struct snd_ctl_elem_value *ucontrol) |
530 | { | 529 | { |
531 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 530 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
532 | struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec); | 531 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
533 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 532 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
534 | 533 | ||
535 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; | 534 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; |
@@ -1103,6 +1102,13 @@ static int adc_mux_ev(struct snd_soc_dapm_widget *w, | |||
1103 | return 0; | 1102 | return 0; |
1104 | } | 1103 | } |
1105 | 1104 | ||
1105 | static int micbias_ev(struct snd_soc_dapm_widget *w, | ||
1106 | struct snd_kcontrol *kcontrol, int event) | ||
1107 | { | ||
1108 | late_enable_ev(w, kcontrol, event); | ||
1109 | return 0; | ||
1110 | } | ||
1111 | |||
1106 | static int dac_ev(struct snd_soc_dapm_widget *w, | 1112 | static int dac_ev(struct snd_soc_dapm_widget *w, |
1107 | struct snd_kcontrol *kcontrol, int event) | 1113 | struct snd_kcontrol *kcontrol, int event) |
1108 | { | 1114 | { |
@@ -1440,6 +1446,10 @@ SND_SOC_DAPM_INPUT("DMIC1DAT"), | |||
1440 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 1446 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
1441 | SND_SOC_DAPM_INPUT("Clock"), | 1447 | SND_SOC_DAPM_INPUT("Clock"), |
1442 | 1448 | ||
1449 | SND_SOC_DAPM_MICBIAS("MICBIAS", WM8994_MICBIAS, 2, 0), | ||
1450 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, | ||
1451 | SND_SOC_DAPM_PRE_PMU), | ||
1452 | |||
1443 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1453 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
1444 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1454 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
1445 | 1455 | ||
@@ -1755,6 +1765,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { | |||
1755 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, | 1765 | { "AIF2DACDAT", NULL, "AIF1DACDAT" }, |
1756 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, | 1766 | { "AIF1ADCDAT", NULL, "AIF2ADCDAT" }, |
1757 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, | 1767 | { "AIF2ADCDAT", NULL, "AIF1ADCDAT" }, |
1768 | { "MICBIAS", NULL, "CLK_SYS" }, | ||
1769 | { "MICBIAS", NULL, "MICBIAS Supply" }, | ||
1758 | }; | 1770 | }; |
1759 | 1771 | ||
1760 | static const struct snd_soc_dapm_route wm8994_intercon[] = { | 1772 | static const struct snd_soc_dapm_route wm8994_intercon[] = { |
@@ -2883,6 +2895,13 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
2883 | else | 2895 | else |
2884 | snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, | 2896 | snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, |
2885 | ARRAY_SIZE(wm8994_eq_controls)); | 2897 | ARRAY_SIZE(wm8994_eq_controls)); |
2898 | |||
2899 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { | ||
2900 | if (pdata->micbias[i]) { | ||
2901 | snd_soc_write(codec, WM8958_MICBIAS1 + i, | ||
2902 | pdata->micbias[i] & 0xffff); | ||
2903 | } | ||
2904 | } | ||
2886 | } | 2905 | } |
2887 | 2906 | ||
2888 | /** | 2907 | /** |
@@ -2993,46 +3012,18 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
2993 | int report = 0; | 3012 | int report = 0; |
2994 | 3013 | ||
2995 | /* If nothing present then clear our statuses */ | 3014 | /* If nothing present then clear our statuses */ |
2996 | if (!(status & WM8958_MICD_STS)) { | 3015 | if (!(status & WM8958_MICD_STS)) |
2997 | wm8994->jack_is_video = false; | ||
2998 | wm8994->jack_is_mic = false; | ||
2999 | goto done; | 3016 | goto done; |
3000 | } | ||
3001 | 3017 | ||
3002 | /* Assume anything over 475 ohms is a microphone and remember | 3018 | report = SND_JACK_MICROPHONE; |
3003 | * that we've seen one (since buttons override it) */ | ||
3004 | if (status & 0x600) | ||
3005 | wm8994->jack_is_mic = true; | ||
3006 | if (wm8994->jack_is_mic) | ||
3007 | report |= SND_JACK_MICROPHONE; | ||
3008 | |||
3009 | /* Video has an impedence of approximately 75 ohms; assume | ||
3010 | * this isn't used as a button and remember it since buttons | ||
3011 | * override it. */ | ||
3012 | if (status & 0x40) | ||
3013 | wm8994->jack_is_video = true; | ||
3014 | if (wm8994->jack_is_video) | ||
3015 | report |= SND_JACK_VIDEOOUT; | ||
3016 | 3019 | ||
3017 | /* Everything else is buttons; just assign slots */ | 3020 | /* Everything else is buttons; just assign slots */ |
3018 | if (status & 0x4) | 3021 | if (status & 0x1c0) |
3019 | report |= SND_JACK_BTN_0; | 3022 | report |= SND_JACK_BTN_0; |
3020 | if (status & 0x8) | ||
3021 | report |= SND_JACK_BTN_1; | ||
3022 | if (status & 0x10) | ||
3023 | report |= SND_JACK_BTN_2; | ||
3024 | if (status & 0x20) | ||
3025 | report |= SND_JACK_BTN_3; | ||
3026 | if (status & 0x80) | ||
3027 | report |= SND_JACK_BTN_4; | ||
3028 | if (status & 0x100) | ||
3029 | report |= SND_JACK_BTN_5; | ||
3030 | 3023 | ||
3031 | done: | 3024 | done: |
3032 | snd_soc_jack_report(wm8994->micdet[0].jack, report, | 3025 | snd_soc_jack_report(wm8994->micdet[0].jack, report, |
3033 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | | 3026 | SND_JACK_BTN_0 | SND_JACK_MICROPHONE); |
3034 | SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5 | | ||
3035 | SND_JACK_MICROPHONE | SND_JACK_VIDEOOUT); | ||
3036 | } | 3027 | } |
3037 | 3028 | ||
3038 | /** | 3029 | /** |
@@ -3131,13 +3122,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3131 | wm8994->pdata = dev_get_platdata(codec->dev->parent); | 3122 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
3132 | wm8994->codec = codec; | 3123 | wm8994->codec = codec; |
3133 | 3124 | ||
3125 | if (wm8994->pdata && wm8994->pdata->micdet_irq) | ||
3126 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; | ||
3127 | else if (wm8994->pdata && wm8994->pdata->irq_base) | ||
3128 | wm8994->micdet_irq = wm8994->pdata->irq_base + | ||
3129 | WM8994_IRQ_MIC1_DET; | ||
3130 | |||
3134 | pm_runtime_enable(codec->dev); | 3131 | pm_runtime_enable(codec->dev); |
3135 | pm_runtime_resume(codec->dev); | 3132 | pm_runtime_resume(codec->dev); |
3136 | 3133 | ||
3137 | /* Read our current status back from the chip - we don't want to | 3134 | /* Read our current status back from the chip - we don't want to |
3138 | * reset as this may interfere with the GPIO or LDO operation. */ | 3135 | * reset as this may interfere with the GPIO or LDO operation. */ |
3139 | for (i = 0; i < WM8994_CACHE_SIZE; i++) { | 3136 | for (i = 0; i < WM8994_CACHE_SIZE; i++) { |
3140 | if (!wm8994_readable(i) || wm8994_volatile(i)) | 3137 | if (!wm8994_readable(codec, i) || wm8994_volatile(codec, i)) |
3141 | continue; | 3138 | continue; |
3142 | 3139 | ||
3143 | ret = wm8994_reg_read(codec->control_data, i); | 3140 | ret = wm8994_reg_read(codec->control_data, i); |
@@ -3179,14 +3176,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3179 | 3176 | ||
3180 | switch (control->type) { | 3177 | switch (control->type) { |
3181 | case WM8994: | 3178 | case WM8994: |
3182 | ret = wm8994_request_irq(codec->control_data, | 3179 | if (wm8994->micdet_irq) { |
3183 | WM8994_IRQ_MIC1_DET, | 3180 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
3184 | wm8994_mic_irq, "Mic 1 detect", | 3181 | wm8994_mic_irq, |
3185 | wm8994); | 3182 | IRQF_TRIGGER_RISING, |
3186 | if (ret != 0) | 3183 | "Mic1 detect", |
3187 | dev_warn(codec->dev, | 3184 | wm8994); |
3188 | "Failed to request Mic1 detect IRQ: %d\n", | 3185 | if (ret != 0) |
3189 | ret); | 3186 | dev_warn(codec->dev, |
3187 | "Failed to request Mic1 detect IRQ: %d\n", | ||
3188 | ret); | ||
3189 | } | ||
3190 | 3190 | ||
3191 | ret = wm8994_request_irq(codec->control_data, | 3191 | ret = wm8994_request_irq(codec->control_data, |
3192 | WM8994_IRQ_MIC1_SHRT, | 3192 | WM8994_IRQ_MIC1_SHRT, |
@@ -3217,15 +3217,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3217 | break; | 3217 | break; |
3218 | 3218 | ||
3219 | case WM8958: | 3219 | case WM8958: |
3220 | ret = wm8994_request_irq(codec->control_data, | 3220 | if (wm8994->micdet_irq) { |
3221 | WM8994_IRQ_MIC1_DET, | 3221 | ret = request_threaded_irq(wm8994->micdet_irq, NULL, |
3222 | wm8958_mic_irq, "Mic detect", | 3222 | wm8958_mic_irq, |
3223 | wm8994); | 3223 | IRQF_TRIGGER_RISING, |
3224 | if (ret != 0) | 3224 | "Mic detect", |
3225 | dev_warn(codec->dev, | 3225 | wm8994); |
3226 | "Failed to request Mic detect IRQ: %d\n", | 3226 | if (ret != 0) |
3227 | ret); | 3227 | dev_warn(codec->dev, |
3228 | break; | 3228 | "Failed to request Mic detect IRQ: %d\n", |
3229 | ret); | ||
3230 | } | ||
3229 | } | 3231 | } |
3230 | 3232 | ||
3231 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 3233 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
@@ -3369,7 +3371,8 @@ err_irq: | |||
3369 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 3371 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
3370 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 3372 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
3371 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 3373 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); |
3372 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); | 3374 | if (wm8994->micdet_irq) |
3375 | free_irq(wm8994->micdet_irq, wm8994); | ||
3373 | err: | 3376 | err: |
3374 | kfree(wm8994); | 3377 | kfree(wm8994); |
3375 | return ret; | 3378 | return ret; |
@@ -3386,8 +3389,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3386 | 3389 | ||
3387 | switch (control->type) { | 3390 | switch (control->type) { |
3388 | case WM8994: | 3391 | case WM8994: |
3389 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, | 3392 | if (wm8994->micdet_irq) |
3390 | wm8994); | 3393 | free_irq(wm8994->micdet_irq, wm8994); |
3391 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, | 3394 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, |
3392 | wm8994); | 3395 | wm8994); |
3393 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, | 3396 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, |
@@ -3397,8 +3400,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3397 | break; | 3400 | break; |
3398 | 3401 | ||
3399 | case WM8958: | 3402 | case WM8958: |
3400 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, | 3403 | if (wm8994->micdet_irq) |
3401 | wm8994); | 3404 | free_irq(wm8994->micdet_irq, wm8994); |
3402 | break; | 3405 | break; |
3403 | } | 3406 | } |
3404 | kfree(wm8994->retune_mobile_texts); | 3407 | kfree(wm8994->retune_mobile_texts); |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 0c355bfc88f1..999b8851226b 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -43,6 +43,6 @@ struct wm8994_access_mask { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE]; | 45 | extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE]; |
46 | extern const __devinitdata u16 wm8994_reg_defaults[WM8994_CACHE_SIZE]; | 46 | extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE]; |
47 | 47 | ||
48 | #endif | 48 | #endif |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 608c84c5aa8e..67eaaecbb42e 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/regulator/consumer.h> | ||
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
@@ -30,6 +31,18 @@ | |||
30 | 31 | ||
31 | #include "wm8995.h" | 32 | #include "wm8995.h" |
32 | 33 | ||
34 | #define WM8995_NUM_SUPPLIES 8 | ||
35 | static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = { | ||
36 | "DCVDD", | ||
37 | "DBVDD1", | ||
38 | "DBVDD2", | ||
39 | "DBVDD3", | ||
40 | "AVDD1", | ||
41 | "AVDD2", | ||
42 | "CPVDD", | ||
43 | "MICVDD" | ||
44 | }; | ||
45 | |||
33 | static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = { | 46 | static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = { |
34 | [0] = 0x8995, [5] = 0x0100, [16] = 0x000b, [17] = 0x000b, | 47 | [0] = 0x8995, [5] = 0x0100, [16] = 0x000b, [17] = 0x000b, |
35 | [24] = 0x02c0, [25] = 0x02c0, [26] = 0x02c0, [27] = 0x02c0, | 48 | [24] = 0x02c0, [25] = 0x02c0, [26] = 0x02c0, [27] = 0x02c0, |
@@ -126,8 +139,37 @@ struct wm8995_priv { | |||
126 | int mclk[2]; | 139 | int mclk[2]; |
127 | int aifclk[2]; | 140 | int aifclk[2]; |
128 | struct fll_config fll[2], fll_suspend[2]; | 141 | struct fll_config fll[2], fll_suspend[2]; |
142 | struct regulator_bulk_data supplies[WM8995_NUM_SUPPLIES]; | ||
143 | struct notifier_block disable_nb[WM8995_NUM_SUPPLIES]; | ||
144 | struct snd_soc_codec *codec; | ||
129 | }; | 145 | }; |
130 | 146 | ||
147 | /* | ||
148 | * We can't use the same notifier block for more than one supply and | ||
149 | * there's no way I can see to get from a callback to the caller | ||
150 | * except container_of(). | ||
151 | */ | ||
152 | #define WM8995_REGULATOR_EVENT(n) \ | ||
153 | static int wm8995_regulator_event_##n(struct notifier_block *nb, \ | ||
154 | unsigned long event, void *data) \ | ||
155 | { \ | ||
156 | struct wm8995_priv *wm8995 = container_of(nb, struct wm8995_priv, \ | ||
157 | disable_nb[n]); \ | ||
158 | if (event & REGULATOR_EVENT_DISABLE) { \ | ||
159 | wm8995->codec->cache_sync = 1; \ | ||
160 | } \ | ||
161 | return 0; \ | ||
162 | } | ||
163 | |||
164 | WM8995_REGULATOR_EVENT(0) | ||
165 | WM8995_REGULATOR_EVENT(1) | ||
166 | WM8995_REGULATOR_EVENT(2) | ||
167 | WM8995_REGULATOR_EVENT(3) | ||
168 | WM8995_REGULATOR_EVENT(4) | ||
169 | WM8995_REGULATOR_EVENT(5) | ||
170 | WM8995_REGULATOR_EVENT(6) | ||
171 | WM8995_REGULATOR_EVENT(7) | ||
172 | |||
131 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | 173 | static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); |
132 | static const DECLARE_TLV_DB_SCALE(in1lr_pga_tlv, -1650, 150, 0); | 174 | static const DECLARE_TLV_DB_SCALE(in1lr_pga_tlv, -1650, 150, 0); |
133 | static const DECLARE_TLV_DB_SCALE(in1l_boost_tlv, 0, 600, 0); | 175 | static const DECLARE_TLV_DB_SCALE(in1l_boost_tlv, 0, 600, 0); |
@@ -909,7 +951,7 @@ static const struct snd_soc_dapm_route wm8995_intercon[] = { | |||
909 | { "SPK2R", NULL, "SPK2R Driver" } | 951 | { "SPK2R", NULL, "SPK2R Driver" } |
910 | }; | 952 | }; |
911 | 953 | ||
912 | static int wm8995_volatile(unsigned int reg) | 954 | static int wm8995_volatile(struct snd_soc_codec *codec, unsigned int reg) |
913 | { | 955 | { |
914 | /* out of bounds registers are generally considered | 956 | /* out of bounds registers are generally considered |
915 | * volatile to support register banks that are partially | 957 | * volatile to support register banks that are partially |
@@ -1483,6 +1525,11 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec, | |||
1483 | break; | 1525 | break; |
1484 | case SND_SOC_BIAS_STANDBY: | 1526 | case SND_SOC_BIAS_STANDBY: |
1485 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1527 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1528 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies), | ||
1529 | wm8995->supplies); | ||
1530 | if (ret) | ||
1531 | return ret; | ||
1532 | |||
1486 | ret = snd_soc_cache_sync(codec); | 1533 | ret = snd_soc_cache_sync(codec); |
1487 | if (ret) { | 1534 | if (ret) { |
1488 | dev_err(codec->dev, | 1535 | dev_err(codec->dev, |
@@ -1492,12 +1539,13 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec, | |||
1492 | 1539 | ||
1493 | snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, | 1540 | snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, |
1494 | WM8995_BG_ENA_MASK, WM8995_BG_ENA); | 1541 | WM8995_BG_ENA_MASK, WM8995_BG_ENA); |
1495 | |||
1496 | } | 1542 | } |
1497 | break; | 1543 | break; |
1498 | case SND_SOC_BIAS_OFF: | 1544 | case SND_SOC_BIAS_OFF: |
1499 | snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, | 1545 | snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1, |
1500 | WM8995_BG_ENA_MASK, 0); | 1546 | WM8995_BG_ENA_MASK, 0); |
1547 | regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies), | ||
1548 | wm8995->supplies); | ||
1501 | break; | 1549 | break; |
1502 | } | 1550 | } |
1503 | 1551 | ||
@@ -1536,10 +1584,12 @@ static int wm8995_remove(struct snd_soc_codec *codec) | |||
1536 | static int wm8995_probe(struct snd_soc_codec *codec) | 1584 | static int wm8995_probe(struct snd_soc_codec *codec) |
1537 | { | 1585 | { |
1538 | struct wm8995_priv *wm8995; | 1586 | struct wm8995_priv *wm8995; |
1587 | int i; | ||
1539 | int ret; | 1588 | int ret; |
1540 | 1589 | ||
1541 | codec->dapm.idle_bias_off = 1; | 1590 | codec->dapm.idle_bias_off = 1; |
1542 | wm8995 = snd_soc_codec_get_drvdata(codec); | 1591 | wm8995 = snd_soc_codec_get_drvdata(codec); |
1592 | wm8995->codec = codec; | ||
1543 | 1593 | ||
1544 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type); | 1594 | ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type); |
1545 | if (ret < 0) { | 1595 | if (ret < 0) { |
@@ -1547,21 +1597,58 @@ static int wm8995_probe(struct snd_soc_codec *codec) | |||
1547 | return ret; | 1597 | return ret; |
1548 | } | 1598 | } |
1549 | 1599 | ||
1600 | for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) | ||
1601 | wm8995->supplies[i].supply = wm8995_supply_names[i]; | ||
1602 | |||
1603 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8995->supplies), | ||
1604 | wm8995->supplies); | ||
1605 | if (ret) { | ||
1606 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
1607 | return ret; | ||
1608 | } | ||
1609 | |||
1610 | wm8995->disable_nb[0].notifier_call = wm8995_regulator_event_0; | ||
1611 | wm8995->disable_nb[1].notifier_call = wm8995_regulator_event_1; | ||
1612 | wm8995->disable_nb[2].notifier_call = wm8995_regulator_event_2; | ||
1613 | wm8995->disable_nb[3].notifier_call = wm8995_regulator_event_3; | ||
1614 | wm8995->disable_nb[4].notifier_call = wm8995_regulator_event_4; | ||
1615 | wm8995->disable_nb[5].notifier_call = wm8995_regulator_event_5; | ||
1616 | wm8995->disable_nb[6].notifier_call = wm8995_regulator_event_6; | ||
1617 | wm8995->disable_nb[7].notifier_call = wm8995_regulator_event_7; | ||
1618 | |||
1619 | /* This should really be moved into the regulator core */ | ||
1620 | for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) { | ||
1621 | ret = regulator_register_notifier(wm8995->supplies[i].consumer, | ||
1622 | &wm8995->disable_nb[i]); | ||
1623 | if (ret) { | ||
1624 | dev_err(codec->dev, | ||
1625 | "Failed to register regulator notifier: %d\n", | ||
1626 | ret); | ||
1627 | } | ||
1628 | } | ||
1629 | |||
1630 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies), | ||
1631 | wm8995->supplies); | ||
1632 | if (ret) { | ||
1633 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
1634 | goto err_reg_get; | ||
1635 | } | ||
1636 | |||
1550 | ret = snd_soc_read(codec, WM8995_SOFTWARE_RESET); | 1637 | ret = snd_soc_read(codec, WM8995_SOFTWARE_RESET); |
1551 | if (ret < 0) { | 1638 | if (ret < 0) { |
1552 | dev_err(codec->dev, "Failed to read device ID: %d\n", ret); | 1639 | dev_err(codec->dev, "Failed to read device ID: %d\n", ret); |
1553 | return ret; | 1640 | goto err_reg_enable; |
1554 | } | 1641 | } |
1555 | 1642 | ||
1556 | if (ret != 0x8995) { | 1643 | if (ret != 0x8995) { |
1557 | dev_err(codec->dev, "Invalid device ID: %#x\n", ret); | 1644 | dev_err(codec->dev, "Invalid device ID: %#x\n", ret); |
1558 | return -EINVAL; | 1645 | goto err_reg_enable; |
1559 | } | 1646 | } |
1560 | 1647 | ||
1561 | ret = snd_soc_write(codec, WM8995_SOFTWARE_RESET, 0); | 1648 | ret = snd_soc_write(codec, WM8995_SOFTWARE_RESET, 0); |
1562 | if (ret < 0) { | 1649 | if (ret < 0) { |
1563 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 1650 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
1564 | return ret; | 1651 | goto err_reg_enable; |
1565 | } | 1652 | } |
1566 | 1653 | ||
1567 | wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1654 | wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -1596,6 +1683,12 @@ static int wm8995_probe(struct snd_soc_codec *codec) | |||
1596 | ARRAY_SIZE(wm8995_intercon)); | 1683 | ARRAY_SIZE(wm8995_intercon)); |
1597 | 1684 | ||
1598 | return 0; | 1685 | return 0; |
1686 | |||
1687 | err_reg_enable: | ||
1688 | regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies), wm8995->supplies); | ||
1689 | err_reg_get: | ||
1690 | regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies); | ||
1691 | return ret; | ||
1599 | } | 1692 | } |
1600 | 1693 | ||
1601 | #define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 1694 | #define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index cce704c275c6..55cdf2982020 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -167,10 +167,10 @@ struct wm9081_priv { | |||
167 | int fll_fref; | 167 | int fll_fref; |
168 | int fll_fout; | 168 | int fll_fout; |
169 | int tdm_width; | 169 | int tdm_width; |
170 | struct wm9081_retune_mobile_config *retune; | 170 | struct wm9081_pdata pdata; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static int wm9081_volatile_register(unsigned int reg) | 173 | static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
174 | { | 174 | { |
175 | switch (reg) { | 175 | switch (reg) { |
176 | case WM9081_SOFTWARE_RESET: | 176 | case WM9081_SOFTWARE_RESET: |
@@ -389,27 +389,6 @@ SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0), | |||
389 | SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0), | 389 | SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0), |
390 | }; | 390 | }; |
391 | 391 | ||
392 | static int speaker_event(struct snd_soc_dapm_widget *w, | ||
393 | struct snd_kcontrol *kcontrol, int event) | ||
394 | { | ||
395 | struct snd_soc_codec *codec = w->codec; | ||
396 | unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT); | ||
397 | |||
398 | switch (event) { | ||
399 | case SND_SOC_DAPM_POST_PMU: | ||
400 | reg |= WM9081_SPK_ENA; | ||
401 | break; | ||
402 | |||
403 | case SND_SOC_DAPM_PRE_PMD: | ||
404 | reg &= ~WM9081_SPK_ENA; | ||
405 | break; | ||
406 | } | ||
407 | |||
408 | snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | struct _fll_div { | 392 | struct _fll_div { |
414 | u16 fll_fratio; | 393 | u16 fll_fratio; |
415 | u16 fll_outdiv; | 394 | u16 fll_outdiv; |
@@ -747,9 +726,8 @@ SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0, | |||
747 | 726 | ||
748 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), | 727 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), |
749 | 728 | ||
750 | SND_SOC_DAPM_PGA_E("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0, | 729 | SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0), |
751 | speaker_event, | 730 | SND_SOC_DAPM_PGA("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), |
752 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
753 | 731 | ||
754 | SND_SOC_DAPM_OUTPUT("LINEOUT"), | 732 | SND_SOC_DAPM_OUTPUT("LINEOUT"), |
755 | SND_SOC_DAPM_OUTPUT("SPKN"), | 733 | SND_SOC_DAPM_OUTPUT("SPKN"), |
@@ -762,7 +740,7 @@ SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0), | |||
762 | }; | 740 | }; |
763 | 741 | ||
764 | 742 | ||
765 | static const struct snd_soc_dapm_route audio_paths[] = { | 743 | static const struct snd_soc_dapm_route wm9081_audio_paths[] = { |
766 | { "DAC", NULL, "CLK_SYS" }, | 744 | { "DAC", NULL, "CLK_SYS" }, |
767 | { "DAC", NULL, "CLK_DSP" }, | 745 | { "DAC", NULL, "CLK_DSP" }, |
768 | 746 | ||
@@ -780,8 +758,10 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
780 | { "Speaker PGA", NULL, "TOCLK" }, | 758 | { "Speaker PGA", NULL, "TOCLK" }, |
781 | { "Speaker PGA", NULL, "CLK_SYS" }, | 759 | { "Speaker PGA", NULL, "CLK_SYS" }, |
782 | 760 | ||
783 | { "SPKN", NULL, "Speaker PGA" }, | 761 | { "Speaker", NULL, "Speaker PGA" }, |
784 | { "SPKP", NULL, "Speaker PGA" }, | 762 | |
763 | { "SPKN", NULL, "Speaker" }, | ||
764 | { "SPKP", NULL, "Speaker" }, | ||
785 | }; | 765 | }; |
786 | 766 | ||
787 | static int wm9081_set_bias_level(struct snd_soc_codec *codec, | 767 | static int wm9081_set_bias_level(struct snd_soc_codec *codec, |
@@ -1082,21 +1062,22 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, | |||
1082 | aif4 |= wm9081->bclk / wm9081->fs; | 1062 | aif4 |= wm9081->bclk / wm9081->fs; |
1083 | 1063 | ||
1084 | /* Apply a ReTune Mobile configuration if it's in use */ | 1064 | /* Apply a ReTune Mobile configuration if it's in use */ |
1085 | if (wm9081->retune) { | 1065 | if (wm9081->pdata.num_retune_configs) { |
1086 | struct wm9081_retune_mobile_config *retune = wm9081->retune; | 1066 | struct wm9081_pdata *pdata = &wm9081->pdata; |
1087 | struct wm9081_retune_mobile_setting *s; | 1067 | struct wm9081_retune_mobile_setting *s; |
1088 | int eq1; | 1068 | int eq1; |
1089 | 1069 | ||
1090 | best = 0; | 1070 | best = 0; |
1091 | best_val = abs(retune->configs[0].rate - wm9081->fs); | 1071 | best_val = abs(pdata->retune_configs[0].rate - wm9081->fs); |
1092 | for (i = 0; i < retune->num_configs; i++) { | 1072 | for (i = 0; i < pdata->num_retune_configs; i++) { |
1093 | cur_val = abs(retune->configs[i].rate - wm9081->fs); | 1073 | cur_val = abs(pdata->retune_configs[i].rate - |
1074 | wm9081->fs); | ||
1094 | if (cur_val < best_val) { | 1075 | if (cur_val < best_val) { |
1095 | best_val = cur_val; | 1076 | best_val = cur_val; |
1096 | best = i; | 1077 | best = i; |
1097 | } | 1078 | } |
1098 | } | 1079 | } |
1099 | s = &retune->configs[best]; | 1080 | s = &pdata->retune_configs[best]; |
1100 | 1081 | ||
1101 | dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", | 1082 | dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", |
1102 | s->name, s->rate); | 1083 | s->name, s->rate); |
@@ -1139,10 +1120,9 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1139 | return 0; | 1120 | return 0; |
1140 | } | 1121 | } |
1141 | 1122 | ||
1142 | static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai, | 1123 | static int wm9081_set_sysclk(struct snd_soc_codec *codec, |
1143 | int clk_id, unsigned int freq, int dir) | 1124 | int clk_id, unsigned int freq, int dir) |
1144 | { | 1125 | { |
1145 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1146 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1126 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1147 | 1127 | ||
1148 | switch (clk_id) { | 1128 | switch (clk_id) { |
@@ -1207,7 +1187,6 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, | |||
1207 | 1187 | ||
1208 | static struct snd_soc_dai_ops wm9081_dai_ops = { | 1188 | static struct snd_soc_dai_ops wm9081_dai_ops = { |
1209 | .hw_params = wm9081_hw_params, | 1189 | .hw_params = wm9081_hw_params, |
1210 | .set_sysclk = wm9081_set_sysclk, | ||
1211 | .set_fmt = wm9081_set_dai_fmt, | 1190 | .set_fmt = wm9081_set_dai_fmt, |
1212 | .digital_mute = wm9081_digital_mute, | 1191 | .digital_mute = wm9081_digital_mute, |
1213 | .set_tdm_slot = wm9081_set_tdm_slot, | 1192 | .set_tdm_slot = wm9081_set_tdm_slot, |
@@ -1231,7 +1210,6 @@ static struct snd_soc_dai_driver wm9081_dai = { | |||
1231 | static int wm9081_probe(struct snd_soc_codec *codec) | 1210 | static int wm9081_probe(struct snd_soc_codec *codec) |
1232 | { | 1211 | { |
1233 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1212 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1234 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
1235 | int ret; | 1213 | int ret; |
1236 | u16 reg; | 1214 | u16 reg; |
1237 | 1215 | ||
@@ -1255,6 +1233,14 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1255 | return ret; | 1233 | return ret; |
1256 | } | 1234 | } |
1257 | 1235 | ||
1236 | reg = 0; | ||
1237 | if (wm9081->pdata.irq_high) | ||
1238 | reg |= WM9081_IRQ_POL; | ||
1239 | if (!wm9081->pdata.irq_cmos) | ||
1240 | reg |= WM9081_IRQ_OP_CTRL; | ||
1241 | snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL, | ||
1242 | WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg); | ||
1243 | |||
1258 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1244 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1259 | 1245 | ||
1260 | /* Enable zero cross by default */ | 1246 | /* Enable zero cross by default */ |
@@ -1266,17 +1252,13 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1266 | 1252 | ||
1267 | snd_soc_add_controls(codec, wm9081_snd_controls, | 1253 | snd_soc_add_controls(codec, wm9081_snd_controls, |
1268 | ARRAY_SIZE(wm9081_snd_controls)); | 1254 | ARRAY_SIZE(wm9081_snd_controls)); |
1269 | if (!wm9081->retune) { | 1255 | if (!wm9081->pdata.num_retune_configs) { |
1270 | dev_dbg(codec->dev, | 1256 | dev_dbg(codec->dev, |
1271 | "No ReTune Mobile data, using normal EQ\n"); | 1257 | "No ReTune Mobile data, using normal EQ\n"); |
1272 | snd_soc_add_controls(codec, wm9081_eq_controls, | 1258 | snd_soc_add_controls(codec, wm9081_eq_controls, |
1273 | ARRAY_SIZE(wm9081_eq_controls)); | 1259 | ARRAY_SIZE(wm9081_eq_controls)); |
1274 | } | 1260 | } |
1275 | 1261 | ||
1276 | snd_soc_dapm_new_controls(dapm, wm9081_dapm_widgets, | ||
1277 | ARRAY_SIZE(wm9081_dapm_widgets)); | ||
1278 | snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); | ||
1279 | |||
1280 | return ret; | 1262 | return ret; |
1281 | } | 1263 | } |
1282 | 1264 | ||
@@ -1320,11 +1302,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { | |||
1320 | .remove = wm9081_remove, | 1302 | .remove = wm9081_remove, |
1321 | .suspend = wm9081_suspend, | 1303 | .suspend = wm9081_suspend, |
1322 | .resume = wm9081_resume, | 1304 | .resume = wm9081_resume, |
1305 | |||
1306 | .set_sysclk = wm9081_set_sysclk, | ||
1323 | .set_bias_level = wm9081_set_bias_level, | 1307 | .set_bias_level = wm9081_set_bias_level, |
1308 | |||
1324 | .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults), | 1309 | .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults), |
1325 | .reg_word_size = sizeof(u16), | 1310 | .reg_word_size = sizeof(u16), |
1326 | .reg_cache_default = wm9081_reg_defaults, | 1311 | .reg_cache_default = wm9081_reg_defaults, |
1327 | .volatile_register = wm9081_volatile_register, | 1312 | .volatile_register = wm9081_volatile_register, |
1313 | |||
1314 | .dapm_widgets = wm9081_dapm_widgets, | ||
1315 | .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), | ||
1316 | .dapm_routes = wm9081_audio_paths, | ||
1317 | .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), | ||
1328 | }; | 1318 | }; |
1329 | 1319 | ||
1330 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1320 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
@@ -1343,8 +1333,8 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, | |||
1343 | wm9081->control_data = i2c; | 1333 | wm9081->control_data = i2c; |
1344 | 1334 | ||
1345 | if (dev_get_platdata(&i2c->dev)) | 1335 | if (dev_get_platdata(&i2c->dev)) |
1346 | memcpy(&wm9081->retune, dev_get_platdata(&i2c->dev), | 1336 | memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev), |
1347 | sizeof(wm9081->retune)); | 1337 | sizeof(wm9081->pdata)); |
1348 | 1338 | ||
1349 | ret = snd_soc_register_codec(&i2c->dev, | 1339 | ret = snd_soc_register_codec(&i2c->dev, |
1350 | &soc_codec_dev_wm9081, &wm9081_dai, 1); | 1340 | &soc_codec_dev_wm9081, &wm9081_dai, 1); |
@@ -1368,7 +1358,7 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); | |||
1368 | 1358 | ||
1369 | static struct i2c_driver wm9081_i2c_driver = { | 1359 | static struct i2c_driver wm9081_i2c_driver = { |
1370 | .driver = { | 1360 | .driver = { |
1371 | .name = "wm9081-codec", | 1361 | .name = "wm9081", |
1372 | .owner = THIS_MODULE, | 1362 | .owner = THIS_MODULE, |
1373 | }, | 1363 | }, |
1374 | .probe = wm9081_i2c_probe, | 1364 | .probe = wm9081_i2c_probe, |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index a788c4297046..4de12203e611 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -144,7 +144,7 @@ struct wm9090_priv { | |||
144 | void *control_data; | 144 | void *control_data; |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static int wm9090_volatile(unsigned int reg) | 147 | static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg) |
148 | { | 148 | { |
149 | switch (reg) { | 149 | switch (reg) { |
150 | case WM9090_SOFTWARE_RESET: | 150 | case WM9090_SOFTWARE_RESET: |
@@ -518,7 +518,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
518 | for (i = 1; i < codec->driver->reg_cache_size; i++) { | 518 | for (i = 1; i < codec->driver->reg_cache_size; i++) { |
519 | if (reg_cache[i] == wm9090_reg_defaults[i]) | 519 | if (reg_cache[i] == wm9090_reg_defaults[i]) |
520 | continue; | 520 | continue; |
521 | if (wm9090_volatile(i)) | 521 | if (wm9090_volatile(codec, i)) |
522 | continue; | 522 | continue; |
523 | 523 | ||
524 | ret = snd_soc_write(codec, i, reg_cache[i]); | 524 | ret = snd_soc_write(codec, i, reg_cache[i]); |
@@ -551,7 +551,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec, | |||
551 | static int wm9090_probe(struct snd_soc_codec *codec) | 551 | static int wm9090_probe(struct snd_soc_codec *codec) |
552 | { | 552 | { |
553 | struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); | 553 | struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec); |
554 | u16 *reg_cache = codec->reg_cache; | ||
555 | int ret; | 554 | int ret; |
556 | 555 | ||
557 | codec->control_data = wm9090->control_data; | 556 | codec->control_data = wm9090->control_data; |
@@ -576,22 +575,30 @@ static int wm9090_probe(struct snd_soc_codec *codec) | |||
576 | /* Configure some defaults; they will be written out when we | 575 | /* Configure some defaults; they will be written out when we |
577 | * bring the bias up. | 576 | * bring the bias up. |
578 | */ | 577 | */ |
579 | reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU | 578 | snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_A_VOLUME, |
580 | | WM9090_IN1A_ZC; | 579 | WM9090_IN1_VU | WM9090_IN1A_ZC, |
581 | reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU | 580 | WM9090_IN1_VU | WM9090_IN1A_ZC); |
582 | | WM9090_IN1B_ZC; | 581 | snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_B_VOLUME, |
583 | reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU | 582 | WM9090_IN1_VU | WM9090_IN1B_ZC, |
584 | | WM9090_IN2A_ZC; | 583 | WM9090_IN1_VU | WM9090_IN1B_ZC); |
585 | reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU | 584 | snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_A_VOLUME, |
586 | | WM9090_IN2B_ZC; | 585 | WM9090_IN2_VU | WM9090_IN2A_ZC, |
587 | reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |= | 586 | WM9090_IN2_VU | WM9090_IN2A_ZC); |
588 | WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC; | 587 | snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_B_VOLUME, |
589 | reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |= | 588 | WM9090_IN2_VU | WM9090_IN2B_ZC, |
590 | WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC; | 589 | WM9090_IN2_VU | WM9090_IN2B_ZC); |
591 | reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |= | 590 | snd_soc_update_bits(codec, WM9090_SPEAKER_VOLUME_LEFT, |
592 | WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC; | 591 | WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC, |
593 | 592 | WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC); | |
594 | reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA; | 593 | snd_soc_update_bits(codec, WM9090_LEFT_OUTPUT_VOLUME, |
594 | WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC, | ||
595 | WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC); | ||
596 | snd_soc_update_bits(codec, WM9090_RIGHT_OUTPUT_VOLUME, | ||
597 | WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC, | ||
598 | WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC); | ||
599 | |||
600 | snd_soc_update_bits(codec, WM9090_CLOCKING_1, | ||
601 | WM9090_TOCLK_ENA, WM9090_TOCLK_ENA); | ||
595 | 602 | ||
596 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 603 | wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
597 | 604 | ||
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 516892706063..7b6b3c18e299 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -82,7 +82,8 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) | |||
82 | } while (reg & op && count < 400); | 82 | } while (reg & op && count < 400); |
83 | 83 | ||
84 | if (reg & op) | 84 | if (reg & op) |
85 | dev_err(codec->dev, "Timed out waiting for DC Servo\n"); | 85 | dev_err(codec->dev, "Timed out waiting for DC Servo %x\n", |
86 | op); | ||
86 | } | 87 | } |
87 | 88 | ||
88 | /* | 89 | /* |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 9e0e565e6ed9..d0d60b8a54d4 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -658,7 +658,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
658 | return -ENODEV; | 658 | return -ENODEV; |
659 | } | 659 | } |
660 | 660 | ||
661 | ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1, | 661 | ioarea = request_mem_region(mem->start, resource_size(mem), |
662 | pdev->name); | 662 | pdev->name); |
663 | if (!ioarea) { | 663 | if (!ioarea) { |
664 | dev_err(&pdev->dev, "McBSP region already claimed\n"); | 664 | dev_err(&pdev->dev, "McBSP region already claimed\n"); |
@@ -694,20 +694,25 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
694 | } | 694 | } |
695 | clk_enable(dev->clk); | 695 | clk_enable(dev->clk); |
696 | 696 | ||
697 | dev->base = (void __iomem *)IO_ADDRESS(mem->start); | 697 | dev->base = ioremap(mem->start, resource_size(mem)); |
698 | if (!dev->base) { | ||
699 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
700 | ret = -ENOMEM; | ||
701 | goto err_release_clk; | ||
702 | } | ||
698 | 703 | ||
699 | dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr = | 704 | dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr = |
700 | (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG); | 705 | (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); |
701 | 706 | ||
702 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = | 707 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = |
703 | (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG); | 708 | (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG); |
704 | 709 | ||
705 | /* first TX, then RX */ | 710 | /* first TX, then RX */ |
706 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 711 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
707 | if (!res) { | 712 | if (!res) { |
708 | dev_err(&pdev->dev, "no DMA resource\n"); | 713 | dev_err(&pdev->dev, "no DMA resource\n"); |
709 | ret = -ENXIO; | 714 | ret = -ENXIO; |
710 | goto err_free_mem; | 715 | goto err_iounmap; |
711 | } | 716 | } |
712 | dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start; | 717 | dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start; |
713 | 718 | ||
@@ -715,7 +720,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
715 | if (!res) { | 720 | if (!res) { |
716 | dev_err(&pdev->dev, "no DMA resource\n"); | 721 | dev_err(&pdev->dev, "no DMA resource\n"); |
717 | ret = -ENXIO; | 722 | ret = -ENXIO; |
718 | goto err_free_mem; | 723 | goto err_iounmap; |
719 | } | 724 | } |
720 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; | 725 | dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; |
721 | dev->dev = &pdev->dev; | 726 | dev->dev = &pdev->dev; |
@@ -724,14 +729,19 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
724 | 729 | ||
725 | ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); | 730 | ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai); |
726 | if (ret != 0) | 731 | if (ret != 0) |
727 | goto err_free_mem; | 732 | goto err_iounmap; |
728 | 733 | ||
729 | return 0; | 734 | return 0; |
730 | 735 | ||
736 | err_iounmap: | ||
737 | iounmap(dev->base); | ||
738 | err_release_clk: | ||
739 | clk_disable(dev->clk); | ||
740 | clk_put(dev->clk); | ||
731 | err_free_mem: | 741 | err_free_mem: |
732 | kfree(dev); | 742 | kfree(dev); |
733 | err_release_region: | 743 | err_release_region: |
734 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 744 | release_mem_region(mem->start, resource_size(mem)); |
735 | 745 | ||
736 | return ret; | 746 | return ret; |
737 | } | 747 | } |
@@ -747,7 +757,7 @@ static int davinci_i2s_remove(struct platform_device *pdev) | |||
747 | dev->clk = NULL; | 757 | dev->clk = NULL; |
748 | kfree(dev); | 758 | kfree(dev); |
749 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 759 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
750 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 760 | release_mem_region(mem->start, resource_size(mem)); |
751 | 761 | ||
752 | return 0; | 762 | return 0; |
753 | } | 763 | } |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index fb55d2c5d704..a5af834c8ef5 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -868,7 +868,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
868 | } | 868 | } |
869 | 869 | ||
870 | ioarea = request_mem_region(mem->start, | 870 | ioarea = request_mem_region(mem->start, |
871 | (mem->end - mem->start) + 1, pdev->name); | 871 | resource_size(mem), pdev->name); |
872 | if (!ioarea) { | 872 | if (!ioarea) { |
873 | dev_err(&pdev->dev, "Audio region already claimed\n"); | 873 | dev_err(&pdev->dev, "Audio region already claimed\n"); |
874 | ret = -EBUSY; | 874 | ret = -EBUSY; |
@@ -885,7 +885,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
885 | clk_enable(dev->clk); | 885 | clk_enable(dev->clk); |
886 | dev->clk_active = 1; | 886 | dev->clk_active = 1; |
887 | 887 | ||
888 | dev->base = (void __iomem *)IO_ADDRESS(mem->start); | 888 | dev->base = ioremap(mem->start, resource_size(mem)); |
889 | if (!dev->base) { | ||
890 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
891 | ret = -ENOMEM; | ||
892 | goto err_release_clk; | ||
893 | } | ||
894 | |||
889 | dev->op_mode = pdata->op_mode; | 895 | dev->op_mode = pdata->op_mode; |
890 | dev->tdm_slots = pdata->tdm_slots; | 896 | dev->tdm_slots = pdata->tdm_slots; |
891 | dev->num_serializer = pdata->num_serializer; | 897 | dev->num_serializer = pdata->num_serializer; |
@@ -899,14 +905,14 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
899 | dma_data->asp_chan_q = pdata->asp_chan_q; | 905 | dma_data->asp_chan_q = pdata->asp_chan_q; |
900 | dma_data->ram_chan_q = pdata->ram_chan_q; | 906 | dma_data->ram_chan_q = pdata->ram_chan_q; |
901 | dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + | 907 | dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset + |
902 | io_v2p(dev->base)); | 908 | mem->start); |
903 | 909 | ||
904 | /* first TX, then RX */ | 910 | /* first TX, then RX */ |
905 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 911 | res = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
906 | if (!res) { | 912 | if (!res) { |
907 | dev_err(&pdev->dev, "no DMA resource\n"); | 913 | dev_err(&pdev->dev, "no DMA resource\n"); |
908 | ret = -ENODEV; | 914 | ret = -ENODEV; |
909 | goto err_release_region; | 915 | goto err_iounmap; |
910 | } | 916 | } |
911 | 917 | ||
912 | dma_data->channel = res->start; | 918 | dma_data->channel = res->start; |
@@ -915,13 +921,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
915 | dma_data->asp_chan_q = pdata->asp_chan_q; | 921 | dma_data->asp_chan_q = pdata->asp_chan_q; |
916 | dma_data->ram_chan_q = pdata->ram_chan_q; | 922 | dma_data->ram_chan_q = pdata->ram_chan_q; |
917 | dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + | 923 | dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset + |
918 | io_v2p(dev->base)); | 924 | mem->start); |
919 | 925 | ||
920 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 926 | res = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
921 | if (!res) { | 927 | if (!res) { |
922 | dev_err(&pdev->dev, "no DMA resource\n"); | 928 | dev_err(&pdev->dev, "no DMA resource\n"); |
923 | ret = -ENODEV; | 929 | ret = -ENODEV; |
924 | goto err_release_region; | 930 | goto err_iounmap; |
925 | } | 931 | } |
926 | 932 | ||
927 | dma_data->channel = res->start; | 933 | dma_data->channel = res->start; |
@@ -929,11 +935,16 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
929 | ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); | 935 | ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]); |
930 | 936 | ||
931 | if (ret != 0) | 937 | if (ret != 0) |
932 | goto err_release_region; | 938 | goto err_iounmap; |
933 | return 0; | 939 | return 0; |
934 | 940 | ||
941 | err_iounmap: | ||
942 | iounmap(dev->base); | ||
943 | err_release_clk: | ||
944 | clk_disable(dev->clk); | ||
945 | clk_put(dev->clk); | ||
935 | err_release_region: | 946 | err_release_region: |
936 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 947 | release_mem_region(mem->start, resource_size(mem)); |
937 | err_release_data: | 948 | err_release_data: |
938 | kfree(dev); | 949 | kfree(dev); |
939 | 950 | ||
@@ -951,7 +962,7 @@ static int davinci_mcasp_remove(struct platform_device *pdev) | |||
951 | dev->clk = NULL; | 962 | dev->clk = NULL; |
952 | 963 | ||
953 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 964 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
954 | release_mem_region(mem->start, (mem->end - mem->start) + 1); | 965 | release_mem_region(mem->start, resource_size(mem)); |
955 | 966 | ||
956 | kfree(dev); | 967 | kfree(dev); |
957 | 968 | ||
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig index 57429041189c..91a28de94109 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/ep93xx/Kconfig | |||
@@ -30,3 +30,12 @@ config SND_EP93XX_SOC_SIMONE | |||
30 | help | 30 | help |
31 | Say Y or M here if you want to add support for AC97 audio on the | 31 | Say Y or M here if you want to add support for AC97 audio on the |
32 | Simplemachines Sim.One board. | 32 | Simplemachines Sim.One board. |
33 | |||
34 | config SND_EP93XX_SOC_EDB93XX | ||
35 | tristate "SoC Audio support for Cirrus Logic EDB93xx boards" | ||
36 | depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A) | ||
37 | select SND_EP93XX_SOC_I2S | ||
38 | select SND_SOC_CS4271 | ||
39 | help | ||
40 | Say Y or M here if you want to add support for I2S audio on the | ||
41 | Cirrus Logic EDB93xx boards. | ||
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile index 8e7977fb6b7d..5514146cbdf0 100644 --- a/sound/soc/ep93xx/Makefile +++ b/sound/soc/ep93xx/Makefile | |||
@@ -10,6 +10,8 @@ obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o | |||
10 | # EP93XX Machine Support | 10 | # EP93XX Machine Support |
11 | snd-soc-snappercl15-objs := snappercl15.o | 11 | snd-soc-snappercl15-objs := snappercl15.o |
12 | snd-soc-simone-objs := simone.o | 12 | snd-soc-simone-objs := simone.o |
13 | snd-soc-edb93xx-objs := edb93xx.o | ||
13 | 14 | ||
14 | obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o | 15 | obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o |
15 | obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o | 16 | obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o |
17 | obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o | ||
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c new file mode 100644 index 000000000000..d3aa15119d26 --- /dev/null +++ b/sound/soc/ep93xx/edb93xx.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * SoC audio for EDB93xx | ||
3 | * | ||
4 | * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (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 | * This driver support CS4271 codec being master or slave, working | ||
17 | * in control port mode, connected either via SPI or I2C. | ||
18 | * The data format accepted is I2S or left-justified. | ||
19 | * DAPM support not implemented. | ||
20 | */ | ||
21 | |||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/gpio.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | #include <mach/hardware.h> | ||
29 | #include "ep93xx-pcm.h" | ||
30 | |||
31 | #define edb93xx_has_audio() (machine_is_edb9301() || \ | ||
32 | machine_is_edb9302() || \ | ||
33 | machine_is_edb9302a() || \ | ||
34 | machine_is_edb9307a() || \ | ||
35 | machine_is_edb9315a()) | ||
36 | |||
37 | static int edb93xx_hw_params(struct snd_pcm_substream *substream, | ||
38 | struct snd_pcm_hw_params *params) | ||
39 | { | ||
40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
43 | int err; | ||
44 | unsigned int mclk_rate; | ||
45 | unsigned int rate = params_rate(params); | ||
46 | |||
47 | /* | ||
48 | * According to CS4271 datasheet we use MCLK/LRCK=256 for | ||
49 | * rates below 50kHz and 128 for higher sample rates | ||
50 | */ | ||
51 | if (rate < 50000) | ||
52 | mclk_rate = rate * 64 * 4; | ||
53 | else | ||
54 | mclk_rate = rate * 64 * 2; | ||
55 | |||
56 | err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
57 | SND_SOC_DAIFMT_NB_IF | | ||
58 | SND_SOC_DAIFMT_CBS_CFS); | ||
59 | if (err) | ||
60 | return err; | ||
61 | |||
62 | err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
63 | SND_SOC_DAIFMT_NB_IF | | ||
64 | SND_SOC_DAIFMT_CBS_CFS); | ||
65 | if (err) | ||
66 | return err; | ||
67 | |||
68 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, | ||
69 | SND_SOC_CLOCK_IN); | ||
70 | if (err) | ||
71 | return err; | ||
72 | |||
73 | return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, | ||
74 | SND_SOC_CLOCK_OUT); | ||
75 | } | ||
76 | |||
77 | static struct snd_soc_ops edb93xx_ops = { | ||
78 | .hw_params = edb93xx_hw_params, | ||
79 | }; | ||
80 | |||
81 | static struct snd_soc_dai_link edb93xx_dai = { | ||
82 | .name = "CS4271", | ||
83 | .stream_name = "CS4271 HiFi", | ||
84 | .platform_name = "ep93xx-pcm-audio", | ||
85 | .cpu_dai_name = "ep93xx-i2s", | ||
86 | .codec_name = "spi0.0", | ||
87 | .codec_dai_name = "cs4271-hifi", | ||
88 | .ops = &edb93xx_ops, | ||
89 | }; | ||
90 | |||
91 | static struct snd_soc_card snd_soc_edb93xx = { | ||
92 | .name = "EDB93XX", | ||
93 | .dai_link = &edb93xx_dai, | ||
94 | .num_links = 1, | ||
95 | }; | ||
96 | |||
97 | static struct platform_device *edb93xx_snd_device; | ||
98 | |||
99 | static int __init edb93xx_init(void) | ||
100 | { | ||
101 | int ret; | ||
102 | |||
103 | if (!edb93xx_has_audio()) | ||
104 | return -ENODEV; | ||
105 | |||
106 | ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97, | ||
107 | EP93XX_SYSCON_I2SCLKDIV_ORIDE | | ||
108 | EP93XX_SYSCON_I2SCLKDIV_SPOL); | ||
109 | if (ret) | ||
110 | return ret; | ||
111 | |||
112 | edb93xx_snd_device = platform_device_alloc("soc-audio", -1); | ||
113 | if (!edb93xx_snd_device) { | ||
114 | ret = -ENOMEM; | ||
115 | goto free_i2s; | ||
116 | } | ||
117 | |||
118 | platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx); | ||
119 | ret = platform_device_add(edb93xx_snd_device); | ||
120 | if (ret) | ||
121 | goto device_put; | ||
122 | |||
123 | return 0; | ||
124 | |||
125 | device_put: | ||
126 | platform_device_put(edb93xx_snd_device); | ||
127 | free_i2s: | ||
128 | ep93xx_i2s_release(); | ||
129 | return ret; | ||
130 | } | ||
131 | module_init(edb93xx_init); | ||
132 | |||
133 | static void __exit edb93xx_exit(void) | ||
134 | { | ||
135 | platform_device_unregister(edb93xx_snd_device); | ||
136 | ep93xx_i2s_release(); | ||
137 | } | ||
138 | module_exit(edb93xx_exit); | ||
139 | |||
140 | MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>"); | ||
141 | MODULE_DESCRIPTION("ALSA SoC EDB93xx"); | ||
142 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c index 68a0bae1208a..104e95cda0ad 100644 --- a/sound/soc/ep93xx/ep93xx-ac97.c +++ b/sound/soc/ep93xx/ep93xx-ac97.c | |||
@@ -253,7 +253,6 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | |||
253 | struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai); | 253 | struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai); |
254 | unsigned v = 0; | 254 | unsigned v = 0; |
255 | 255 | ||
256 | |||
257 | switch (cmd) { | 256 | switch (cmd) { |
258 | case SNDRV_PCM_TRIGGER_START: | 257 | case SNDRV_PCM_TRIGGER_START: |
259 | case SNDRV_PCM_TRIGGER_RESUME: | 258 | case SNDRV_PCM_TRIGGER_RESUME: |
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c index fff579a1c134..042f4e93746f 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/ep93xx/ep93xx-i2s.c | |||
@@ -242,7 +242,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
242 | { | 242 | { |
243 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); | 243 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
244 | unsigned word_len, div, sdiv, lrdiv; | 244 | unsigned word_len, div, sdiv, lrdiv; |
245 | int found = 0, err; | 245 | int err; |
246 | 246 | ||
247 | switch (params_format(params)) { | 247 | switch (params_format(params)) { |
248 | case SNDRV_PCM_FORMAT_S16_LE: | 248 | case SNDRV_PCM_FORMAT_S16_LE: |
@@ -275,15 +275,14 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
275 | * the codec uses. | 275 | * the codec uses. |
276 | */ | 276 | */ |
277 | div = clk_get_rate(info->mclk) / params_rate(params); | 277 | div = clk_get_rate(info->mclk) / params_rate(params); |
278 | for (sdiv = 2; sdiv <= 4; sdiv += 2) | 278 | sdiv = 4; |
279 | for (lrdiv = 64; lrdiv <= 128; lrdiv <<= 1) | 279 | if (div > (256 + 512) / 2) { |
280 | if (sdiv * lrdiv == div) { | 280 | lrdiv = 128; |
281 | found = 1; | 281 | } else { |
282 | goto out; | 282 | lrdiv = 64; |
283 | } | 283 | if (div < (128 + 256) / 2) |
284 | out: | 284 | sdiv = 2; |
285 | if (!found) | 285 | } |
286 | return -EINVAL; | ||
287 | 286 | ||
288 | err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); | 287 | err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv); |
289 | if (err) | 288 | if (err) |
@@ -314,10 +313,12 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) | |||
314 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); | 313 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
315 | 314 | ||
316 | if (!dai->active) | 315 | if (!dai->active) |
317 | return; | 316 | return 0; |
318 | 317 | ||
319 | ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); | 318 | ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK); |
320 | ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); | 319 | ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE); |
320 | |||
321 | return 0; | ||
321 | } | 322 | } |
322 | 323 | ||
323 | static int ep93xx_i2s_resume(struct snd_soc_dai *dai) | 324 | static int ep93xx_i2s_resume(struct snd_soc_dai *dai) |
@@ -325,10 +326,12 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai) | |||
325 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); | 326 | struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai); |
326 | 327 | ||
327 | if (!dai->active) | 328 | if (!dai->active) |
328 | return; | 329 | return 0; |
329 | 330 | ||
330 | ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); | 331 | ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK); |
331 | ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); | 332 | ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE); |
333 | |||
334 | return 0; | ||
332 | } | 335 | } |
333 | #else | 336 | #else |
334 | #define ep93xx_i2s_suspend NULL | 337 | #define ep93xx_i2s_suspend NULL |
@@ -352,13 +355,13 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = { | |||
352 | .playback = { | 355 | .playback = { |
353 | .channels_min = 2, | 356 | .channels_min = 2, |
354 | .channels_max = 2, | 357 | .channels_max = 2, |
355 | .rates = SNDRV_PCM_RATE_8000_96000, | 358 | .rates = SNDRV_PCM_RATE_8000_192000, |
356 | .formats = EP93XX_I2S_FORMATS, | 359 | .formats = EP93XX_I2S_FORMATS, |
357 | }, | 360 | }, |
358 | .capture = { | 361 | .capture = { |
359 | .channels_min = 2, | 362 | .channels_min = 2, |
360 | .channels_max = 2, | 363 | .channels_max = 2, |
361 | .rates = SNDRV_PCM_RATE_8000_96000, | 364 | .rates = SNDRV_PCM_RATE_8000_192000, |
362 | .formats = EP93XX_I2S_FORMATS, | 365 | .formats = EP93XX_I2S_FORMATS, |
363 | }, | 366 | }, |
364 | .ops = &ep93xx_i2s_dai_ops, | 367 | .ops = &ep93xx_i2s_dai_ops, |
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c index 06670776f649..a456e491155f 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/ep93xx/ep93xx-pcm.c | |||
@@ -35,9 +35,9 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = { | |||
35 | SNDRV_PCM_INFO_INTERLEAVED | | 35 | SNDRV_PCM_INFO_INTERLEAVED | |
36 | SNDRV_PCM_INFO_BLOCK_TRANSFER), | 36 | SNDRV_PCM_INFO_BLOCK_TRANSFER), |
37 | 37 | ||
38 | .rates = SNDRV_PCM_RATE_8000_96000, | 38 | .rates = SNDRV_PCM_RATE_8000_192000, |
39 | .rate_min = SNDRV_PCM_RATE_8000, | 39 | .rate_min = SNDRV_PCM_RATE_8000, |
40 | .rate_max = SNDRV_PCM_RATE_96000, | 40 | .rate_max = SNDRV_PCM_RATE_192000, |
41 | 41 | ||
42 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | | 42 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | |
43 | SNDRV_PCM_FMTBIT_S24_LE | | 43 | SNDRV_PCM_FMTBIT_S24_LE | |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 7d7847a1e66b..c16c6b2eff95 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -53,9 +53,8 @@ struct mpc8610_hpcd_data { | |||
53 | * | 53 | * |
54 | * Here we program the DMACR and PMUXCR registers. | 54 | * Here we program the DMACR and PMUXCR registers. |
55 | */ | 55 | */ |
56 | static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) | 56 | static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card) |
57 | { | 57 | { |
58 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
59 | struct mpc8610_hpcd_data *machine_data = | 58 | struct mpc8610_hpcd_data *machine_data = |
60 | container_of(card, struct mpc8610_hpcd_data, card); | 59 | container_of(card, struct mpc8610_hpcd_data, card); |
61 | struct ccsr_guts_86xx __iomem *guts; | 60 | struct ccsr_guts_86xx __iomem *guts; |
@@ -138,9 +137,8 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) | |||
138 | * This function is called to remove the sound device for one SSI. We | 137 | * This function is called to remove the sound device for one SSI. We |
139 | * de-program the DMACR and PMUXCR register. | 138 | * de-program the DMACR and PMUXCR register. |
140 | */ | 139 | */ |
141 | static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) | 140 | static int mpc8610_hpcd_machine_remove(struct snd_soc_card *card) |
142 | { | 141 | { |
143 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
144 | struct mpc8610_hpcd_data *machine_data = | 142 | struct mpc8610_hpcd_data *machine_data = |
145 | container_of(card, struct mpc8610_hpcd_data, card); | 143 | container_of(card, struct mpc8610_hpcd_data, card); |
146 | struct ccsr_guts_86xx __iomem *guts; | 144 | struct ccsr_guts_86xx __iomem *guts; |
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 026b756961e0..66e0b68af147 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c | |||
@@ -85,9 +85,8 @@ struct machine_data { | |||
85 | * | 85 | * |
86 | * Here we program the DMACR and PMUXCR registers. | 86 | * Here we program the DMACR and PMUXCR registers. |
87 | */ | 87 | */ |
88 | static int p1022_ds_machine_probe(struct platform_device *sound_device) | 88 | static int p1022_ds_machine_probe(struct snd_soc_card *card) |
89 | { | 89 | { |
90 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
91 | struct machine_data *mdata = | 90 | struct machine_data *mdata = |
92 | container_of(card, struct machine_data, card); | 91 | container_of(card, struct machine_data, card); |
93 | struct ccsr_guts_85xx __iomem *guts; | 92 | struct ccsr_guts_85xx __iomem *guts; |
@@ -160,9 +159,8 @@ static int p1022_ds_startup(struct snd_pcm_substream *substream) | |||
160 | * This function is called to remove the sound device for one SSI. We | 159 | * This function is called to remove the sound device for one SSI. We |
161 | * de-program the DMACR and PMUXCR register. | 160 | * de-program the DMACR and PMUXCR register. |
162 | */ | 161 | */ |
163 | static int p1022_ds_machine_remove(struct platform_device *sound_device) | 162 | static int p1022_ds_machine_remove(struct snd_soc_card *card) |
164 | { | 163 | { |
165 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
166 | struct machine_data *mdata = | 164 | struct machine_data *mdata = |
167 | container_of(card, struct machine_data, card); | 165 | container_of(card, struct machine_data, card); |
168 | struct ccsr_guts_85xx __iomem *guts; | 166 | struct ccsr_guts_85xx __iomem *guts; |
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig index 9eeb8f0d67e9..d8f130d39dd9 100644 --- a/sound/soc/imx/Kconfig +++ b/sound/soc/imx/Kconfig | |||
@@ -30,6 +30,16 @@ config SND_MXC_SOC_WM1133_EV1 | |||
30 | Enable support for audio on the i.MX31ADS with the WM1133-EV1 | 30 | Enable support for audio on the i.MX31ADS with the WM1133-EV1 |
31 | PMIC board with WM8835x fitted. | 31 | PMIC board with WM8835x fitted. |
32 | 32 | ||
33 | config SND_SOC_MX27VIS_AIC32X4 | ||
34 | tristate "SoC audio support for Visstrim M10 boards" | ||
35 | depends on MACH_IMX27_VISSTRIM_M10 | ||
36 | select SND_SOC_TVL320AIC32X4 | ||
37 | select SND_MXC_SOC_SSI | ||
38 | select SND_MXC_SOC_MX2 | ||
39 | help | ||
40 | Say Y if you want to add support for SoC audio on Visstrim SM10 | ||
41 | board with TLV320AIC32X4 codec. | ||
42 | |||
33 | config SND_SOC_PHYCORE_AC97 | 43 | config SND_SOC_PHYCORE_AC97 |
34 | tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" | 44 | tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" |
35 | depends on MACH_PCM043 || MACH_PCA100 | 45 | depends on MACH_PCM043 || MACH_PCA100 |
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile index b67fc02a4ecc..d6d609ba7e24 100644 --- a/sound/soc/imx/Makefile +++ b/sound/soc/imx/Makefile | |||
@@ -10,8 +10,10 @@ obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o | |||
10 | # i.MX Machine Support | 10 | # i.MX Machine Support |
11 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o | 11 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o |
12 | snd-soc-phycore-ac97-objs := phycore-ac97.o | 12 | snd-soc-phycore-ac97-objs := phycore-ac97.o |
13 | snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o | ||
13 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o | 14 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o |
14 | 15 | ||
15 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o | 16 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o |
16 | obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o | 17 | obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o |
18 | obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o | ||
17 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o | 19 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o |
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c index 30894ea7f333..bc92ec620004 100644 --- a/sound/soc/imx/imx-ssi.c +++ b/sound/soc/imx/imx-ssi.c | |||
@@ -108,7 +108,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) | |||
108 | break; | 108 | break; |
109 | case SND_SOC_DAIFMT_DSP_B: | 109 | case SND_SOC_DAIFMT_DSP_B: |
110 | /* data on rising edge of bclk, frame high with data */ | 110 | /* data on rising edge of bclk, frame high with data */ |
111 | strcr |= SSI_STCR_TFSL; | 111 | strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0; |
112 | break; | 112 | break; |
113 | case SND_SOC_DAIFMT_DSP_A: | 113 | case SND_SOC_DAIFMT_DSP_A: |
114 | /* data on rising edge of bclk, frame high 1clk before data */ | 114 | /* data on rising edge of bclk, frame high 1clk before data */ |
@@ -656,6 +656,9 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
656 | ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; | 656 | ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0; |
657 | ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; | 657 | ssi->dma_params_tx.dma_addr = res->start + SSI_STX0; |
658 | 658 | ||
659 | ssi->dma_params_tx.burstsize = 4; | ||
660 | ssi->dma_params_rx.burstsize = 4; | ||
661 | |||
659 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); | 662 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0"); |
660 | if (res) | 663 | if (res) |
661 | ssi->dma_params_tx.dma = res->start; | 664 | ssi->dma_params_tx.dma = res->start; |
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c new file mode 100644 index 000000000000..054110b91d42 --- /dev/null +++ b/sound/soc/imx/mx27vis-aic32x4.c | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * mx27vis-aic32x4.c | ||
3 | * | ||
4 | * Copyright 2011 Vista Silicon S.L. | ||
5 | * | ||
6 | * Author: Javier Martin <javier.martin@vista-silicon.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||
21 | * MA 02110-1301, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/module.h> | ||
25 | #include <linux/moduleparam.h> | ||
26 | #include <linux/device.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <sound/core.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/soc.h> | ||
31 | #include <sound/soc-dapm.h> | ||
32 | #include <asm/mach-types.h> | ||
33 | #include <mach/audmux.h> | ||
34 | |||
35 | #include "../codecs/tlv320aic32x4.h" | ||
36 | #include "imx-ssi.h" | ||
37 | |||
38 | static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, | ||
39 | struct snd_pcm_hw_params *params) | ||
40 | { | ||
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
43 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
44 | int ret; | ||
45 | u32 dai_format; | ||
46 | |||
47 | dai_format = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF | | ||
48 | SND_SOC_DAIFMT_CBM_CFM; | ||
49 | |||
50 | /* set codec DAI configuration */ | ||
51 | snd_soc_dai_set_fmt(codec_dai, dai_format); | ||
52 | |||
53 | /* set cpu DAI configuration */ | ||
54 | snd_soc_dai_set_fmt(cpu_dai, dai_format); | ||
55 | |||
56 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | ||
57 | 25000000, SND_SOC_CLOCK_OUT); | ||
58 | if (ret) { | ||
59 | pr_err("%s: failed setting codec sysclk\n", __func__); | ||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, | ||
64 | SND_SOC_CLOCK_IN); | ||
65 | if (ret) { | ||
66 | pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n"); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static struct snd_soc_ops mx27vis_aic32x4_snd_ops = { | ||
74 | .hw_params = mx27vis_aic32x4_hw_params, | ||
75 | }; | ||
76 | |||
77 | static struct snd_soc_dai_link mx27vis_aic32x4_dai = { | ||
78 | .name = "tlv320aic32x4", | ||
79 | .stream_name = "TLV320AIC32X4", | ||
80 | .codec_dai_name = "tlv320aic32x4-hifi", | ||
81 | .platform_name = "imx-pcm-audio.0", | ||
82 | .codec_name = "tlv320aic32x4.0-0018", | ||
83 | .cpu_dai_name = "imx-ssi.0", | ||
84 | .ops = &mx27vis_aic32x4_snd_ops, | ||
85 | }; | ||
86 | |||
87 | static struct snd_soc_card mx27vis_aic32x4 = { | ||
88 | .name = "visstrim_m10-audio", | ||
89 | .dai_link = &mx27vis_aic32x4_dai, | ||
90 | .num_links = 1, | ||
91 | }; | ||
92 | |||
93 | static struct platform_device *mx27vis_aic32x4_snd_device; | ||
94 | |||
95 | static int __init mx27vis_aic32x4_init(void) | ||
96 | { | ||
97 | int ret; | ||
98 | |||
99 | mx27vis_aic32x4_snd_device = platform_device_alloc("soc-audio", -1); | ||
100 | if (!mx27vis_aic32x4_snd_device) | ||
101 | return -ENOMEM; | ||
102 | |||
103 | platform_set_drvdata(mx27vis_aic32x4_snd_device, &mx27vis_aic32x4); | ||
104 | ret = platform_device_add(mx27vis_aic32x4_snd_device); | ||
105 | |||
106 | if (ret) { | ||
107 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); | ||
108 | platform_device_put(mx27vis_aic32x4_snd_device); | ||
109 | } | ||
110 | |||
111 | /* Connect SSI0 as clock slave to SSI1 external pins */ | ||
112 | mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0, | ||
113 | MXC_AUDMUX_V1_PCR_SYN | | ||
114 | MXC_AUDMUX_V1_PCR_TFSDIR | | ||
115 | MXC_AUDMUX_V1_PCR_TCLKDIR | | ||
116 | MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | | ||
117 | MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) | ||
118 | ); | ||
119 | mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1, | ||
120 | MXC_AUDMUX_V1_PCR_SYN | | ||
121 | MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) | ||
122 | ); | ||
123 | |||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | static void __exit mx27vis_aic32x4_exit(void) | ||
128 | { | ||
129 | platform_device_unregister(mx27vis_aic32x4_snd_device); | ||
130 | } | ||
131 | |||
132 | module_init(mx27vis_aic32x4_init); | ||
133 | module_exit(mx27vis_aic32x4_exit); | ||
134 | |||
135 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); | ||
136 | MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim"); | ||
137 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/mid-x86/Kconfig b/sound/soc/mid-x86/Kconfig new file mode 100644 index 000000000000..29350428f1c2 --- /dev/null +++ b/sound/soc/mid-x86/Kconfig | |||
@@ -0,0 +1,14 @@ | |||
1 | config SND_MFLD_MACHINE | ||
2 | tristate "SOC Machine Audio driver for Intel Medfield MID platform" | ||
3 | depends on INTEL_SCU_IPC | ||
4 | depends on SND_INTEL_SST | ||
5 | select SND_SOC_SN95031 | ||
6 | select SND_SST_PLATFORM | ||
7 | help | ||
8 | This adds support for ASoC machine driver for Intel(R) MID Medfield platform | ||
9 | used as alsa device in audio substem in Intel(R) MID devices | ||
10 | Say Y if you have such a device | ||
11 | If unsure select "N". | ||
12 | |||
13 | config SND_SST_PLATFORM | ||
14 | tristate | ||
diff --git a/sound/soc/mid-x86/Makefile b/sound/soc/mid-x86/Makefile new file mode 100644 index 000000000000..639883339465 --- /dev/null +++ b/sound/soc/mid-x86/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | snd-soc-sst-platform-objs := sst_platform.o | ||
2 | snd-soc-mfld-machine-objs := mfld_machine.o | ||
3 | |||
4 | obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o | ||
5 | obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o | ||
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c new file mode 100644 index 000000000000..429aa1be2cff --- /dev/null +++ b/sound/soc/mid-x86/mfld_machine.c | |||
@@ -0,0 +1,452 @@ | |||
1 | /* | ||
2 | * mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform | ||
3 | * | ||
4 | * Copyright (C) 2010 Intel Corp | ||
5 | * Author: Vinod Koul <vinod.koul@intel.com> | ||
6 | * Author: Harsha Priya <priya.harsha@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program 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; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | */ | ||
24 | |||
25 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
26 | |||
27 | #include <linux/init.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/jack.h> | ||
35 | #include "../codecs/sn95031.h" | ||
36 | |||
37 | #define MID_MONO 1 | ||
38 | #define MID_STEREO 2 | ||
39 | #define MID_MAX_CAP 5 | ||
40 | #define MFLD_JACK_INSERT 0x04 | ||
41 | |||
42 | enum soc_mic_bias_zones { | ||
43 | MFLD_MV_START = 0, | ||
44 | /* mic bias volutage range for Headphones*/ | ||
45 | MFLD_MV_HP = 400, | ||
46 | /* mic bias volutage range for American Headset*/ | ||
47 | MFLD_MV_AM_HS = 650, | ||
48 | /* mic bias volutage range for Headset*/ | ||
49 | MFLD_MV_HS = 2000, | ||
50 | MFLD_MV_UNDEFINED, | ||
51 | }; | ||
52 | |||
53 | static unsigned int hs_switch; | ||
54 | static unsigned int lo_dac; | ||
55 | |||
56 | struct mfld_mc_private { | ||
57 | struct platform_device *socdev; | ||
58 | void __iomem *int_base; | ||
59 | struct snd_soc_codec *codec; | ||
60 | u8 interrupt_status; | ||
61 | }; | ||
62 | |||
63 | struct snd_soc_jack mfld_jack; | ||
64 | |||
65 | /*Headset jack detection DAPM pins */ | ||
66 | static struct snd_soc_jack_pin mfld_jack_pins[] = { | ||
67 | { | ||
68 | .pin = "Headphones", | ||
69 | .mask = SND_JACK_HEADPHONE, | ||
70 | }, | ||
71 | { | ||
72 | .pin = "AMIC1", | ||
73 | .mask = SND_JACK_MICROPHONE, | ||
74 | }, | ||
75 | }; | ||
76 | |||
77 | /* jack detection voltage zones */ | ||
78 | static struct snd_soc_jack_zone mfld_zones[] = { | ||
79 | {MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE}, | ||
80 | {MFLD_MV_AM_HS, MFLD_MV_HS, SND_JACK_HEADSET}, | ||
81 | }; | ||
82 | |||
83 | /* sound card controls */ | ||
84 | static const char *headset_switch_text[] = {"Earpiece", "Headset"}; | ||
85 | |||
86 | static const char *lo_text[] = {"Vibra", "Headset", "IHF", "None"}; | ||
87 | |||
88 | static const struct soc_enum headset_enum = | ||
89 | SOC_ENUM_SINGLE_EXT(2, headset_switch_text); | ||
90 | |||
91 | static const struct soc_enum lo_enum = | ||
92 | SOC_ENUM_SINGLE_EXT(4, lo_text); | ||
93 | |||
94 | static int headset_get_switch(struct snd_kcontrol *kcontrol, | ||
95 | struct snd_ctl_elem_value *ucontrol) | ||
96 | { | ||
97 | ucontrol->value.integer.value[0] = hs_switch; | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int headset_set_switch(struct snd_kcontrol *kcontrol, | ||
102 | struct snd_ctl_elem_value *ucontrol) | ||
103 | { | ||
104 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
105 | |||
106 | if (ucontrol->value.integer.value[0] == hs_switch) | ||
107 | return 0; | ||
108 | |||
109 | if (ucontrol->value.integer.value[0]) { | ||
110 | pr_debug("hs_set HS path\n"); | ||
111 | snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); | ||
112 | snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); | ||
113 | } else { | ||
114 | pr_debug("hs_set EP path\n"); | ||
115 | snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); | ||
116 | snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); | ||
117 | } | ||
118 | snd_soc_dapm_sync(&codec->dapm); | ||
119 | hs_switch = ucontrol->value.integer.value[0]; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static void lo_enable_out_pins(struct snd_soc_codec *codec) | ||
125 | { | ||
126 | snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL"); | ||
127 | snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR"); | ||
128 | snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL"); | ||
129 | snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR"); | ||
130 | snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT"); | ||
131 | snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT"); | ||
132 | if (hs_switch) { | ||
133 | snd_soc_dapm_enable_pin(&codec->dapm, "Headphones"); | ||
134 | snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); | ||
135 | } else { | ||
136 | snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); | ||
137 | snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT"); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | static int lo_get_switch(struct snd_kcontrol *kcontrol, | ||
142 | struct snd_ctl_elem_value *ucontrol) | ||
143 | { | ||
144 | ucontrol->value.integer.value[0] = lo_dac; | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int lo_set_switch(struct snd_kcontrol *kcontrol, | ||
149 | struct snd_ctl_elem_value *ucontrol) | ||
150 | { | ||
151 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
152 | |||
153 | if (ucontrol->value.integer.value[0] == lo_dac) | ||
154 | return 0; | ||
155 | |||
156 | /* we dont want to work with last state of lineout so just enable all | ||
157 | * pins and then disable pins not required | ||
158 | */ | ||
159 | lo_enable_out_pins(codec); | ||
160 | switch (ucontrol->value.integer.value[0]) { | ||
161 | case 0: | ||
162 | pr_debug("set vibra path\n"); | ||
163 | snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT"); | ||
164 | snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT"); | ||
165 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0); | ||
166 | break; | ||
167 | |||
168 | case 1: | ||
169 | pr_debug("set hs path\n"); | ||
170 | snd_soc_dapm_disable_pin(&codec->dapm, "Headphones"); | ||
171 | snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT"); | ||
172 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22); | ||
173 | break; | ||
174 | |||
175 | case 2: | ||
176 | pr_debug("set spkr path\n"); | ||
177 | snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL"); | ||
178 | snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR"); | ||
179 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44); | ||
180 | break; | ||
181 | |||
182 | case 3: | ||
183 | pr_debug("set null path\n"); | ||
184 | snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL"); | ||
185 | snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR"); | ||
186 | snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66); | ||
187 | break; | ||
188 | } | ||
189 | snd_soc_dapm_sync(&codec->dapm); | ||
190 | lo_dac = ucontrol->value.integer.value[0]; | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static const struct snd_kcontrol_new mfld_snd_controls[] = { | ||
195 | SOC_ENUM_EXT("Playback Switch", headset_enum, | ||
196 | headset_get_switch, headset_set_switch), | ||
197 | SOC_ENUM_EXT("Lineout Mux", lo_enum, | ||
198 | lo_get_switch, lo_set_switch), | ||
199 | }; | ||
200 | |||
201 | static const struct snd_soc_dapm_widget mfld_widgets[] = { | ||
202 | SND_SOC_DAPM_HP("Headphones", NULL), | ||
203 | SND_SOC_DAPM_MIC("Mic", NULL), | ||
204 | }; | ||
205 | |||
206 | static const struct snd_soc_dapm_route mfld_map[] = { | ||
207 | {"Headphones", NULL, "HPOUTR"}, | ||
208 | {"Headphones", NULL, "HPOUTL"}, | ||
209 | {"Mic", NULL, "AMIC1"}, | ||
210 | }; | ||
211 | |||
212 | static void mfld_jack_check(unsigned int intr_status) | ||
213 | { | ||
214 | struct mfld_jack_data jack_data; | ||
215 | |||
216 | jack_data.mfld_jack = &mfld_jack; | ||
217 | jack_data.intr_id = intr_status; | ||
218 | |||
219 | sn95031_jack_detection(&jack_data); | ||
220 | /* TODO: add american headset detection post gpiolib support */ | ||
221 | } | ||
222 | |||
223 | static int mfld_init(struct snd_soc_pcm_runtime *runtime) | ||
224 | { | ||
225 | struct snd_soc_codec *codec = runtime->codec; | ||
226 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
227 | int ret_val; | ||
228 | |||
229 | /* Add jack sense widgets */ | ||
230 | snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets)); | ||
231 | |||
232 | /* Set up the map */ | ||
233 | snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map)); | ||
234 | |||
235 | /* always connected */ | ||
236 | snd_soc_dapm_enable_pin(dapm, "Headphones"); | ||
237 | snd_soc_dapm_enable_pin(dapm, "Mic"); | ||
238 | snd_soc_dapm_sync(dapm); | ||
239 | |||
240 | ret_val = snd_soc_add_controls(codec, mfld_snd_controls, | ||
241 | ARRAY_SIZE(mfld_snd_controls)); | ||
242 | if (ret_val) { | ||
243 | pr_err("soc_add_controls failed %d", ret_val); | ||
244 | return ret_val; | ||
245 | } | ||
246 | /* default is earpiece pin, userspace sets it explcitly */ | ||
247 | snd_soc_dapm_disable_pin(dapm, "Headphones"); | ||
248 | /* default is lineout NC, userspace sets it explcitly */ | ||
249 | snd_soc_dapm_disable_pin(dapm, "LINEOUTL"); | ||
250 | snd_soc_dapm_disable_pin(dapm, "LINEOUTR"); | ||
251 | lo_dac = 3; | ||
252 | hs_switch = 0; | ||
253 | /* we dont use linein in this so set to NC */ | ||
254 | snd_soc_dapm_disable_pin(dapm, "LINEINL"); | ||
255 | snd_soc_dapm_disable_pin(dapm, "LINEINR"); | ||
256 | snd_soc_dapm_sync(dapm); | ||
257 | |||
258 | /* Headset and button jack detection */ | ||
259 | ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack", | ||
260 | SND_JACK_HEADSET | SND_JACK_BTN_0 | | ||
261 | SND_JACK_BTN_1, &mfld_jack); | ||
262 | if (ret_val) { | ||
263 | pr_err("jack creation failed\n"); | ||
264 | return ret_val; | ||
265 | } | ||
266 | |||
267 | ret_val = snd_soc_jack_add_pins(&mfld_jack, | ||
268 | ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins); | ||
269 | if (ret_val) { | ||
270 | pr_err("adding jack pins failed\n"); | ||
271 | return ret_val; | ||
272 | } | ||
273 | ret_val = snd_soc_jack_add_zones(&mfld_jack, | ||
274 | ARRAY_SIZE(mfld_zones), mfld_zones); | ||
275 | if (ret_val) { | ||
276 | pr_err("adding jack zones failed\n"); | ||
277 | return ret_val; | ||
278 | } | ||
279 | |||
280 | /* we want to check if anything is inserted at boot, | ||
281 | * so send a fake event to codec and it will read adc | ||
282 | * to find if anything is there or not */ | ||
283 | mfld_jack_check(MFLD_JACK_INSERT); | ||
284 | return ret_val; | ||
285 | } | ||
286 | |||
287 | struct snd_soc_dai_link mfld_msic_dailink[] = { | ||
288 | { | ||
289 | .name = "Medfield Headset", | ||
290 | .stream_name = "Headset", | ||
291 | .cpu_dai_name = "Headset-cpu-dai", | ||
292 | .codec_dai_name = "SN95031 Headset", | ||
293 | .codec_name = "sn95031", | ||
294 | .platform_name = "sst-platform", | ||
295 | .init = mfld_init, | ||
296 | }, | ||
297 | { | ||
298 | .name = "Medfield Speaker", | ||
299 | .stream_name = "Speaker", | ||
300 | .cpu_dai_name = "Speaker-cpu-dai", | ||
301 | .codec_dai_name = "SN95031 Speaker", | ||
302 | .codec_name = "sn95031", | ||
303 | .platform_name = "sst-platform", | ||
304 | .init = NULL, | ||
305 | }, | ||
306 | { | ||
307 | .name = "Medfield Vibra", | ||
308 | .stream_name = "Vibra1", | ||
309 | .cpu_dai_name = "Vibra1-cpu-dai", | ||
310 | .codec_dai_name = "SN95031 Vibra1", | ||
311 | .codec_name = "sn95031", | ||
312 | .platform_name = "sst-platform", | ||
313 | .init = NULL, | ||
314 | }, | ||
315 | { | ||
316 | .name = "Medfield Haptics", | ||
317 | .stream_name = "Vibra2", | ||
318 | .cpu_dai_name = "Vibra2-cpu-dai", | ||
319 | .codec_dai_name = "SN95031 Vibra2", | ||
320 | .codec_name = "sn95031", | ||
321 | .platform_name = "sst-platform", | ||
322 | .init = NULL, | ||
323 | }, | ||
324 | }; | ||
325 | |||
326 | /* SoC card */ | ||
327 | static struct snd_soc_card snd_soc_card_mfld = { | ||
328 | .name = "medfield_audio", | ||
329 | .dai_link = mfld_msic_dailink, | ||
330 | .num_links = ARRAY_SIZE(mfld_msic_dailink), | ||
331 | }; | ||
332 | |||
333 | static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev) | ||
334 | { | ||
335 | struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev; | ||
336 | |||
337 | memcpy_fromio(&mc_private->interrupt_status, | ||
338 | ((void *)(mc_private->int_base)), | ||
339 | sizeof(u8)); | ||
340 | return IRQ_WAKE_THREAD; | ||
341 | } | ||
342 | |||
343 | static irqreturn_t snd_mfld_jack_detection(int irq, void *data) | ||
344 | { | ||
345 | struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data; | ||
346 | |||
347 | if (mfld_jack.codec == NULL) | ||
348 | return IRQ_HANDLED; | ||
349 | mfld_jack_check(mc_drv_ctx->interrupt_status); | ||
350 | |||
351 | return IRQ_HANDLED; | ||
352 | } | ||
353 | |||
354 | static int __devinit snd_mfld_mc_probe(struct platform_device *pdev) | ||
355 | { | ||
356 | int ret_val = 0, irq; | ||
357 | struct mfld_mc_private *mc_drv_ctx; | ||
358 | struct resource *irq_mem; | ||
359 | |||
360 | pr_debug("snd_mfld_mc_probe called\n"); | ||
361 | |||
362 | /* retrive the irq number */ | ||
363 | irq = platform_get_irq(pdev, 0); | ||
364 | |||
365 | /* audio interrupt base of SRAM location where | ||
366 | * interrupts are stored by System FW */ | ||
367 | mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC); | ||
368 | if (!mc_drv_ctx) { | ||
369 | pr_err("allocation failed\n"); | ||
370 | return -ENOMEM; | ||
371 | } | ||
372 | |||
373 | irq_mem = platform_get_resource_byname( | ||
374 | pdev, IORESOURCE_MEM, "IRQ_BASE"); | ||
375 | if (!irq_mem) { | ||
376 | pr_err("no mem resource given\n"); | ||
377 | ret_val = -ENODEV; | ||
378 | goto unalloc; | ||
379 | } | ||
380 | mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start, | ||
381 | resource_size(irq_mem)); | ||
382 | if (!mc_drv_ctx->int_base) { | ||
383 | pr_err("Mapping of cache failed\n"); | ||
384 | ret_val = -ENOMEM; | ||
385 | goto unalloc; | ||
386 | } | ||
387 | /* register for interrupt */ | ||
388 | ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler, | ||
389 | snd_mfld_jack_detection, | ||
390 | IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx); | ||
391 | if (ret_val) { | ||
392 | pr_err("cannot register IRQ\n"); | ||
393 | goto unalloc; | ||
394 | } | ||
395 | /* register the soc card */ | ||
396 | snd_soc_card_mfld.dev = &pdev->dev; | ||
397 | ret_val = snd_soc_register_card(&snd_soc_card_mfld); | ||
398 | if (ret_val) { | ||
399 | pr_debug("snd_soc_register_card failed %d\n", ret_val); | ||
400 | goto freeirq; | ||
401 | } | ||
402 | platform_set_drvdata(pdev, mc_drv_ctx); | ||
403 | pr_debug("successfully exited probe\n"); | ||
404 | return ret_val; | ||
405 | |||
406 | freeirq: | ||
407 | free_irq(irq, mc_drv_ctx); | ||
408 | unalloc: | ||
409 | kfree(mc_drv_ctx); | ||
410 | return ret_val; | ||
411 | } | ||
412 | |||
413 | static int __devexit snd_mfld_mc_remove(struct platform_device *pdev) | ||
414 | { | ||
415 | struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev); | ||
416 | |||
417 | pr_debug("snd_mfld_mc_remove called\n"); | ||
418 | free_irq(platform_get_irq(pdev, 0), mc_drv_ctx); | ||
419 | snd_soc_unregister_card(&snd_soc_card_mfld); | ||
420 | kfree(mc_drv_ctx); | ||
421 | platform_set_drvdata(pdev, NULL); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | static struct platform_driver snd_mfld_mc_driver = { | ||
426 | .driver = { | ||
427 | .owner = THIS_MODULE, | ||
428 | .name = "msic_audio", | ||
429 | }, | ||
430 | .probe = snd_mfld_mc_probe, | ||
431 | .remove = __devexit_p(snd_mfld_mc_remove), | ||
432 | }; | ||
433 | |||
434 | static int __init snd_mfld_driver_init(void) | ||
435 | { | ||
436 | pr_debug("snd_mfld_driver_init called\n"); | ||
437 | return platform_driver_register(&snd_mfld_mc_driver); | ||
438 | } | ||
439 | module_init(snd_mfld_driver_init); | ||
440 | |||
441 | static void __exit snd_mfld_driver_exit(void) | ||
442 | { | ||
443 | pr_debug("snd_mfld_driver_exit called\n"); | ||
444 | platform_driver_unregister(&snd_mfld_mc_driver); | ||
445 | } | ||
446 | module_exit(snd_mfld_driver_exit); | ||
447 | |||
448 | MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver"); | ||
449 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); | ||
450 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); | ||
451 | MODULE_LICENSE("GPL v2"); | ||
452 | MODULE_ALIAS("platform:msic-audio"); | ||
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c new file mode 100644 index 000000000000..ee2c22475a76 --- /dev/null +++ b/sound/soc/mid-x86/sst_platform.c | |||
@@ -0,0 +1,474 @@ | |||
1 | /* | ||
2 | * sst_platform.c - Intel MID Platform driver | ||
3 | * | ||
4 | * Copyright (C) 2010 Intel Corp | ||
5 | * Author: Vinod Koul <vinod.koul@intel.com> | ||
6 | * Author: Harsha Priya <priya.harsha@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program 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; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | * | ||
24 | * | ||
25 | */ | ||
26 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
27 | |||
28 | #include <linux/slab.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include "../../../drivers/staging/intel_sst/intel_sst_ioctl.h" | ||
35 | #include "../../../drivers/staging/intel_sst/intel_sst.h" | ||
36 | #include "sst_platform.h" | ||
37 | |||
38 | static struct snd_pcm_hardware sst_platform_pcm_hw = { | ||
39 | .info = (SNDRV_PCM_INFO_INTERLEAVED | | ||
40 | SNDRV_PCM_INFO_DOUBLE | | ||
41 | SNDRV_PCM_INFO_PAUSE | | ||
42 | SNDRV_PCM_INFO_RESUME | | ||
43 | SNDRV_PCM_INFO_MMAP| | ||
44 | SNDRV_PCM_INFO_MMAP_VALID | | ||
45 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
46 | SNDRV_PCM_INFO_SYNC_START), | ||
47 | .formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 | | ||
48 | SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 | | ||
49 | SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32), | ||
50 | .rates = (SNDRV_PCM_RATE_8000| | ||
51 | SNDRV_PCM_RATE_44100 | | ||
52 | SNDRV_PCM_RATE_48000), | ||
53 | .rate_min = SST_MIN_RATE, | ||
54 | .rate_max = SST_MAX_RATE, | ||
55 | .channels_min = SST_MIN_CHANNEL, | ||
56 | .channels_max = SST_MAX_CHANNEL, | ||
57 | .buffer_bytes_max = SST_MAX_BUFFER, | ||
58 | .period_bytes_min = SST_MIN_PERIOD_BYTES, | ||
59 | .period_bytes_max = SST_MAX_PERIOD_BYTES, | ||
60 | .periods_min = SST_MIN_PERIODS, | ||
61 | .periods_max = SST_MAX_PERIODS, | ||
62 | .fifo_size = SST_FIFO_SIZE, | ||
63 | }; | ||
64 | |||
65 | /* MFLD - MSIC */ | ||
66 | struct snd_soc_dai_driver sst_platform_dai[] = { | ||
67 | { | ||
68 | .name = "Headset-cpu-dai", | ||
69 | .id = 0, | ||
70 | .playback = { | ||
71 | .channels_min = SST_STEREO, | ||
72 | .channels_max = SST_STEREO, | ||
73 | .rates = SNDRV_PCM_RATE_48000, | ||
74 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
75 | }, | ||
76 | .capture = { | ||
77 | .channels_min = 1, | ||
78 | .channels_max = 5, | ||
79 | .rates = SNDRV_PCM_RATE_48000, | ||
80 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
81 | }, | ||
82 | }, | ||
83 | { | ||
84 | .name = "Speaker-cpu-dai", | ||
85 | .id = 1, | ||
86 | .playback = { | ||
87 | .channels_min = SST_MONO, | ||
88 | .channels_max = SST_STEREO, | ||
89 | .rates = SNDRV_PCM_RATE_48000, | ||
90 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
91 | }, | ||
92 | }, | ||
93 | { | ||
94 | .name = "Vibra1-cpu-dai", | ||
95 | .id = 2, | ||
96 | .playback = { | ||
97 | .channels_min = SST_MONO, | ||
98 | .channels_max = SST_MONO, | ||
99 | .rates = SNDRV_PCM_RATE_48000, | ||
100 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
101 | }, | ||
102 | }, | ||
103 | { | ||
104 | .name = "Vibra2-cpu-dai", | ||
105 | .id = 3, | ||
106 | .playback = { | ||
107 | .channels_min = SST_MONO, | ||
108 | .channels_max = SST_STEREO, | ||
109 | .rates = SNDRV_PCM_RATE_48000, | ||
110 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
111 | }, | ||
112 | }, | ||
113 | }; | ||
114 | |||
115 | /* helper functions */ | ||
116 | static inline void sst_set_stream_status(struct sst_runtime_stream *stream, | ||
117 | int state) | ||
118 | { | ||
119 | spin_lock(&stream->status_lock); | ||
120 | stream->stream_status = state; | ||
121 | spin_unlock(&stream->status_lock); | ||
122 | } | ||
123 | |||
124 | static inline int sst_get_stream_status(struct sst_runtime_stream *stream) | ||
125 | { | ||
126 | int state; | ||
127 | |||
128 | spin_lock(&stream->status_lock); | ||
129 | state = stream->stream_status; | ||
130 | spin_unlock(&stream->status_lock); | ||
131 | return state; | ||
132 | } | ||
133 | |||
134 | static void sst_fill_pcm_params(struct snd_pcm_substream *substream, | ||
135 | struct snd_sst_stream_params *param) | ||
136 | { | ||
137 | |||
138 | param->uc.pcm_params.codec = SST_CODEC_TYPE_PCM; | ||
139 | param->uc.pcm_params.num_chan = (u8) substream->runtime->channels; | ||
140 | param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits; | ||
141 | param->uc.pcm_params.reserved = 0; | ||
142 | param->uc.pcm_params.sfreq = substream->runtime->rate; | ||
143 | param->uc.pcm_params.ring_buffer_size = | ||
144 | snd_pcm_lib_buffer_bytes(substream); | ||
145 | param->uc.pcm_params.period_count = substream->runtime->period_size; | ||
146 | param->uc.pcm_params.ring_buffer_addr = | ||
147 | virt_to_phys(substream->dma_buffer.area); | ||
148 | pr_debug("period_cnt = %d\n", param->uc.pcm_params.period_count); | ||
149 | pr_debug("sfreq= %d, wd_sz = %d\n", | ||
150 | param->uc.pcm_params.sfreq, param->uc.pcm_params.pcm_wd_sz); | ||
151 | } | ||
152 | |||
153 | static int sst_platform_alloc_stream(struct snd_pcm_substream *substream) | ||
154 | { | ||
155 | struct sst_runtime_stream *stream = | ||
156 | substream->runtime->private_data; | ||
157 | struct snd_sst_stream_params param = {{{0,},},}; | ||
158 | struct snd_sst_params str_params = {0}; | ||
159 | int ret_val; | ||
160 | |||
161 | /* set codec params and inform SST driver the same */ | ||
162 | sst_fill_pcm_params(substream, ¶m); | ||
163 | substream->runtime->dma_area = substream->dma_buffer.area; | ||
164 | str_params.sparams = param; | ||
165 | str_params.codec = param.uc.pcm_params.codec; | ||
166 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
167 | str_params.ops = STREAM_OPS_PLAYBACK; | ||
168 | str_params.device_type = substream->pcm->device + 1; | ||
169 | pr_debug("Playbck stream,Device %d\n", | ||
170 | substream->pcm->device); | ||
171 | } else { | ||
172 | str_params.ops = STREAM_OPS_CAPTURE; | ||
173 | str_params.device_type = SND_SST_DEVICE_CAPTURE; | ||
174 | pr_debug("Capture stream,Device %d\n", | ||
175 | substream->pcm->device); | ||
176 | } | ||
177 | ret_val = stream->sstdrv_ops->pcm_control->open(&str_params); | ||
178 | pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val); | ||
179 | if (ret_val < 0) | ||
180 | return ret_val; | ||
181 | |||
182 | stream->stream_info.str_id = ret_val; | ||
183 | pr_debug("str id : %d\n", stream->stream_info.str_id); | ||
184 | return ret_val; | ||
185 | } | ||
186 | |||
187 | static void sst_period_elapsed(void *mad_substream) | ||
188 | { | ||
189 | struct snd_pcm_substream *substream = mad_substream; | ||
190 | struct sst_runtime_stream *stream; | ||
191 | int status; | ||
192 | |||
193 | if (!substream || !substream->runtime) | ||
194 | return; | ||
195 | stream = substream->runtime->private_data; | ||
196 | if (!stream) | ||
197 | return; | ||
198 | status = sst_get_stream_status(stream); | ||
199 | if (status != SST_PLATFORM_RUNNING) | ||
200 | return; | ||
201 | snd_pcm_period_elapsed(substream); | ||
202 | } | ||
203 | |||
204 | static int sst_platform_init_stream(struct snd_pcm_substream *substream) | ||
205 | { | ||
206 | struct sst_runtime_stream *stream = | ||
207 | substream->runtime->private_data; | ||
208 | int ret_val; | ||
209 | |||
210 | pr_debug("setting buffer ptr param\n"); | ||
211 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | ||
212 | stream->stream_info.period_elapsed = sst_period_elapsed; | ||
213 | stream->stream_info.mad_substream = substream; | ||
214 | stream->stream_info.buffer_ptr = 0; | ||
215 | stream->stream_info.sfreq = substream->runtime->rate; | ||
216 | ret_val = stream->sstdrv_ops->pcm_control->device_control( | ||
217 | SST_SND_STREAM_INIT, &stream->stream_info); | ||
218 | if (ret_val) | ||
219 | pr_err("control_set ret error %d\n", ret_val); | ||
220 | return ret_val; | ||
221 | |||
222 | } | ||
223 | /* end -- helper functions */ | ||
224 | |||
225 | static int sst_platform_open(struct snd_pcm_substream *substream) | ||
226 | { | ||
227 | struct snd_pcm_runtime *runtime; | ||
228 | struct sst_runtime_stream *stream; | ||
229 | int ret_val = 0; | ||
230 | |||
231 | pr_debug("sst_platform_open called\n"); | ||
232 | runtime = substream->runtime; | ||
233 | runtime->hw = sst_platform_pcm_hw; | ||
234 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | ||
235 | if (!stream) | ||
236 | return -ENOMEM; | ||
237 | spin_lock_init(&stream->status_lock); | ||
238 | stream->stream_info.str_id = 0; | ||
239 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | ||
240 | stream->stream_info.mad_substream = substream; | ||
241 | /* allocate memory for SST API set */ | ||
242 | stream->sstdrv_ops = kzalloc(sizeof(*stream->sstdrv_ops), | ||
243 | GFP_KERNEL); | ||
244 | if (!stream->sstdrv_ops) { | ||
245 | pr_err("sst: mem allocation for ops fail\n"); | ||
246 | kfree(stream); | ||
247 | return -ENOMEM; | ||
248 | } | ||
249 | stream->sstdrv_ops->vendor_id = MSIC_VENDOR_ID; | ||
250 | /* registering with SST driver to get access to SST APIs to use */ | ||
251 | ret_val = register_sst_card(stream->sstdrv_ops); | ||
252 | if (ret_val) { | ||
253 | pr_err("sst: sst card registration failed\n"); | ||
254 | return ret_val; | ||
255 | } | ||
256 | runtime->private_data = stream; | ||
257 | return snd_pcm_hw_constraint_integer(runtime, | ||
258 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
259 | } | ||
260 | |||
261 | static int sst_platform_close(struct snd_pcm_substream *substream) | ||
262 | { | ||
263 | struct sst_runtime_stream *stream; | ||
264 | int ret_val = 0, str_id; | ||
265 | |||
266 | pr_debug("sst_platform_close called\n"); | ||
267 | stream = substream->runtime->private_data; | ||
268 | str_id = stream->stream_info.str_id; | ||
269 | if (str_id) | ||
270 | ret_val = stream->sstdrv_ops->pcm_control->close(str_id); | ||
271 | kfree(stream->sstdrv_ops); | ||
272 | kfree(stream); | ||
273 | return ret_val; | ||
274 | } | ||
275 | |||
276 | static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream) | ||
277 | { | ||
278 | struct sst_runtime_stream *stream; | ||
279 | int ret_val = 0, str_id; | ||
280 | |||
281 | pr_debug("sst_platform_pcm_prepare called\n"); | ||
282 | stream = substream->runtime->private_data; | ||
283 | str_id = stream->stream_info.str_id; | ||
284 | if (stream->stream_info.str_id) { | ||
285 | ret_val = stream->sstdrv_ops->pcm_control->device_control( | ||
286 | SST_SND_DROP, &str_id); | ||
287 | return ret_val; | ||
288 | } | ||
289 | |||
290 | ret_val = sst_platform_alloc_stream(substream); | ||
291 | if (ret_val < 0) | ||
292 | return ret_val; | ||
293 | snprintf(substream->pcm->id, sizeof(substream->pcm->id), | ||
294 | "%d", stream->stream_info.str_id); | ||
295 | |||
296 | ret_val = sst_platform_init_stream(substream); | ||
297 | if (ret_val) | ||
298 | return ret_val; | ||
299 | substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER; | ||
300 | return ret_val; | ||
301 | } | ||
302 | |||
303 | static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream, | ||
304 | int cmd) | ||
305 | { | ||
306 | int ret_val = 0, str_id; | ||
307 | struct sst_runtime_stream *stream; | ||
308 | int str_cmd, status; | ||
309 | |||
310 | pr_debug("sst_platform_pcm_trigger called\n"); | ||
311 | stream = substream->runtime->private_data; | ||
312 | str_id = stream->stream_info.str_id; | ||
313 | switch (cmd) { | ||
314 | case SNDRV_PCM_TRIGGER_START: | ||
315 | pr_debug("sst: Trigger Start\n"); | ||
316 | str_cmd = SST_SND_START; | ||
317 | status = SST_PLATFORM_RUNNING; | ||
318 | stream->stream_info.mad_substream = substream; | ||
319 | break; | ||
320 | case SNDRV_PCM_TRIGGER_STOP: | ||
321 | pr_debug("sst: in stop\n"); | ||
322 | str_cmd = SST_SND_DROP; | ||
323 | status = SST_PLATFORM_DROPPED; | ||
324 | break; | ||
325 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
326 | pr_debug("sst: in pause\n"); | ||
327 | str_cmd = SST_SND_PAUSE; | ||
328 | status = SST_PLATFORM_PAUSED; | ||
329 | break; | ||
330 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
331 | pr_debug("sst: in pause release\n"); | ||
332 | str_cmd = SST_SND_RESUME; | ||
333 | status = SST_PLATFORM_RUNNING; | ||
334 | break; | ||
335 | default: | ||
336 | return -EINVAL; | ||
337 | } | ||
338 | ret_val = stream->sstdrv_ops->pcm_control->device_control(str_cmd, | ||
339 | &str_id); | ||
340 | if (!ret_val) | ||
341 | sst_set_stream_status(stream, status); | ||
342 | |||
343 | return ret_val; | ||
344 | } | ||
345 | |||
346 | |||
347 | static snd_pcm_uframes_t sst_platform_pcm_pointer | ||
348 | (struct snd_pcm_substream *substream) | ||
349 | { | ||
350 | struct sst_runtime_stream *stream; | ||
351 | int ret_val, status; | ||
352 | struct pcm_stream_info *str_info; | ||
353 | |||
354 | stream = substream->runtime->private_data; | ||
355 | status = sst_get_stream_status(stream); | ||
356 | if (status == SST_PLATFORM_INIT) | ||
357 | return 0; | ||
358 | str_info = &stream->stream_info; | ||
359 | ret_val = stream->sstdrv_ops->pcm_control->device_control( | ||
360 | SST_SND_BUFFER_POINTER, str_info); | ||
361 | if (ret_val) { | ||
362 | pr_err("sst: error code = %d\n", ret_val); | ||
363 | return ret_val; | ||
364 | } | ||
365 | return stream->stream_info.buffer_ptr; | ||
366 | } | ||
367 | |||
368 | static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream, | ||
369 | struct snd_pcm_hw_params *params) | ||
370 | { | ||
371 | snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); | ||
372 | memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); | ||
373 | |||
374 | return 0; | ||
375 | } | ||
376 | |||
377 | static struct snd_pcm_ops sst_platform_ops = { | ||
378 | .open = sst_platform_open, | ||
379 | .close = sst_platform_close, | ||
380 | .ioctl = snd_pcm_lib_ioctl, | ||
381 | .prepare = sst_platform_pcm_prepare, | ||
382 | .trigger = sst_platform_pcm_trigger, | ||
383 | .pointer = sst_platform_pcm_pointer, | ||
384 | .hw_params = sst_platform_pcm_hw_params, | ||
385 | }; | ||
386 | |||
387 | static void sst_pcm_free(struct snd_pcm *pcm) | ||
388 | { | ||
389 | pr_debug("sst_pcm_free called\n"); | ||
390 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
391 | } | ||
392 | |||
393 | int sst_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, | ||
394 | struct snd_pcm *pcm) | ||
395 | { | ||
396 | int retval = 0; | ||
397 | |||
398 | pr_debug("sst_pcm_new called\n"); | ||
399 | if (dai->driver->playback.channels_min || | ||
400 | dai->driver->capture.channels_min) { | ||
401 | retval = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
402 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
403 | snd_dma_continuous_data(GFP_KERNEL), | ||
404 | SST_MIN_BUFFER, SST_MAX_BUFFER); | ||
405 | if (retval) { | ||
406 | pr_err("dma buffer allocationf fail\n"); | ||
407 | return retval; | ||
408 | } | ||
409 | } | ||
410 | return retval; | ||
411 | } | ||
412 | struct snd_soc_platform_driver sst_soc_platform_drv = { | ||
413 | .ops = &sst_platform_ops, | ||
414 | .pcm_new = sst_pcm_new, | ||
415 | .pcm_free = sst_pcm_free, | ||
416 | }; | ||
417 | |||
418 | static int sst_platform_probe(struct platform_device *pdev) | ||
419 | { | ||
420 | int ret; | ||
421 | |||
422 | pr_debug("sst_platform_probe called\n"); | ||
423 | ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv); | ||
424 | if (ret) { | ||
425 | pr_err("registering soc platform failed\n"); | ||
426 | return ret; | ||
427 | } | ||
428 | |||
429 | ret = snd_soc_register_dais(&pdev->dev, | ||
430 | sst_platform_dai, ARRAY_SIZE(sst_platform_dai)); | ||
431 | if (ret) { | ||
432 | pr_err("registering cpu dais failed\n"); | ||
433 | snd_soc_unregister_platform(&pdev->dev); | ||
434 | } | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | static int sst_platform_remove(struct platform_device *pdev) | ||
439 | { | ||
440 | |||
441 | snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai)); | ||
442 | snd_soc_unregister_platform(&pdev->dev); | ||
443 | pr_debug("sst_platform_remove sucess\n"); | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | static struct platform_driver sst_platform_driver = { | ||
448 | .driver = { | ||
449 | .name = "sst-platform", | ||
450 | .owner = THIS_MODULE, | ||
451 | }, | ||
452 | .probe = sst_platform_probe, | ||
453 | .remove = sst_platform_remove, | ||
454 | }; | ||
455 | |||
456 | static int __init sst_soc_platform_init(void) | ||
457 | { | ||
458 | pr_debug("sst_soc_platform_init called\n"); | ||
459 | return platform_driver_register(&sst_platform_driver); | ||
460 | } | ||
461 | module_init(sst_soc_platform_init); | ||
462 | |||
463 | static void __exit sst_soc_platform_exit(void) | ||
464 | { | ||
465 | platform_driver_unregister(&sst_platform_driver); | ||
466 | pr_debug("sst_soc_platform_exit sucess\n"); | ||
467 | } | ||
468 | module_exit(sst_soc_platform_exit); | ||
469 | |||
470 | MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver"); | ||
471 | MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>"); | ||
472 | MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>"); | ||
473 | MODULE_LICENSE("GPL v2"); | ||
474 | MODULE_ALIAS("platform:sst-platform"); | ||
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h new file mode 100644 index 000000000000..df370286694f --- /dev/null +++ b/sound/soc/mid-x86/sst_platform.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * sst_platform.h - Intel MID Platform driver header file | ||
3 | * | ||
4 | * Copyright (C) 2010 Intel Corp | ||
5 | * Author: Vinod Koul <vinod.koul@intel.com> | ||
6 | * Author: Harsha Priya <priya.harsha@intel.com> | ||
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
8 | * | ||
9 | * This program 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; version 2 of the License. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
21 | * | ||
22 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
23 | * | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #ifndef __SST_PLATFORMDRV_H__ | ||
28 | #define __SST_PLATFORMDRV_H__ | ||
29 | |||
30 | #define SST_MONO 1 | ||
31 | #define SST_STEREO 2 | ||
32 | #define SST_MAX_CAP 5 | ||
33 | |||
34 | #define SST_MIN_RATE 8000 | ||
35 | #define SST_MAX_RATE 48000 | ||
36 | #define SST_MIN_CHANNEL 1 | ||
37 | #define SST_MAX_CHANNEL 5 | ||
38 | #define SST_MAX_BUFFER (800*1024) | ||
39 | #define SST_MIN_BUFFER (800*1024) | ||
40 | #define SST_MIN_PERIOD_BYTES 32 | ||
41 | #define SST_MAX_PERIOD_BYTES SST_MAX_BUFFER | ||
42 | #define SST_MIN_PERIODS 2 | ||
43 | #define SST_MAX_PERIODS (1024*2) | ||
44 | #define SST_FIFO_SIZE 0 | ||
45 | #define SST_CARD_NAMES "intel_mid_card" | ||
46 | #define MSIC_VENDOR_ID 3 | ||
47 | |||
48 | struct sst_runtime_stream { | ||
49 | int stream_status; | ||
50 | struct pcm_stream_info stream_info; | ||
51 | struct intel_sst_card_ops *sstdrv_ops; | ||
52 | spinlock_t status_lock; | ||
53 | }; | ||
54 | |||
55 | enum sst_drv_status { | ||
56 | SST_PLATFORM_INIT = 1, | ||
57 | SST_PLATFORM_STARTED, | ||
58 | SST_PLATFORM_RUNNING, | ||
59 | SST_PLATFORM_PAUSED, | ||
60 | SST_PLATFORM_DROPPED, | ||
61 | }; | ||
62 | |||
63 | #endif | ||
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index a088db6d5091..b5922984eac6 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -24,6 +24,7 @@ config SND_OMAP_SOC_RX51 | |||
24 | select OMAP_MCBSP | 24 | select OMAP_MCBSP |
25 | select SND_OMAP_SOC_MCBSP | 25 | select SND_OMAP_SOC_MCBSP |
26 | select SND_SOC_TLV320AIC3X | 26 | select SND_SOC_TLV320AIC3X |
27 | select SND_SOC_TPA6130A2 | ||
27 | help | 28 | help |
28 | Say Y if you want to add support for SoC audio on Nokia RX-51 | 29 | Say Y if you want to add support for SoC audio on Nokia RX-51 |
29 | hardware. This is also known as Nokia N900 product. | 30 | hardware. This is also known as Nokia N900 product. |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c index 09fb0df8d416..d0986220eff9 100644 --- a/sound/soc/omap/rx51.c +++ b/sound/soc/omap/rx51.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
32 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
33 | #include <plat/mcbsp.h> | 33 | #include <plat/mcbsp.h> |
34 | #include "../codecs/tpa6130a2.h" | ||
34 | 35 | ||
35 | #include <asm/mach-types.h> | 36 | #include <asm/mach-types.h> |
36 | 37 | ||
@@ -39,6 +40,7 @@ | |||
39 | 40 | ||
40 | #define RX51_TVOUT_SEL_GPIO 40 | 41 | #define RX51_TVOUT_SEL_GPIO 40 |
41 | #define RX51_JACK_DETECT_GPIO 177 | 42 | #define RX51_JACK_DETECT_GPIO 177 |
43 | #define RX51_ECI_SW_GPIO 182 | ||
42 | /* | 44 | /* |
43 | * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This | 45 | * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This |
44 | * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c | 46 | * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c |
@@ -47,7 +49,9 @@ | |||
47 | 49 | ||
48 | enum { | 50 | enum { |
49 | RX51_JACK_DISABLED, | 51 | RX51_JACK_DISABLED, |
50 | RX51_JACK_TVOUT, /* tv-out */ | 52 | RX51_JACK_TVOUT, /* tv-out with stereo output */ |
53 | RX51_JACK_HP, /* headphone: stereo output, no mic */ | ||
54 | RX51_JACK_HS, /* headset: stereo output with mic */ | ||
51 | }; | 55 | }; |
52 | 56 | ||
53 | static int rx51_spk_func; | 57 | static int rx51_spk_func; |
@@ -57,6 +61,19 @@ static int rx51_jack_func; | |||
57 | static void rx51_ext_control(struct snd_soc_codec *codec) | 61 | static void rx51_ext_control(struct snd_soc_codec *codec) |
58 | { | 62 | { |
59 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 63 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
64 | int hp = 0, hs = 0, tvout = 0; | ||
65 | |||
66 | switch (rx51_jack_func) { | ||
67 | case RX51_JACK_TVOUT: | ||
68 | tvout = 1; | ||
69 | hp = 1; | ||
70 | break; | ||
71 | case RX51_JACK_HS: | ||
72 | hs = 1; | ||
73 | case RX51_JACK_HP: | ||
74 | hp = 1; | ||
75 | break; | ||
76 | } | ||
60 | 77 | ||
61 | if (rx51_spk_func) | 78 | if (rx51_spk_func) |
62 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); | 79 | snd_soc_dapm_enable_pin(dapm, "Ext Spk"); |
@@ -66,9 +83,16 @@ static void rx51_ext_control(struct snd_soc_codec *codec) | |||
66 | snd_soc_dapm_enable_pin(dapm, "DMic"); | 83 | snd_soc_dapm_enable_pin(dapm, "DMic"); |
67 | else | 84 | else |
68 | snd_soc_dapm_disable_pin(dapm, "DMic"); | 85 | snd_soc_dapm_disable_pin(dapm, "DMic"); |
86 | if (hp) | ||
87 | snd_soc_dapm_enable_pin(dapm, "Headphone Jack"); | ||
88 | else | ||
89 | snd_soc_dapm_disable_pin(dapm, "Headphone Jack"); | ||
90 | if (hs) | ||
91 | snd_soc_dapm_enable_pin(dapm, "HS Mic"); | ||
92 | else | ||
93 | snd_soc_dapm_disable_pin(dapm, "HS Mic"); | ||
69 | 94 | ||
70 | gpio_set_value(RX51_TVOUT_SEL_GPIO, | 95 | gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout); |
71 | rx51_jack_func == RX51_JACK_TVOUT); | ||
72 | 96 | ||
73 | snd_soc_dapm_sync(dapm); | 97 | snd_soc_dapm_sync(dapm); |
74 | } | 98 | } |
@@ -153,6 +177,19 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w, | |||
153 | return 0; | 177 | return 0; |
154 | } | 178 | } |
155 | 179 | ||
180 | static int rx51_hp_event(struct snd_soc_dapm_widget *w, | ||
181 | struct snd_kcontrol *k, int event) | ||
182 | { | ||
183 | struct snd_soc_codec *codec = w->dapm->codec; | ||
184 | |||
185 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
186 | tpa6130a2_stereo_enable(codec, 1); | ||
187 | else | ||
188 | tpa6130a2_stereo_enable(codec, 0); | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
156 | static int rx51_get_input(struct snd_kcontrol *kcontrol, | 193 | static int rx51_get_input(struct snd_kcontrol *kcontrol, |
157 | struct snd_ctl_elem_value *ucontrol) | 194 | struct snd_ctl_elem_value *ucontrol) |
158 | { | 195 | { |
@@ -203,7 +240,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { | |||
203 | { | 240 | { |
204 | .gpio = RX51_JACK_DETECT_GPIO, | 241 | .gpio = RX51_JACK_DETECT_GPIO, |
205 | .name = "avdet-gpio", | 242 | .name = "avdet-gpio", |
206 | .report = SND_JACK_VIDEOOUT, | 243 | .report = SND_JACK_HEADSET, |
207 | .invert = 1, | 244 | .invert = 1, |
208 | .debounce_time = 200, | 245 | .debounce_time = 200, |
209 | }, | 246 | }, |
@@ -212,19 +249,38 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = { | |||
212 | static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { | 249 | static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { |
213 | SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), | 250 | SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), |
214 | SND_SOC_DAPM_MIC("DMic", NULL), | 251 | SND_SOC_DAPM_MIC("DMic", NULL), |
252 | SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event), | ||
253 | SND_SOC_DAPM_MIC("HS Mic", NULL), | ||
254 | SND_SOC_DAPM_LINE("FM Transmitter", NULL), | ||
255 | }; | ||
256 | |||
257 | static const struct snd_soc_dapm_widget aic34_dapm_widgetsb[] = { | ||
258 | SND_SOC_DAPM_SPK("Earphone", NULL), | ||
215 | }; | 259 | }; |
216 | 260 | ||
217 | static const struct snd_soc_dapm_route audio_map[] = { | 261 | static const struct snd_soc_dapm_route audio_map[] = { |
218 | {"Ext Spk", NULL, "HPLOUT"}, | 262 | {"Ext Spk", NULL, "HPLOUT"}, |
219 | {"Ext Spk", NULL, "HPROUT"}, | 263 | {"Ext Spk", NULL, "HPROUT"}, |
264 | {"Headphone Jack", NULL, "LLOUT"}, | ||
265 | {"Headphone Jack", NULL, "RLOUT"}, | ||
266 | {"FM Transmitter", NULL, "LLOUT"}, | ||
267 | {"FM Transmitter", NULL, "RLOUT"}, | ||
220 | 268 | ||
221 | {"DMic Rate 64", NULL, "Mic Bias 2V"}, | 269 | {"DMic Rate 64", NULL, "Mic Bias 2V"}, |
222 | {"Mic Bias 2V", NULL, "DMic"}, | 270 | {"Mic Bias 2V", NULL, "DMic"}, |
223 | }; | 271 | }; |
224 | 272 | ||
273 | static const struct snd_soc_dapm_route audio_mapb[] = { | ||
274 | {"b LINE2R", NULL, "MONO_LOUT"}, | ||
275 | {"Earphone", NULL, "b HPLOUT"}, | ||
276 | |||
277 | {"LINE1L", NULL, "b Mic Bias 2.5V"}, | ||
278 | {"b Mic Bias 2.5V", NULL, "HS Mic"} | ||
279 | }; | ||
280 | |||
225 | static const char *spk_function[] = {"Off", "On"}; | 281 | static const char *spk_function[] = {"Off", "On"}; |
226 | static const char *input_function[] = {"ADC", "Digital Mic"}; | 282 | static const char *input_function[] = {"ADC", "Digital Mic"}; |
227 | static const char *jack_function[] = {"Off", "TV-OUT"}; | 283 | static const char *jack_function[] = {"Off", "TV-OUT", "Headphone", "Headset"}; |
228 | 284 | ||
229 | static const struct soc_enum rx51_enum[] = { | 285 | static const struct soc_enum rx51_enum[] = { |
230 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), | 286 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), |
@@ -239,6 +295,11 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = { | |||
239 | rx51_get_input, rx51_set_input), | 295 | rx51_get_input, rx51_set_input), |
240 | SOC_ENUM_EXT("Jack Function", rx51_enum[2], | 296 | SOC_ENUM_EXT("Jack Function", rx51_enum[2], |
241 | rx51_get_jack, rx51_set_jack), | 297 | rx51_get_jack, rx51_set_jack), |
298 | SOC_DAPM_PIN_SWITCH("FM Transmitter"), | ||
299 | }; | ||
300 | |||
301 | static const struct snd_kcontrol_new aic34_rx51_controlsb[] = { | ||
302 | SOC_DAPM_PIN_SWITCH("Earphone"), | ||
242 | }; | 303 | }; |
243 | 304 | ||
244 | static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) | 305 | static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) |
@@ -265,11 +326,21 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) | |||
265 | /* Set up RX-51 specific audio path audio_map */ | 326 | /* Set up RX-51 specific audio path audio_map */ |
266 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | 327 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); |
267 | 328 | ||
329 | err = tpa6130a2_add_controls(codec); | ||
330 | if (err < 0) | ||
331 | return err; | ||
332 | snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42); | ||
333 | |||
334 | err = omap_mcbsp_st_add_controls(codec, 1); | ||
335 | if (err < 0) | ||
336 | return err; | ||
337 | |||
268 | snd_soc_dapm_sync(dapm); | 338 | snd_soc_dapm_sync(dapm); |
269 | 339 | ||
270 | /* AV jack detection */ | 340 | /* AV jack detection */ |
271 | err = snd_soc_jack_new(codec, "AV Jack", | 341 | err = snd_soc_jack_new(codec, "AV Jack", |
272 | SND_JACK_VIDEOOUT, &rx51_av_jack); | 342 | SND_JACK_HEADSET | SND_JACK_VIDEOOUT, |
343 | &rx51_av_jack); | ||
273 | if (err) | 344 | if (err) |
274 | return err; | 345 | return err; |
275 | err = snd_soc_jack_add_gpios(&rx51_av_jack, | 346 | err = snd_soc_jack_add_gpios(&rx51_av_jack, |
@@ -279,6 +350,24 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd) | |||
279 | return err; | 350 | return err; |
280 | } | 351 | } |
281 | 352 | ||
353 | static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm) | ||
354 | { | ||
355 | int err; | ||
356 | |||
357 | err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb, | ||
358 | ARRAY_SIZE(aic34_rx51_controlsb)); | ||
359 | if (err < 0) | ||
360 | return err; | ||
361 | |||
362 | err = snd_soc_dapm_new_controls(dapm, aic34_dapm_widgetsb, | ||
363 | ARRAY_SIZE(aic34_dapm_widgetsb)); | ||
364 | if (err < 0) | ||
365 | return 0; | ||
366 | |||
367 | return snd_soc_dapm_add_routes(dapm, audio_mapb, | ||
368 | ARRAY_SIZE(audio_mapb)); | ||
369 | } | ||
370 | |||
282 | /* Digital audio interface glue - connects codec <--> CPU */ | 371 | /* Digital audio interface glue - connects codec <--> CPU */ |
283 | static struct snd_soc_dai_link rx51_dai[] = { | 372 | static struct snd_soc_dai_link rx51_dai[] = { |
284 | { | 373 | { |
@@ -293,11 +382,30 @@ static struct snd_soc_dai_link rx51_dai[] = { | |||
293 | }, | 382 | }, |
294 | }; | 383 | }; |
295 | 384 | ||
385 | struct snd_soc_aux_dev rx51_aux_dev[] = { | ||
386 | { | ||
387 | .name = "TLV320AIC34b", | ||
388 | .codec_name = "tlv320aic3x-codec.2-0019", | ||
389 | .init = rx51_aic34b_init, | ||
390 | }, | ||
391 | }; | ||
392 | |||
393 | static struct snd_soc_codec_conf rx51_codec_conf[] = { | ||
394 | { | ||
395 | .dev_name = "tlv320aic3x-codec.2-0019", | ||
396 | .name_prefix = "b", | ||
397 | }, | ||
398 | }; | ||
399 | |||
296 | /* Audio card */ | 400 | /* Audio card */ |
297 | static struct snd_soc_card rx51_sound_card = { | 401 | static struct snd_soc_card rx51_sound_card = { |
298 | .name = "RX-51", | 402 | .name = "RX-51", |
299 | .dai_link = rx51_dai, | 403 | .dai_link = rx51_dai, |
300 | .num_links = ARRAY_SIZE(rx51_dai), | 404 | .num_links = ARRAY_SIZE(rx51_dai), |
405 | .aux_dev = rx51_aux_dev, | ||
406 | .num_aux_devs = ARRAY_SIZE(rx51_aux_dev), | ||
407 | .codec_conf = rx51_codec_conf, | ||
408 | .num_configs = ARRAY_SIZE(rx51_codec_conf), | ||
301 | }; | 409 | }; |
302 | 410 | ||
303 | static struct platform_device *rx51_snd_device; | 411 | static struct platform_device *rx51_snd_device; |
@@ -309,10 +417,14 @@ static int __init rx51_soc_init(void) | |||
309 | if (!machine_is_nokia_rx51()) | 417 | if (!machine_is_nokia_rx51()) |
310 | return -ENODEV; | 418 | return -ENODEV; |
311 | 419 | ||
312 | err = gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel"); | 420 | err = gpio_request_one(RX51_TVOUT_SEL_GPIO, |
421 | GPIOF_DIR_OUT | GPIOF_INIT_LOW, "tvout_sel"); | ||
313 | if (err) | 422 | if (err) |
314 | goto err_gpio_tvout_sel; | 423 | goto err_gpio_tvout_sel; |
315 | gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0); | 424 | err = gpio_request_one(RX51_ECI_SW_GPIO, |
425 | GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "eci_sw"); | ||
426 | if (err) | ||
427 | goto err_gpio_eci_sw; | ||
316 | 428 | ||
317 | rx51_snd_device = platform_device_alloc("soc-audio", -1); | 429 | rx51_snd_device = platform_device_alloc("soc-audio", -1); |
318 | if (!rx51_snd_device) { | 430 | if (!rx51_snd_device) { |
@@ -330,6 +442,8 @@ static int __init rx51_soc_init(void) | |||
330 | err2: | 442 | err2: |
331 | platform_device_put(rx51_snd_device); | 443 | platform_device_put(rx51_snd_device); |
332 | err1: | 444 | err1: |
445 | gpio_free(RX51_ECI_SW_GPIO); | ||
446 | err_gpio_eci_sw: | ||
333 | gpio_free(RX51_TVOUT_SEL_GPIO); | 447 | gpio_free(RX51_TVOUT_SEL_GPIO); |
334 | err_gpio_tvout_sel: | 448 | err_gpio_tvout_sel: |
335 | 449 | ||
@@ -342,6 +456,7 @@ static void __exit rx51_soc_exit(void) | |||
342 | rx51_av_jack_gpios); | 456 | rx51_av_jack_gpios); |
343 | 457 | ||
344 | platform_device_unregister(rx51_snd_device); | 458 | platform_device_unregister(rx51_snd_device); |
459 | gpio_free(RX51_ECI_SW_GPIO); | ||
345 | gpio_free(RX51_TVOUT_SEL_GPIO); | 460 | gpio_free(RX51_TVOUT_SEL_GPIO); |
346 | } | 461 | } |
347 | 462 | ||
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c index 0fd60f423036..2afabaf59491 100644 --- a/sound/soc/pxa/raumfeld.c +++ b/sound/soc/pxa/raumfeld.c | |||
@@ -151,13 +151,13 @@ static struct snd_soc_ops raumfeld_cs4270_ops = { | |||
151 | .hw_params = raumfeld_cs4270_hw_params, | 151 | .hw_params = raumfeld_cs4270_hw_params, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | static int raumfeld_line_suspend(struct platform_device *pdev, pm_message_t state) | 154 | static int raumfeld_line_suspend(struct snd_soc_card *card) |
155 | { | 155 | { |
156 | raumfeld_enable_audio(false); | 156 | raumfeld_enable_audio(false); |
157 | return 0; | 157 | return 0; |
158 | } | 158 | } |
159 | 159 | ||
160 | static int raumfeld_line_resume(struct platform_device *pdev) | 160 | static int raumfeld_line_resume(struct snd_soc_card *card) |
161 | { | 161 | { |
162 | raumfeld_enable_audio(true); | 162 | raumfeld_enable_audio(true); |
163 | return 0; | 163 | return 0; |
@@ -229,19 +229,19 @@ static struct snd_soc_dai_link raumfeld_dai[] = { | |||
229 | { | 229 | { |
230 | .name = "ak4104", | 230 | .name = "ak4104", |
231 | .stream_name = "Playback", | 231 | .stream_name = "Playback", |
232 | .cpu_dai_name = "pxa-ssp-dai.1", | 232 | .cpu_dai_name = "pxa-ssp-dai.1", |
233 | .codec_dai_name = "ak4104-hifi", | 233 | .codec_dai_name = "ak4104-hifi", |
234 | .platform_name = "pxa-pcm-audio", | 234 | .platform_name = "pxa-pcm-audio", |
235 | .ops = &raumfeld_ak4104_ops, | 235 | .ops = &raumfeld_ak4104_ops, |
236 | .codec_name = "ak4104-codec.0", | 236 | .codec_name = "ak4104-codec.0", |
237 | }, | 237 | }, |
238 | { | 238 | { |
239 | .name = "CS4270", | 239 | .name = "CS4270", |
240 | .stream_name = "CS4270", | 240 | .stream_name = "CS4270", |
241 | .cpu_dai_name = "pxa-ssp-dai.0", | 241 | .cpu_dai_name = "pxa-ssp-dai.0", |
242 | .platform_name = "pxa-pcm-audio", | 242 | .platform_name = "pxa-pcm-audio", |
243 | .codec_dai_name = "cs4270-hifi", | 243 | .codec_dai_name = "cs4270-hifi", |
244 | .codec_name = "cs4270-codec.0-0048", | 244 | .codec_name = "cs4270-codec.0-0048", |
245 | .ops = &raumfeld_cs4270_ops, | 245 | .ops = &raumfeld_cs4270_ops, |
246 | },}; | 246 | },}; |
247 | 247 | ||
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index 4b6e5d608b42..9a2351366957 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -237,7 +237,7 @@ static struct snd_soc_dai_link tosa_dai[] = { | |||
237 | }, | 237 | }, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static int tosa_probe(struct platform_device *dev) | 240 | static int tosa_probe(struct snd_soc_card *card) |
241 | { | 241 | { |
242 | int ret; | 242 | int ret; |
243 | 243 | ||
@@ -251,7 +251,7 @@ static int tosa_probe(struct platform_device *dev) | |||
251 | return ret; | 251 | return ret; |
252 | } | 252 | } |
253 | 253 | ||
254 | static int tosa_remove(struct platform_device *dev) | 254 | static int tosa_remove(struct snd_soc_card *card) |
255 | { | 255 | { |
256 | gpio_free(TOSA_GPIO_L_MUTE); | 256 | gpio_free(TOSA_GPIO_L_MUTE); |
257 | return 0; | 257 | return 0; |
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c index 3ceaef68e01d..d69d9fc32233 100644 --- a/sound/soc/pxa/z2.c +++ b/sound/soc/pxa/z2.c | |||
@@ -95,6 +95,11 @@ static struct snd_soc_jack_pin hs_jack_pins[] = { | |||
95 | .pin = "Headphone Jack", | 95 | .pin = "Headphone Jack", |
96 | .mask = SND_JACK_HEADPHONE, | 96 | .mask = SND_JACK_HEADPHONE, |
97 | }, | 97 | }, |
98 | { | ||
99 | .pin = "Ext Spk", | ||
100 | .mask = SND_JACK_HEADPHONE, | ||
101 | .invert = 1 | ||
102 | }, | ||
98 | }; | 103 | }; |
99 | 104 | ||
100 | /* Headset jack detection gpios */ | 105 | /* Headset jack detection gpios */ |
@@ -147,7 +152,7 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd) | |||
147 | snd_soc_dapm_disable_pin(dapm, "LINPUT3"); | 152 | snd_soc_dapm_disable_pin(dapm, "LINPUT3"); |
148 | snd_soc_dapm_disable_pin(dapm, "RINPUT3"); | 153 | snd_soc_dapm_disable_pin(dapm, "RINPUT3"); |
149 | snd_soc_dapm_disable_pin(dapm, "OUT3"); | 154 | snd_soc_dapm_disable_pin(dapm, "OUT3"); |
150 | snd_soc_dapm_disable_pin(dapm, "MONO"); | 155 | snd_soc_dapm_disable_pin(dapm, "MONO1"); |
151 | 156 | ||
152 | /* Add z2 specific widgets */ | 157 | /* Add z2 specific widgets */ |
153 | snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets, | 158 | snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets, |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c index 25bba108fea3..ac577263b3e3 100644 --- a/sound/soc/pxa/zylonite.c +++ b/sound/soc/pxa/zylonite.c | |||
@@ -189,7 +189,7 @@ static struct snd_soc_dai_link zylonite_dai[] = { | |||
189 | }, | 189 | }, |
190 | }; | 190 | }; |
191 | 191 | ||
192 | static int zylonite_probe(struct platform_device *pdev) | 192 | static int zylonite_probe(struct snd_soc_card *card) |
193 | { | 193 | { |
194 | int ret; | 194 | int ret; |
195 | 195 | ||
@@ -216,7 +216,7 @@ static int zylonite_probe(struct platform_device *pdev) | |||
216 | return 0; | 216 | return 0; |
217 | } | 217 | } |
218 | 218 | ||
219 | static int zylonite_remove(struct platform_device *pdev) | 219 | static int zylonite_remove(struct snd_soc_card *card) |
220 | { | 220 | { |
221 | if (clk_pout) { | 221 | if (clk_pout) { |
222 | clk_disable(pout); | 222 | clk_disable(pout); |
@@ -226,8 +226,7 @@ static int zylonite_remove(struct platform_device *pdev) | |||
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
229 | static int zylonite_suspend_post(struct platform_device *pdev, | 229 | static int zylonite_suspend_post(struct snd_soc_card *card) |
230 | pm_message_t state) | ||
231 | { | 230 | { |
232 | if (clk_pout) | 231 | if (clk_pout) |
233 | clk_disable(pout); | 232 | clk_disable(pout); |
@@ -235,7 +234,7 @@ static int zylonite_suspend_post(struct platform_device *pdev, | |||
235 | return 0; | 234 | return 0; |
236 | } | 235 | } |
237 | 236 | ||
238 | static int zylonite_resume_pre(struct platform_device *pdev) | 237 | static int zylonite_resume_pre(struct snd_soc_card *card) |
239 | { | 238 | { |
240 | int ret = 0; | 239 | int ret = 0; |
241 | 240 | ||
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index d6713d5a90e7..a3fdfb631469 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -35,23 +35,16 @@ config SND_SAMSUNG_I2S | |||
35 | tristate | 35 | tristate |
36 | 36 | ||
37 | config SND_SOC_SAMSUNG_NEO1973_WM8753 | 37 | config SND_SOC_SAMSUNG_NEO1973_WM8753 |
38 | tristate "SoC I2S Audio support for NEO1973 - WM8753" | 38 | tristate "Audio support for Openmoko Neo1973 Smartphones (GTA01/GTA02)" |
39 | depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA01 | 39 | depends on SND_SOC_SAMSUNG && (MACH_NEO1973_GTA01 || MACH_NEO1973_GTA02) |
40 | select SND_S3C24XX_I2S | 40 | select SND_S3C24XX_I2S |
41 | select SND_SOC_WM8753 | 41 | select SND_SOC_WM8753 |
42 | select SND_SOC_LM4857 if MACH_NEO1973_GTA01 | ||
43 | select SND_SOC_DFBMCS320 | ||
42 | help | 44 | help |
43 | Say Y if you want to add support for SoC audio on smdk2440 | 45 | Say Y here to enable audio support for the Openmoko Neo1973 |
44 | with the WM8753. | 46 | Smartphones. |
45 | 47 | ||
46 | config SND_SOC_SAMSUNG_NEO1973_GTA02_WM8753 | ||
47 | tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)" | ||
48 | depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02 | ||
49 | select SND_S3C24XX_I2S | ||
50 | select SND_SOC_WM8753 | ||
51 | help | ||
52 | This driver provides audio support for the Openmoko Neo FreeRunner | ||
53 | smartphone. | ||
54 | |||
55 | config SND_SOC_SAMSUNG_JIVE_WM8750 | 48 | config SND_SOC_SAMSUNG_JIVE_WM8750 |
56 | tristate "SoC I2S Audio support for Jive" | 49 | tristate "SoC I2S Audio support for Jive" |
57 | depends on SND_SOC_SAMSUNG && MACH_JIVE | 50 | depends on SND_SOC_SAMSUNG && MACH_JIVE |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 705d4e8a6724..294dec05c26d 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -20,7 +20,6 @@ obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o | |||
20 | # S3C24XX Machine Support | 20 | # S3C24XX Machine Support |
21 | snd-soc-jive-wm8750-objs := jive_wm8750.o | 21 | snd-soc-jive-wm8750-objs := jive_wm8750.o |
22 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o | 22 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o |
23 | snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o | ||
24 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o | 23 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o |
25 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o | 24 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o |
26 | snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o | 25 | snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o |
@@ -38,7 +37,6 @@ snd-soc-smdk-spdif-objs := smdk_spdif.o | |||
38 | 37 | ||
39 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 38 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
40 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 39 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
41 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o | ||
42 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o | 40 | obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o |
43 | obj-$(CONFIG_SND_SOC_SAMSUNG_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o | 41 | obj-$(CONFIG_SND_SOC_SAMSUNG_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o |
44 | obj-$(CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o | 42 | obj-$(CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o |
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index 4770a9550341..f97110e72e85 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -12,24 +12,24 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/io.h> | 15 | #include <linux/io.h> |
18 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
19 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
20 | 18 | ||
21 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
22 | 20 | ||
23 | #include <plat/regs-ac97.h> | ||
24 | #include <mach/dma.h> | 21 | #include <mach/dma.h> |
22 | #include <plat/regs-ac97.h> | ||
25 | #include <plat/audio.h> | 23 | #include <plat/audio.h> |
26 | 24 | ||
27 | #include "dma.h" | 25 | #include "dma.h" |
28 | #include "ac97.h" | ||
29 | 26 | ||
30 | #define AC_CMD_ADDR(x) (x << 16) | 27 | #define AC_CMD_ADDR(x) (x << 16) |
31 | #define AC_CMD_DATA(x) (x & 0xffff) | 28 | #define AC_CMD_DATA(x) (x & 0xffff) |
32 | 29 | ||
30 | #define S3C_AC97_DAI_PCM 0 | ||
31 | #define S3C_AC97_DAI_MIC 1 | ||
32 | |||
33 | struct s3c_ac97_info { | 33 | struct s3c_ac97_info { |
34 | struct clk *ac97_clk; | 34 | struct clk *ac97_clk; |
35 | void __iomem *regs; | 35 | void __iomem *regs; |
diff --git a/sound/soc/samsung/ac97.h b/sound/soc/samsung/ac97.h deleted file mode 100644 index 0d0e1b511457..000000000000 --- a/sound/soc/samsung/ac97.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | /* sound/soc/samsung/ac97.h | ||
2 | * | ||
3 | * ALSA SoC Audio Layer - S3C AC97 Controller driver | ||
4 | * Evolved from s3c2443-ac97.h | ||
5 | * | ||
6 | * Copyright (c) 2010 Samsung Electronics Co. Ltd | ||
7 | * Author: Jaswinder Singh <jassi.brar@samsung.com> | ||
8 | * Credits: Graeme Gregory, Sean Choi | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef __S3C_AC97_H_ | ||
16 | #define __S3C_AC97_H_ | ||
17 | |||
18 | #define S3C_AC97_DAI_PCM 0 | ||
19 | #define S3C_AC97_DAI_MIC 1 | ||
20 | |||
21 | #endif /* __S3C_AC97_H_ */ | ||
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index 21240198c5d6..5cb3b880f0d5 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c | |||
@@ -14,17 +14,11 @@ | |||
14 | * option) any later version. | 14 | * option) any later version. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
22 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
23 | 19 | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/pcm_params.h> | ||
27 | #include <sound/soc.h> | 20 | #include <sound/soc.h> |
21 | #include <sound/pcm_params.h> | ||
28 | 22 | ||
29 | #include <asm/dma.h> | 23 | #include <asm/dma.h> |
30 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
@@ -32,6 +26,9 @@ | |||
32 | 26 | ||
33 | #include "dma.h" | 27 | #include "dma.h" |
34 | 28 | ||
29 | #define ST_RUNNING (1<<0) | ||
30 | #define ST_OPENED (1<<1) | ||
31 | |||
35 | static const struct snd_pcm_hardware dma_hardware = { | 32 | static const struct snd_pcm_hardware dma_hardware = { |
36 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 33 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
37 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 34 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
@@ -313,7 +310,7 @@ dma_pointer(struct snd_pcm_substream *substream) | |||
313 | /* we seem to be getting the odd error from the pcm library due | 310 | /* we seem to be getting the odd error from the pcm library due |
314 | * to out-of-bounds pointers. this is maybe due to the dma engine | 311 | * to out-of-bounds pointers. this is maybe due to the dma engine |
315 | * not having loaded the new values for the channel before being | 312 | * not having loaded the new values for the channel before being |
316 | * callled... (todo - fix ) | 313 | * called... (todo - fix ) |
317 | */ | 314 | */ |
318 | 315 | ||
319 | if (res >= snd_pcm_lib_buffer_bytes(substream)) { | 316 | if (res >= snd_pcm_lib_buffer_bytes(substream)) { |
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h index f8cd2b4223af..c50659269a40 100644 --- a/sound/soc/samsung/dma.h +++ b/sound/soc/samsung/dma.h | |||
@@ -12,9 +12,6 @@ | |||
12 | #ifndef _S3C_AUDIO_H | 12 | #ifndef _S3C_AUDIO_H |
13 | #define _S3C_AUDIO_H | 13 | #define _S3C_AUDIO_H |
14 | 14 | ||
15 | #define ST_RUNNING (1<<0) | ||
16 | #define ST_OPENED (1<<1) | ||
17 | |||
18 | struct s3c_dma_params { | 15 | struct s3c_dma_params { |
19 | struct s3c2410_dma_client *client; /* stream identifier */ | 16 | struct s3c2410_dma_client *client; /* stream identifier */ |
20 | int channel; /* Channel ID */ | 17 | int channel; /* Channel ID */ |
@@ -22,9 +19,4 @@ struct s3c_dma_params { | |||
22 | int dma_size; /* Size of the DMA transfer */ | 19 | int dma_size; /* Size of the DMA transfer */ |
23 | }; | 20 | }; |
24 | 21 | ||
25 | #define S3C24XX_DAI_I2S 0 | ||
26 | |||
27 | /* platform data */ | ||
28 | extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; | ||
29 | |||
30 | #endif | 22 | #endif |
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c index 34dd9ef1b9c0..f6b3a3ce5919 100644 --- a/sound/soc/samsung/goni_wm8994.c +++ b/sound/soc/samsung/goni_wm8994.c | |||
@@ -11,21 +11,13 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <sound/soc.h> | 14 | #include <sound/soc.h> |
19 | #include <sound/jack.h> | 15 | #include <sound/jack.h> |
16 | |||
20 | #include <asm/mach-types.h> | 17 | #include <asm/mach-types.h> |
21 | #include <mach/gpio.h> | 18 | #include <mach/gpio.h> |
22 | #include <mach/regs-clock.h> | ||
23 | 19 | ||
24 | #include <linux/mfd/wm8994/core.h> | ||
25 | #include <linux/mfd/wm8994/registers.h> | ||
26 | #include "../codecs/wm8994.h" | 20 | #include "../codecs/wm8994.h" |
27 | #include "dma.h" | ||
28 | #include "i2s.h" | ||
29 | 21 | ||
30 | #define MACHINE_NAME 0 | 22 | #define MACHINE_NAME 0 |
31 | #define CPU_VOICE_DAI 1 | 23 | #define CPU_VOICE_DAI 1 |
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c index c45f7ce14d61..241f55d00660 100644 --- a/sound/soc/samsung/h1940_uda1380.c +++ b/sound/soc/samsung/h1940_uda1380.c | |||
@@ -13,25 +13,16 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
21 | 17 | ||
22 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
23 | #include <sound/uda1380.h> | ||
24 | #include <sound/jack.h> | 19 | #include <sound/jack.h> |
25 | 20 | ||
26 | #include <plat/regs-iis.h> | 21 | #include <plat/regs-iis.h> |
27 | |||
28 | #include <mach/h1940-latch.h> | 22 | #include <mach/h1940-latch.h> |
29 | |||
30 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
31 | 24 | ||
32 | #include "dma.h" | ||
33 | #include "s3c24xx-i2s.h" | 25 | #include "s3c24xx-i2s.h" |
34 | #include "../codecs/uda1380.h" | ||
35 | 26 | ||
36 | static unsigned int rates[] = { | 27 | static unsigned int rates[] = { |
37 | 11025, | 28 | 11025, |
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index d00ac3a7102c..ffa09b3b2caa 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c | |||
@@ -15,9 +15,8 @@ | |||
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | 17 | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | #include <sound/pcm_params.h> | ||
21 | 20 | ||
22 | #include <plat/audio.h> | 21 | #include <plat/audio.h> |
23 | 22 | ||
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c index 08802520e014..3b53ad54bc33 100644 --- a/sound/soc/samsung/jive_wm8750.c +++ b/sound/soc/samsung/jive_wm8750.c | |||
@@ -11,22 +11,11 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/timer.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/clk.h> | ||
20 | |||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | 14 | #include <sound/soc.h> |
24 | 15 | ||
25 | #include <asm/mach-types.h> | 16 | #include <asm/mach-types.h> |
26 | 17 | ||
27 | #include "dma.h" | ||
28 | #include "s3c2412-i2s.h" | 18 | #include "s3c2412-i2s.h" |
29 | |||
30 | #include "../codecs/wm8750.h" | 19 | #include "../codecs/wm8750.h" |
31 | 20 | ||
32 | static const struct snd_soc_dapm_route audio_map[] = { | 21 | static const struct snd_soc_dapm_route audio_map[] = { |
diff --git a/sound/soc/samsung/lm4857.h b/sound/soc/samsung/lm4857.h deleted file mode 100644 index 0cf5b7011d6f..000000000000 --- a/sound/soc/samsung/lm4857.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /* | ||
2 | * lm4857.h -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * Revision history | ||
14 | * 18th Jun 2007 Initial version. | ||
15 | */ | ||
16 | |||
17 | #ifndef LM4857_H_ | ||
18 | #define LM4857_H_ | ||
19 | |||
20 | /* The register offsets in the cache array */ | ||
21 | #define LM4857_MVOL 0 | ||
22 | #define LM4857_LVOL 1 | ||
23 | #define LM4857_RVOL 2 | ||
24 | #define LM4857_CTRL 3 | ||
25 | |||
26 | /* the shifts required to set these bits */ | ||
27 | #define LM4857_3D 5 | ||
28 | #define LM4857_WAKEUP 5 | ||
29 | #define LM4857_EPGAIN 4 | ||
30 | |||
31 | #endif /*LM4857_H_*/ | ||
32 | |||
diff --git a/sound/soc/samsung/ln2440sbc_alc650.c b/sound/soc/samsung/ln2440sbc_alc650.c index a2bb34def740..bd91c19a6c08 100644 --- a/sound/soc/samsung/ln2440sbc_alc650.c +++ b/sound/soc/samsung/ln2440sbc_alc650.c | |||
@@ -16,15 +16,8 @@ | |||
16 | * | 16 | * |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
24 | 20 | ||
25 | #include "dma.h" | ||
26 | #include "ac97.h" | ||
27 | |||
28 | static struct snd_soc_card ln2440sbc; | 21 | static struct snd_soc_card ln2440sbc; |
29 | 22 | ||
30 | static struct snd_soc_dai_link ln2440sbc_dai[] = { | 23 | static struct snd_soc_dai_link ln2440sbc_dai[] = { |
diff --git a/sound/soc/samsung/neo1973_gta02_wm8753.c b/sound/soc/samsung/neo1973_gta02_wm8753.c deleted file mode 100644 index 0d0ae2b9eef6..000000000000 --- a/sound/soc/samsung/neo1973_gta02_wm8753.c +++ /dev/null | |||
@@ -1,504 +0,0 @@ | |||
1 | /* | ||
2 | * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02) | ||
3 | * | ||
4 | * Copyright 2007 Openmoko Inc | ||
5 | * Author: Graeme Gregory <graeme@openmoko.org> | ||
6 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
7 | * Author: Graeme Gregory <linux@wolfsonmicro.com> | ||
8 | * Copyright 2009 Wolfson Microelectronics | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/timer.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/soc.h> | ||
25 | |||
26 | #include <asm/mach-types.h> | ||
27 | |||
28 | #include <plat/regs-iis.h> | ||
29 | |||
30 | #include <mach/regs-clock.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <mach/gta02.h> | ||
33 | #include "../codecs/wm8753.h" | ||
34 | #include "dma.h" | ||
35 | #include "s3c24xx-i2s.h" | ||
36 | |||
37 | static struct snd_soc_card neo1973_gta02; | ||
38 | |||
39 | static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, | ||
40 | struct snd_pcm_hw_params *params) | ||
41 | { | ||
42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
44 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
45 | unsigned int pll_out = 0, bclk = 0; | ||
46 | int ret = 0; | ||
47 | unsigned long iis_clkrate; | ||
48 | |||
49 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | ||
50 | |||
51 | switch (params_rate(params)) { | ||
52 | case 8000: | ||
53 | case 16000: | ||
54 | pll_out = 12288000; | ||
55 | break; | ||
56 | case 48000: | ||
57 | bclk = WM8753_BCLK_DIV_4; | ||
58 | pll_out = 12288000; | ||
59 | break; | ||
60 | case 96000: | ||
61 | bclk = WM8753_BCLK_DIV_2; | ||
62 | pll_out = 12288000; | ||
63 | break; | ||
64 | case 11025: | ||
65 | bclk = WM8753_BCLK_DIV_16; | ||
66 | pll_out = 11289600; | ||
67 | break; | ||
68 | case 22050: | ||
69 | bclk = WM8753_BCLK_DIV_8; | ||
70 | pll_out = 11289600; | ||
71 | break; | ||
72 | case 44100: | ||
73 | bclk = WM8753_BCLK_DIV_4; | ||
74 | pll_out = 11289600; | ||
75 | break; | ||
76 | case 88200: | ||
77 | bclk = WM8753_BCLK_DIV_2; | ||
78 | pll_out = 11289600; | ||
79 | break; | ||
80 | } | ||
81 | |||
82 | /* set codec DAI configuration */ | ||
83 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
84 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
85 | SND_SOC_DAIFMT_CBM_CFM); | ||
86 | if (ret < 0) | ||
87 | return ret; | ||
88 | |||
89 | /* set cpu DAI configuration */ | ||
90 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
91 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
92 | SND_SOC_DAIFMT_CBM_CFM); | ||
93 | if (ret < 0) | ||
94 | return ret; | ||
95 | |||
96 | /* set the codec system clock for DAC and ADC */ | ||
97 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, | ||
98 | SND_SOC_CLOCK_IN); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | /* set MCLK division for sample rate */ | ||
103 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, | ||
104 | S3C2410_IISMOD_32FS); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | |||
108 | /* set codec BCLK division for sample rate */ | ||
109 | ret = snd_soc_dai_set_clkdiv(codec_dai, | ||
110 | WM8753_BCLKDIV, bclk); | ||
111 | if (ret < 0) | ||
112 | return ret; | ||
113 | |||
114 | /* set prescaler division for sample rate */ | ||
115 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, | ||
116 | S3C24XX_PRESCALE(4, 4)); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | /* codec PLL input is PCLK/4 */ | ||
121 | ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, | ||
122 | iis_clkrate / 4, pll_out); | ||
123 | if (ret < 0) | ||
124 | return ret; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) | ||
130 | { | ||
131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
132 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
133 | |||
134 | /* disable the PLL */ | ||
135 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Neo1973 WM8753 HiFi DAI opserations. | ||
140 | */ | ||
141 | static struct snd_soc_ops neo1973_gta02_hifi_ops = { | ||
142 | .hw_params = neo1973_gta02_hifi_hw_params, | ||
143 | .hw_free = neo1973_gta02_hifi_hw_free, | ||
144 | }; | ||
145 | |||
146 | static int neo1973_gta02_voice_hw_params( | ||
147 | struct snd_pcm_substream *substream, | ||
148 | struct snd_pcm_hw_params *params) | ||
149 | { | ||
150 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
151 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
152 | unsigned int pcmdiv = 0; | ||
153 | int ret = 0; | ||
154 | unsigned long iis_clkrate; | ||
155 | |||
156 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | ||
157 | |||
158 | if (params_rate(params) != 8000) | ||
159 | return -EINVAL; | ||
160 | if (params_channels(params) != 1) | ||
161 | return -EINVAL; | ||
162 | |||
163 | pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ | ||
164 | |||
165 | /* todo: gg check mode (DSP_B) against CSR datasheet */ | ||
166 | /* set codec DAI configuration */ | ||
167 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | | ||
168 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
169 | if (ret < 0) | ||
170 | return ret; | ||
171 | |||
172 | /* set the codec system clock for DAC and ADC */ | ||
173 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, | ||
174 | 12288000, SND_SOC_CLOCK_IN); | ||
175 | if (ret < 0) | ||
176 | return ret; | ||
177 | |||
178 | /* set codec PCM division for sample rate */ | ||
179 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, | ||
180 | pcmdiv); | ||
181 | if (ret < 0) | ||
182 | return ret; | ||
183 | |||
184 | /* configure and enable PLL for 12.288MHz output */ | ||
185 | ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, | ||
186 | iis_clkrate / 4, 12288000); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) | ||
194 | { | ||
195 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
196 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
197 | |||
198 | /* disable the PLL */ | ||
199 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); | ||
200 | } | ||
201 | |||
202 | static struct snd_soc_ops neo1973_gta02_voice_ops = { | ||
203 | .hw_params = neo1973_gta02_voice_hw_params, | ||
204 | .hw_free = neo1973_gta02_voice_hw_free, | ||
205 | }; | ||
206 | |||
207 | #define LM4853_AMP 1 | ||
208 | #define LM4853_SPK 2 | ||
209 | |||
210 | static u8 lm4853_state; | ||
211 | |||
212 | /* This has no effect, it exists only to maintain compatibility with | ||
213 | * existing ALSA state files. | ||
214 | */ | ||
215 | static int lm4853_set_state(struct snd_kcontrol *kcontrol, | ||
216 | struct snd_ctl_elem_value *ucontrol) | ||
217 | { | ||
218 | int val = ucontrol->value.integer.value[0]; | ||
219 | |||
220 | if (val) | ||
221 | lm4853_state |= LM4853_AMP; | ||
222 | else | ||
223 | lm4853_state &= ~LM4853_AMP; | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static int lm4853_get_state(struct snd_kcontrol *kcontrol, | ||
229 | struct snd_ctl_elem_value *ucontrol) | ||
230 | { | ||
231 | ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP; | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int lm4853_set_spk(struct snd_kcontrol *kcontrol, | ||
237 | struct snd_ctl_elem_value *ucontrol) | ||
238 | { | ||
239 | int val = ucontrol->value.integer.value[0]; | ||
240 | |||
241 | if (val) { | ||
242 | lm4853_state |= LM4853_SPK; | ||
243 | gpio_set_value(GTA02_GPIO_HP_IN, 0); | ||
244 | } else { | ||
245 | lm4853_state &= ~LM4853_SPK; | ||
246 | gpio_set_value(GTA02_GPIO_HP_IN, 1); | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static int lm4853_get_spk(struct snd_kcontrol *kcontrol, | ||
253 | struct snd_ctl_elem_value *ucontrol) | ||
254 | { | ||
255 | ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1; | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int lm4853_event(struct snd_soc_dapm_widget *w, | ||
261 | struct snd_kcontrol *k, | ||
262 | int event) | ||
263 | { | ||
264 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { | ||
270 | SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), | ||
271 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | ||
272 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
273 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
274 | SND_SOC_DAPM_MIC("Handset Mic", NULL), | ||
275 | SND_SOC_DAPM_SPK("Handset Spk", NULL), | ||
276 | }; | ||
277 | |||
278 | |||
279 | /* example machine audio_mapnections */ | ||
280 | static const struct snd_soc_dapm_route audio_map[] = { | ||
281 | |||
282 | /* Connections to the lm4853 amp */ | ||
283 | {"Stereo Out", NULL, "LOUT1"}, | ||
284 | {"Stereo Out", NULL, "ROUT1"}, | ||
285 | |||
286 | /* Connections to the GSM Module */ | ||
287 | {"GSM Line Out", NULL, "MONO1"}, | ||
288 | {"GSM Line Out", NULL, "MONO2"}, | ||
289 | {"RXP", NULL, "GSM Line In"}, | ||
290 | {"RXN", NULL, "GSM Line In"}, | ||
291 | |||
292 | /* Connections to Headset */ | ||
293 | {"MIC1", NULL, "Mic Bias"}, | ||
294 | {"Mic Bias", NULL, "Headset Mic"}, | ||
295 | |||
296 | /* Call Mic */ | ||
297 | {"MIC2", NULL, "Mic Bias"}, | ||
298 | {"MIC2N", NULL, "Mic Bias"}, | ||
299 | {"Mic Bias", NULL, "Handset Mic"}, | ||
300 | |||
301 | /* Call Speaker */ | ||
302 | {"Handset Spk", NULL, "LOUT2"}, | ||
303 | {"Handset Spk", NULL, "ROUT2"}, | ||
304 | |||
305 | /* Connect the ALC pins */ | ||
306 | {"ACIN", NULL, "ACOP"}, | ||
307 | }; | ||
308 | |||
309 | static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { | ||
310 | SOC_DAPM_PIN_SWITCH("Stereo Out"), | ||
311 | SOC_DAPM_PIN_SWITCH("GSM Line Out"), | ||
312 | SOC_DAPM_PIN_SWITCH("GSM Line In"), | ||
313 | SOC_DAPM_PIN_SWITCH("Headset Mic"), | ||
314 | SOC_DAPM_PIN_SWITCH("Handset Mic"), | ||
315 | SOC_DAPM_PIN_SWITCH("Handset Spk"), | ||
316 | |||
317 | /* This has no effect, it exists only to maintain compatibility with | ||
318 | * existing ALSA state files. | ||
319 | */ | ||
320 | SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0, | ||
321 | lm4853_get_state, | ||
322 | lm4853_set_state), | ||
323 | SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0, | ||
324 | lm4853_get_spk, | ||
325 | lm4853_set_spk), | ||
326 | }; | ||
327 | |||
328 | /* | ||
329 | * This is an example machine initialisation for a wm8753 connected to a | ||
330 | * neo1973 GTA02. | ||
331 | */ | ||
332 | static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd) | ||
333 | { | ||
334 | struct snd_soc_codec *codec = rtd->codec; | ||
335 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
336 | int err; | ||
337 | |||
338 | /* set up NC codec pins */ | ||
339 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | ||
340 | snd_soc_dapm_nc_pin(dapm, "OUT4"); | ||
341 | snd_soc_dapm_nc_pin(dapm, "LINE1"); | ||
342 | snd_soc_dapm_nc_pin(dapm, "LINE2"); | ||
343 | |||
344 | /* Add neo1973 gta02 specific widgets */ | ||
345 | snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets, | ||
346 | ARRAY_SIZE(wm8753_dapm_widgets)); | ||
347 | |||
348 | /* add neo1973 gta02 specific controls */ | ||
349 | err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls, | ||
350 | ARRAY_SIZE(wm8753_neo1973_gta02_controls)); | ||
351 | |||
352 | if (err < 0) | ||
353 | return err; | ||
354 | |||
355 | /* set up neo1973 gta02 specific audio path audio_map */ | ||
356 | snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); | ||
357 | |||
358 | /* set endpoints to default off mode */ | ||
359 | snd_soc_dapm_disable_pin(dapm, "Stereo Out"); | ||
360 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
361 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
362 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
363 | snd_soc_dapm_disable_pin(dapm, "Handset Mic"); | ||
364 | snd_soc_dapm_disable_pin(dapm, "Handset Spk"); | ||
365 | |||
366 | /* allow audio paths from the GSM modem to run during suspend */ | ||
367 | snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); | ||
368 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); | ||
369 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); | ||
370 | snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); | ||
371 | snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); | ||
372 | snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); | ||
373 | |||
374 | snd_soc_dapm_sync(dapm); | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * BT Codec DAI | ||
381 | */ | ||
382 | static struct snd_soc_dai_driver bt_dai = { | ||
383 | .name = "bluetooth-dai", | ||
384 | .playback = { | ||
385 | .channels_min = 1, | ||
386 | .channels_max = 1, | ||
387 | .rates = SNDRV_PCM_RATE_8000, | ||
388 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
389 | .capture = { | ||
390 | .channels_min = 1, | ||
391 | .channels_max = 1, | ||
392 | .rates = SNDRV_PCM_RATE_8000, | ||
393 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
394 | }; | ||
395 | |||
396 | static struct snd_soc_dai_link neo1973_gta02_dai[] = { | ||
397 | { /* Hifi Playback - for similatious use with voice below */ | ||
398 | .name = "WM8753", | ||
399 | .stream_name = "WM8753 HiFi", | ||
400 | .cpu_dai_name = "s3c24xx-iis", | ||
401 | .codec_dai_name = "wm8753-hifi", | ||
402 | .init = neo1973_gta02_wm8753_init, | ||
403 | .platform_name = "samsung-audio", | ||
404 | .codec_name = "wm8753-codec.0-001a", | ||
405 | .ops = &neo1973_gta02_hifi_ops, | ||
406 | }, | ||
407 | { /* Voice via BT */ | ||
408 | .name = "Bluetooth", | ||
409 | .stream_name = "Voice", | ||
410 | .cpu_dai_name = "bluetooth-dai", | ||
411 | .codec_dai_name = "wm8753-voice", | ||
412 | .ops = &neo1973_gta02_voice_ops, | ||
413 | .codec_name = "wm8753-codec.0-001a", | ||
414 | .platform_name = "samsung-audio", | ||
415 | }, | ||
416 | }; | ||
417 | |||
418 | static struct snd_soc_card neo1973_gta02 = { | ||
419 | .name = "neo1973-gta02", | ||
420 | .dai_link = neo1973_gta02_dai, | ||
421 | .num_links = ARRAY_SIZE(neo1973_gta02_dai), | ||
422 | }; | ||
423 | |||
424 | static struct platform_device *neo1973_gta02_snd_device; | ||
425 | |||
426 | static int __init neo1973_gta02_init(void) | ||
427 | { | ||
428 | int ret; | ||
429 | |||
430 | if (!machine_is_neo1973_gta02()) { | ||
431 | printk(KERN_INFO | ||
432 | "Only GTA02 is supported by this ASoC driver\n"); | ||
433 | return -ENODEV; | ||
434 | } | ||
435 | |||
436 | neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); | ||
437 | if (!neo1973_gta02_snd_device) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | /* register bluetooth DAI here */ | ||
441 | ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, &bt_dai); | ||
442 | if (ret) | ||
443 | goto err_put_device; | ||
444 | |||
445 | platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02); | ||
446 | ret = platform_device_add(neo1973_gta02_snd_device); | ||
447 | |||
448 | if (ret) | ||
449 | goto err_unregister_dai; | ||
450 | |||
451 | /* Initialise GPIOs used by amp */ | ||
452 | ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN"); | ||
453 | if (ret) { | ||
454 | pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN); | ||
455 | goto err_del_device; | ||
456 | } | ||
457 | |||
458 | ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1); | ||
459 | if (ret) { | ||
460 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); | ||
461 | goto err_free_gpio_hp_in; | ||
462 | } | ||
463 | |||
464 | ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT"); | ||
465 | if (ret) { | ||
466 | pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT); | ||
467 | goto err_free_gpio_hp_in; | ||
468 | } | ||
469 | |||
470 | ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1); | ||
471 | if (ret) { | ||
472 | pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT); | ||
473 | goto err_free_gpio_amp_shut; | ||
474 | } | ||
475 | |||
476 | return 0; | ||
477 | |||
478 | err_free_gpio_amp_shut: | ||
479 | gpio_free(GTA02_GPIO_AMP_SHUT); | ||
480 | err_free_gpio_hp_in: | ||
481 | gpio_free(GTA02_GPIO_HP_IN); | ||
482 | err_del_device: | ||
483 | platform_device_del(neo1973_gta02_snd_device); | ||
484 | err_unregister_dai: | ||
485 | snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev); | ||
486 | err_put_device: | ||
487 | platform_device_put(neo1973_gta02_snd_device); | ||
488 | return ret; | ||
489 | } | ||
490 | module_init(neo1973_gta02_init); | ||
491 | |||
492 | static void __exit neo1973_gta02_exit(void) | ||
493 | { | ||
494 | snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev); | ||
495 | platform_device_unregister(neo1973_gta02_snd_device); | ||
496 | gpio_free(GTA02_GPIO_HP_IN); | ||
497 | gpio_free(GTA02_GPIO_AMP_SHUT); | ||
498 | } | ||
499 | module_exit(neo1973_gta02_exit); | ||
500 | |||
501 | /* Module information */ | ||
502 | MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org"); | ||
503 | MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02"); | ||
504 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index d20815d5ab2e..78bfdb3f5d7e 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c | |||
@@ -1,57 +1,32 @@ | |||
1 | /* | 1 | /* |
2 | * neo1973_wm8753.c -- SoC audio for Neo1973 | 2 | * neo1973_wm8753.c -- SoC audio for Openmoko Neo1973 and Freerunner devices |
3 | * | 3 | * |
4 | * Copyright 2007 Openmoko Inc | ||
5 | * Author: Graeme Gregory <graeme@openmoko.org> | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | 6 | * Copyright 2007 Wolfson Microelectronics PLC. |
5 | * Author: Graeme Gregory | 7 | * Author: Graeme Gregory |
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | 8 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com |
9 | * Copyright 2009 Wolfson Microelectronics | ||
7 | * | 10 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 12 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation; either version 2 of the License, or (at your | 13 | * Free Software Foundation; either version 2 of the License, or (at your |
11 | * option) any later version. | 14 | * option) any later version. |
12 | * | ||
13 | */ | 15 | */ |
14 | 16 | ||
15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/timer.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
20 | #include <linux/i2c.h> | 19 | #include <linux/gpio.h> |
21 | #include <sound/core.h> | 20 | |
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | 21 | #include <sound/soc.h> |
24 | #include <sound/tlv.h> | ||
25 | 22 | ||
26 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
27 | #include <asm/hardware/scoop.h> | ||
28 | #include <mach/regs-clock.h> | ||
29 | #include <mach/regs-gpio.h> | ||
30 | #include <mach/hardware.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <mach/spi-gpio.h> | ||
33 | |||
34 | #include <plat/regs-iis.h> | 24 | #include <plat/regs-iis.h> |
25 | #include <mach/gta02.h> | ||
35 | 26 | ||
36 | #include "../codecs/wm8753.h" | 27 | #include "../codecs/wm8753.h" |
37 | #include "lm4857.h" | ||
38 | #include "dma.h" | ||
39 | #include "s3c24xx-i2s.h" | 28 | #include "s3c24xx-i2s.h" |
40 | 29 | ||
41 | /* define the scenarios */ | ||
42 | #define NEO_AUDIO_OFF 0 | ||
43 | #define NEO_GSM_CALL_AUDIO_HANDSET 1 | ||
44 | #define NEO_GSM_CALL_AUDIO_HEADSET 2 | ||
45 | #define NEO_GSM_CALL_AUDIO_BLUETOOTH 3 | ||
46 | #define NEO_STEREO_TO_SPEAKERS 4 | ||
47 | #define NEO_STEREO_TO_HEADPHONES 5 | ||
48 | #define NEO_CAPTURE_HANDSET 6 | ||
49 | #define NEO_CAPTURE_HEADSET 7 | ||
50 | #define NEO_CAPTURE_BLUETOOTH 8 | ||
51 | |||
52 | static struct snd_soc_card neo1973; | ||
53 | static struct i2c_client *i2c; | ||
54 | |||
55 | static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | 30 | static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, |
56 | struct snd_pcm_hw_params *params) | 31 | struct snd_pcm_hw_params *params) |
57 | { | 32 | { |
@@ -62,8 +37,6 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | |||
62 | int ret = 0; | 37 | int ret = 0; |
63 | unsigned long iis_clkrate; | 38 | unsigned long iis_clkrate; |
64 | 39 | ||
65 | pr_debug("Entered %s\n", __func__); | ||
66 | |||
67 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | 40 | iis_clkrate = s3c24xx_i2s_get_clockrate(); |
68 | 41 | ||
69 | switch (params_rate(params)) { | 42 | switch (params_rate(params)) { |
@@ -148,8 +121,6 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) | |||
148 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 121 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
149 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 122 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
150 | 123 | ||
151 | pr_debug("Entered %s\n", __func__); | ||
152 | |||
153 | /* disable the PLL */ | 124 | /* disable the PLL */ |
154 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); | 125 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); |
155 | } | 126 | } |
@@ -171,8 +142,6 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | |||
171 | int ret = 0; | 142 | int ret = 0; |
172 | unsigned long iis_clkrate; | 143 | unsigned long iis_clkrate; |
173 | 144 | ||
174 | pr_debug("Entered %s\n", __func__); | ||
175 | |||
176 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | 145 | iis_clkrate = s3c24xx_i2s_get_clockrate(); |
177 | 146 | ||
178 | if (params_rate(params) != 8000) | 147 | if (params_rate(params) != 8000) |
@@ -214,8 +183,6 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) | |||
214 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 183 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
215 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 184 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
216 | 185 | ||
217 | pr_debug("Entered %s\n", __func__); | ||
218 | |||
219 | /* disable the PLL */ | 186 | /* disable the PLL */ |
220 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); | 187 | return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); |
221 | } | 188 | } |
@@ -225,335 +192,232 @@ static struct snd_soc_ops neo1973_voice_ops = { | |||
225 | .hw_free = neo1973_voice_hw_free, | 192 | .hw_free = neo1973_voice_hw_free, |
226 | }; | 193 | }; |
227 | 194 | ||
228 | static int neo1973_scenario; | 195 | /* Shared routes and controls */ |
229 | |||
230 | static int neo1973_get_scenario(struct snd_kcontrol *kcontrol, | ||
231 | struct snd_ctl_elem_value *ucontrol) | ||
232 | { | ||
233 | ucontrol->value.integer.value[0] = neo1973_scenario; | ||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario) | ||
238 | { | ||
239 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
240 | |||
241 | pr_debug("Entered %s\n", __func__); | ||
242 | |||
243 | switch (neo1973_scenario) { | ||
244 | case NEO_AUDIO_OFF: | ||
245 | snd_soc_dapm_disable_pin(dapm, "Audio Out"); | ||
246 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
247 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
248 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
249 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
250 | break; | ||
251 | case NEO_GSM_CALL_AUDIO_HANDSET: | ||
252 | snd_soc_dapm_enable_pin(dapm, "Audio Out"); | ||
253 | snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); | ||
254 | snd_soc_dapm_enable_pin(dapm, "GSM Line In"); | ||
255 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
256 | snd_soc_dapm_enable_pin(dapm, "Call Mic"); | ||
257 | break; | ||
258 | case NEO_GSM_CALL_AUDIO_HEADSET: | ||
259 | snd_soc_dapm_enable_pin(dapm, "Audio Out"); | ||
260 | snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); | ||
261 | snd_soc_dapm_enable_pin(dapm, "GSM Line In"); | ||
262 | snd_soc_dapm_enable_pin(dapm, "Headset Mic"); | ||
263 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
264 | break; | ||
265 | case NEO_GSM_CALL_AUDIO_BLUETOOTH: | ||
266 | snd_soc_dapm_disable_pin(dapm, "Audio Out"); | ||
267 | snd_soc_dapm_enable_pin(dapm, "GSM Line Out"); | ||
268 | snd_soc_dapm_enable_pin(dapm, "GSM Line In"); | ||
269 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
270 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
271 | break; | ||
272 | case NEO_STEREO_TO_SPEAKERS: | ||
273 | snd_soc_dapm_enable_pin(dapm, "Audio Out"); | ||
274 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
275 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
276 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
277 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
278 | break; | ||
279 | case NEO_STEREO_TO_HEADPHONES: | ||
280 | snd_soc_dapm_enable_pin(dapm, "Audio Out"); | ||
281 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
282 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
283 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
284 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
285 | break; | ||
286 | case NEO_CAPTURE_HANDSET: | ||
287 | snd_soc_dapm_disable_pin(dapm, "Audio Out"); | ||
288 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
289 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
290 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
291 | snd_soc_dapm_enable_pin(dapm, "Call Mic"); | ||
292 | break; | ||
293 | case NEO_CAPTURE_HEADSET: | ||
294 | snd_soc_dapm_disable_pin(dapm, "Audio Out"); | ||
295 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
296 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
297 | snd_soc_dapm_enable_pin(dapm, "Headset Mic"); | ||
298 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
299 | break; | ||
300 | case NEO_CAPTURE_BLUETOOTH: | ||
301 | snd_soc_dapm_disable_pin(dapm, "Audio Out"); | ||
302 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
303 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
304 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
305 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
306 | break; | ||
307 | default: | ||
308 | snd_soc_dapm_disable_pin(dapm, "Audio Out"); | ||
309 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
310 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
311 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
312 | snd_soc_dapm_disable_pin(dapm, "Call Mic"); | ||
313 | } | ||
314 | 196 | ||
315 | snd_soc_dapm_sync(dapm); | 197 | static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = { |
198 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | ||
199 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
200 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
201 | SND_SOC_DAPM_MIC("Handset Mic", NULL), | ||
202 | }; | ||
316 | 203 | ||
317 | return 0; | 204 | static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = { |
318 | } | 205 | /* Connections to the GSM Module */ |
206 | {"GSM Line Out", NULL, "MONO1"}, | ||
207 | {"GSM Line Out", NULL, "MONO2"}, | ||
208 | {"RXP", NULL, "GSM Line In"}, | ||
209 | {"RXN", NULL, "GSM Line In"}, | ||
319 | 210 | ||
320 | static int neo1973_set_scenario(struct snd_kcontrol *kcontrol, | 211 | /* Connections to Headset */ |
321 | struct snd_ctl_elem_value *ucontrol) | 212 | {"MIC1", NULL, "Mic Bias"}, |
322 | { | 213 | {"Mic Bias", NULL, "Headset Mic"}, |
323 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
324 | 214 | ||
325 | pr_debug("Entered %s\n", __func__); | 215 | /* Call Mic */ |
216 | {"MIC2", NULL, "Mic Bias"}, | ||
217 | {"MIC2N", NULL, "Mic Bias"}, | ||
218 | {"Mic Bias", NULL, "Handset Mic"}, | ||
326 | 219 | ||
327 | if (neo1973_scenario == ucontrol->value.integer.value[0]) | 220 | /* Connect the ALC pins */ |
328 | return 0; | 221 | {"ACIN", NULL, "ACOP"}, |
222 | }; | ||
329 | 223 | ||
330 | neo1973_scenario = ucontrol->value.integer.value[0]; | 224 | static const struct snd_kcontrol_new neo1973_wm8753_controls[] = { |
331 | set_scenario_endpoints(codec, neo1973_scenario); | 225 | SOC_DAPM_PIN_SWITCH("GSM Line Out"), |
332 | return 1; | 226 | SOC_DAPM_PIN_SWITCH("GSM Line In"), |
333 | } | 227 | SOC_DAPM_PIN_SWITCH("Headset Mic"), |
228 | SOC_DAPM_PIN_SWITCH("Handset Mic"), | ||
229 | }; | ||
334 | 230 | ||
335 | static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0}; | 231 | /* GTA02 specific routes and controlls */ |
336 | 232 | ||
337 | static void lm4857_write_regs(void) | 233 | #ifdef CONFIG_MACH_NEO1973_GTA02 |
338 | { | ||
339 | pr_debug("Entered %s\n", __func__); | ||
340 | 234 | ||
341 | if (i2c_master_send(i2c, lm4857_regs, 4) != 4) | 235 | static int gta02_speaker_enabled; |
342 | printk(KERN_ERR "lm4857: i2c write failed\n"); | ||
343 | } | ||
344 | 236 | ||
345 | static int lm4857_get_reg(struct snd_kcontrol *kcontrol, | 237 | static int lm4853_set_spk(struct snd_kcontrol *kcontrol, |
346 | struct snd_ctl_elem_value *ucontrol) | 238 | struct snd_ctl_elem_value *ucontrol) |
347 | { | 239 | { |
348 | struct soc_mixer_control *mc = | 240 | gta02_speaker_enabled = ucontrol->value.integer.value[0]; |
349 | (struct soc_mixer_control *)kcontrol->private_value; | ||
350 | int reg = mc->reg; | ||
351 | int shift = mc->shift; | ||
352 | int mask = mc->max; | ||
353 | 241 | ||
354 | pr_debug("Entered %s\n", __func__); | 242 | gpio_set_value(GTA02_GPIO_HP_IN, !gta02_speaker_enabled); |
355 | 243 | ||
356 | ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask; | ||
357 | return 0; | 244 | return 0; |
358 | } | 245 | } |
359 | 246 | ||
360 | static int lm4857_set_reg(struct snd_kcontrol *kcontrol, | 247 | static int lm4853_get_spk(struct snd_kcontrol *kcontrol, |
361 | struct snd_ctl_elem_value *ucontrol) | 248 | struct snd_ctl_elem_value *ucontrol) |
362 | { | 249 | { |
363 | struct soc_mixer_control *mc = | 250 | ucontrol->value.integer.value[0] = gta02_speaker_enabled; |
364 | (struct soc_mixer_control *)kcontrol->private_value; | 251 | return 0; |
365 | int reg = mc->reg; | ||
366 | int shift = mc->shift; | ||
367 | int mask = mc->max; | ||
368 | |||
369 | if (((lm4857_regs[reg] >> shift) & mask) == | ||
370 | ucontrol->value.integer.value[0]) | ||
371 | return 0; | ||
372 | |||
373 | lm4857_regs[reg] &= ~(mask << shift); | ||
374 | lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift; | ||
375 | lm4857_write_regs(); | ||
376 | return 1; | ||
377 | } | 252 | } |
378 | 253 | ||
379 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, | 254 | static int lm4853_event(struct snd_soc_dapm_widget *w, |
380 | struct snd_ctl_elem_value *ucontrol) | 255 | struct snd_kcontrol *k, int event) |
381 | { | 256 | { |
382 | u8 value = lm4857_regs[LM4857_CTRL] & 0x0F; | 257 | gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event)); |
383 | |||
384 | pr_debug("Entered %s\n", __func__); | ||
385 | |||
386 | if (value) | ||
387 | value -= 5; | ||
388 | 258 | ||
389 | ucontrol->value.integer.value[0] = value; | ||
390 | return 0; | 259 | return 0; |
391 | } | 260 | } |
392 | 261 | ||
393 | static int lm4857_set_mode(struct snd_kcontrol *kcontrol, | 262 | static const struct snd_soc_dapm_route neo1973_gta02_routes[] = { |
394 | struct snd_ctl_elem_value *ucontrol) | 263 | /* Connections to the amp */ |
395 | { | 264 | {"Stereo Out", NULL, "LOUT1"}, |
396 | u8 value = ucontrol->value.integer.value[0]; | 265 | {"Stereo Out", NULL, "ROUT1"}, |
397 | |||
398 | pr_debug("Entered %s\n", __func__); | ||
399 | |||
400 | if (value) | ||
401 | value += 5; | ||
402 | |||
403 | if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value) | ||
404 | return 0; | ||
405 | |||
406 | lm4857_regs[LM4857_CTRL] &= 0xF0; | ||
407 | lm4857_regs[LM4857_CTRL] |= value; | ||
408 | lm4857_write_regs(); | ||
409 | return 1; | ||
410 | } | ||
411 | 266 | ||
412 | static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { | 267 | /* Call Speaker */ |
413 | SND_SOC_DAPM_LINE("Audio Out", NULL), | 268 | {"Handset Spk", NULL, "LOUT2"}, |
414 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | 269 | {"Handset Spk", NULL, "ROUT2"}, |
415 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
416 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
417 | SND_SOC_DAPM_MIC("Call Mic", NULL), | ||
418 | }; | 270 | }; |
419 | 271 | ||
272 | static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = { | ||
273 | SOC_DAPM_PIN_SWITCH("Handset Spk"), | ||
274 | SOC_DAPM_PIN_SWITCH("Stereo Out"), | ||
420 | 275 | ||
421 | static const struct snd_soc_dapm_route dapm_routes[] = { | 276 | SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0, |
422 | 277 | lm4853_get_spk, | |
423 | /* Connections to the lm4857 amp */ | 278 | lm4853_set_spk), |
424 | {"Audio Out", NULL, "LOUT1"}, | 279 | }; |
425 | {"Audio Out", NULL, "ROUT1"}, | ||
426 | |||
427 | /* Connections to the GSM Module */ | ||
428 | {"GSM Line Out", NULL, "MONO1"}, | ||
429 | {"GSM Line Out", NULL, "MONO2"}, | ||
430 | {"RXP", NULL, "GSM Line In"}, | ||
431 | {"RXN", NULL, "GSM Line In"}, | ||
432 | 280 | ||
433 | /* Connections to Headset */ | 281 | static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = { |
434 | {"MIC1", NULL, "Mic Bias"}, | 282 | SND_SOC_DAPM_SPK("Handset Spk", NULL), |
435 | {"Mic Bias", NULL, "Headset Mic"}, | 283 | SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), |
284 | }; | ||
436 | 285 | ||
437 | /* Call Mic */ | 286 | static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) |
438 | {"MIC2", NULL, "Mic Bias"}, | 287 | { |
439 | {"MIC2N", NULL, "Mic Bias"}, | 288 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
440 | {"Mic Bias", NULL, "Call Mic"}, | 289 | int ret; |
441 | 290 | ||
442 | /* Connect the ALC pins */ | 291 | ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets, |
443 | {"ACIN", NULL, "ACOP"}, | 292 | ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets)); |
444 | }; | 293 | if (ret) |
294 | return ret; | ||
445 | 295 | ||
446 | static const char *lm4857_mode[] = { | 296 | ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes, |
447 | "Off", | 297 | ARRAY_SIZE(neo1973_gta02_routes)); |
448 | "Call Speaker", | 298 | if (ret) |
449 | "Stereo Speakers", | 299 | return ret; |
450 | "Stereo Speakers + Headphones", | ||
451 | "Headphones" | ||
452 | }; | ||
453 | 300 | ||
454 | static const struct soc_enum lm4857_mode_enum[] = { | 301 | ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls, |
455 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode), | 302 | ARRAY_SIZE(neo1973_gta02_wm8753_controls)); |
456 | }; | 303 | if (ret) |
304 | return ret; | ||
457 | 305 | ||
458 | static const char *neo_scenarios[] = { | 306 | snd_soc_dapm_disable_pin(dapm, "Stereo Out"); |
459 | "Off", | 307 | snd_soc_dapm_disable_pin(dapm, "Handset Spk"); |
460 | "GSM Handset", | 308 | snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); |
461 | "GSM Headset", | 309 | snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); |
462 | "GSM Bluetooth", | ||
463 | "Speakers", | ||
464 | "Headphones", | ||
465 | "Capture Handset", | ||
466 | "Capture Headset", | ||
467 | "Capture Bluetooth" | ||
468 | }; | ||
469 | 310 | ||
470 | static const struct soc_enum neo_scenario_enum[] = { | 311 | return 0; |
471 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios), | 312 | } |
472 | }; | ||
473 | 313 | ||
474 | static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0); | 314 | #else |
475 | static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0); | 315 | static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; } |
476 | 316 | #endif | |
477 | static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { | ||
478 | SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0, | ||
479 | lm4857_get_reg, lm4857_set_reg, stereo_tlv), | ||
480 | SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0, | ||
481 | lm4857_get_reg, lm4857_set_reg, stereo_tlv), | ||
482 | SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0, | ||
483 | lm4857_get_reg, lm4857_set_reg, mono_tlv), | ||
484 | SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0], | ||
485 | lm4857_get_mode, lm4857_set_mode), | ||
486 | SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0], | ||
487 | neo1973_get_scenario, neo1973_set_scenario), | ||
488 | SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0, | ||
489 | lm4857_get_reg, lm4857_set_reg), | ||
490 | SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0, | ||
491 | lm4857_get_reg, lm4857_set_reg), | ||
492 | SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0, | ||
493 | lm4857_get_reg, lm4857_set_reg), | ||
494 | SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0, | ||
495 | lm4857_get_reg, lm4857_set_reg), | ||
496 | }; | ||
497 | 317 | ||
498 | /* | ||
499 | * This is an example machine initialisation for a wm8753 connected to a | ||
500 | * neo1973 II. It is missing logic to detect hp/mic insertions and logic | ||
501 | * to re-route the audio in such an event. | ||
502 | */ | ||
503 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) | 318 | static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd) |
504 | { | 319 | { |
505 | struct snd_soc_codec *codec = rtd->codec; | 320 | struct snd_soc_codec *codec = rtd->codec; |
506 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 321 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
507 | int err; | 322 | int ret; |
508 | |||
509 | pr_debug("Entered %s\n", __func__); | ||
510 | 323 | ||
511 | /* set up NC codec pins */ | 324 | /* set up NC codec pins */ |
512 | snd_soc_dapm_nc_pin(dapm, "LOUT2"); | 325 | if (machine_is_neo1973_gta01()) { |
513 | snd_soc_dapm_nc_pin(dapm, "ROUT2"); | 326 | snd_soc_dapm_nc_pin(dapm, "LOUT2"); |
327 | snd_soc_dapm_nc_pin(dapm, "ROUT2"); | ||
328 | } | ||
514 | snd_soc_dapm_nc_pin(dapm, "OUT3"); | 329 | snd_soc_dapm_nc_pin(dapm, "OUT3"); |
515 | snd_soc_dapm_nc_pin(dapm, "OUT4"); | 330 | snd_soc_dapm_nc_pin(dapm, "OUT4"); |
516 | snd_soc_dapm_nc_pin(dapm, "LINE1"); | 331 | snd_soc_dapm_nc_pin(dapm, "LINE1"); |
517 | snd_soc_dapm_nc_pin(dapm, "LINE2"); | 332 | snd_soc_dapm_nc_pin(dapm, "LINE2"); |
518 | 333 | ||
519 | /* Add neo1973 specific widgets */ | 334 | /* Add neo1973 specific widgets */ |
520 | snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets, | 335 | ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets, |
521 | ARRAY_SIZE(wm8753_dapm_widgets)); | 336 | ARRAY_SIZE(neo1973_wm8753_dapm_widgets)); |
522 | 337 | if (ret) | |
523 | /* set endpoints to default mode */ | 338 | return ret; |
524 | set_scenario_endpoints(codec, NEO_AUDIO_OFF); | ||
525 | 339 | ||
526 | /* add neo1973 specific controls */ | 340 | /* add neo1973 specific controls */ |
527 | err = snd_soc_add_controls(codec, wm8753_neo1973_controls, | 341 | ret = snd_soc_add_controls(codec, neo1973_wm8753_controls, |
528 | ARRAY_SIZE(8753_neo1973_controls)); | 342 | ARRAY_SIZE(neo1973_wm8753_controls)); |
529 | if (err < 0) | 343 | if (ret) |
530 | return err; | 344 | return ret; |
531 | 345 | ||
532 | /* set up neo1973 specific audio routes */ | 346 | /* set up neo1973 specific audio routes */ |
533 | err = snd_soc_dapm_add_routes(dapm, dapm_routes, | 347 | ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes, |
534 | ARRAY_SIZE(dapm_routes)); | 348 | ARRAY_SIZE(neo1973_wm8753_routes)); |
349 | if (ret) | ||
350 | return ret; | ||
351 | |||
352 | /* set endpoints to default off mode */ | ||
353 | snd_soc_dapm_disable_pin(dapm, "GSM Line Out"); | ||
354 | snd_soc_dapm_disable_pin(dapm, "GSM Line In"); | ||
355 | snd_soc_dapm_disable_pin(dapm, "Headset Mic"); | ||
356 | snd_soc_dapm_disable_pin(dapm, "Handset Mic"); | ||
357 | |||
358 | /* allow audio paths from the GSM modem to run during suspend */ | ||
359 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out"); | ||
360 | snd_soc_dapm_ignore_suspend(dapm, "GSM Line In"); | ||
361 | snd_soc_dapm_ignore_suspend(dapm, "Headset Mic"); | ||
362 | snd_soc_dapm_ignore_suspend(dapm, "Handset Mic"); | ||
363 | |||
364 | if (machine_is_neo1973_gta02()) { | ||
365 | ret = neo1973_gta02_wm8753_init(codec); | ||
366 | if (ret) | ||
367 | return ret; | ||
368 | } | ||
535 | 369 | ||
536 | snd_soc_dapm_sync(dapm); | 370 | snd_soc_dapm_sync(dapm); |
371 | |||
537 | return 0; | 372 | return 0; |
538 | } | 373 | } |
539 | 374 | ||
540 | /* | 375 | /* GTA01 specific controlls */ |
541 | * BT Codec DAI | 376 | |
542 | */ | 377 | #ifdef CONFIG_MACH_NEO1973_GTA01 |
543 | static struct snd_soc_dai bt_dai = { | 378 | |
544 | .name = "bluetooth-dai", | 379 | static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = { |
545 | .playback = { | 380 | {"Amp IN", NULL, "ROUT1"}, |
546 | .channels_min = 1, | 381 | {"Amp IN", NULL, "LOUT1"}, |
547 | .channels_max = 1, | 382 | |
548 | .rates = SNDRV_PCM_RATE_8000, | 383 | {"Handset Spk", NULL, "Amp EP"}, |
549 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 384 | {"Stereo Out", NULL, "Amp LS"}, |
550 | .capture = { | 385 | {"Headphone", NULL, "Amp HP"}, |
551 | .channels_min = 1, | 386 | }; |
552 | .channels_max = 1, | 387 | |
553 | .rates = SNDRV_PCM_RATE_8000, | 388 | static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = { |
554 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 389 | SND_SOC_DAPM_SPK("Handset Spk", NULL), |
390 | SND_SOC_DAPM_SPK("Stereo Out", NULL), | ||
391 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
555 | }; | 392 | }; |
556 | 393 | ||
394 | static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) | ||
395 | { | ||
396 | int ret; | ||
397 | |||
398 | ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets, | ||
399 | ARRAY_SIZE(neo1973_lm4857_dapm_widgets)); | ||
400 | if (ret) | ||
401 | return ret; | ||
402 | |||
403 | ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes, | ||
404 | ARRAY_SIZE(neo1973_lm4857_routes)); | ||
405 | if (ret) | ||
406 | return ret; | ||
407 | |||
408 | snd_soc_dapm_ignore_suspend(dapm, "Stereo Out"); | ||
409 | snd_soc_dapm_ignore_suspend(dapm, "Handset Spk"); | ||
410 | snd_soc_dapm_ignore_suspend(dapm, "Headphone"); | ||
411 | |||
412 | snd_soc_dapm_sync(dapm); | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | #else | ||
418 | static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; }; | ||
419 | #endif | ||
420 | |||
557 | static struct snd_soc_dai_link neo1973_dai[] = { | 421 | static struct snd_soc_dai_link neo1973_dai[] = { |
558 | { /* Hifi Playback - for similatious use with voice below */ | 422 | { /* Hifi Playback - for similatious use with voice below */ |
559 | .name = "WM8753", | 423 | .name = "WM8753", |
@@ -569,90 +433,49 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
569 | .name = "Bluetooth", | 433 | .name = "Bluetooth", |
570 | .stream_name = "Voice", | 434 | .stream_name = "Voice", |
571 | .platform_name = "samsung-audio", | 435 | .platform_name = "samsung-audio", |
572 | .cpu_dai_name = "bluetooth-dai", | 436 | .cpu_dai_name = "dfbmcs320-pcm", |
573 | .codec_dai_name = "wm8753-voice", | 437 | .codec_dai_name = "wm8753-voice", |
574 | .codec_name = "wm8753-codec.0-001a", | 438 | .codec_name = "wm8753-codec.0-001a", |
575 | .ops = &neo1973_voice_ops, | 439 | .ops = &neo1973_voice_ops, |
576 | }, | 440 | }, |
577 | }; | 441 | }; |
578 | 442 | ||
579 | static struct snd_soc_card neo1973 = { | 443 | static struct snd_soc_aux_dev neo1973_aux_devs[] = { |
580 | .name = "neo1973", | 444 | { |
581 | .dai_link = neo1973_dai, | 445 | .name = "dfbmcs320", |
582 | .num_links = ARRAY_SIZE(neo1973_dai), | 446 | .codec_name = "dfbmcs320.0", |
447 | }, | ||
448 | { | ||
449 | .name = "lm4857", | ||
450 | .codec_name = "lm4857.0-007c", | ||
451 | .init = neo1973_lm4857_init, | ||
452 | }, | ||
583 | }; | 453 | }; |
584 | 454 | ||
585 | static int lm4857_i2c_probe(struct i2c_client *client, | 455 | static struct snd_soc_codec_conf neo1973_codec_conf[] = { |
586 | const struct i2c_device_id *id) | 456 | { |
587 | { | 457 | .dev_name = "lm4857.0-007c", |
588 | pr_debug("Entered %s\n", __func__); | 458 | .name_prefix = "Amp", |
589 | 459 | }, | |
590 | i2c = client; | 460 | }; |
591 | |||
592 | lm4857_write_regs(); | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int lm4857_i2c_remove(struct i2c_client *client) | ||
597 | { | ||
598 | pr_debug("Entered %s\n", __func__); | ||
599 | |||
600 | i2c = NULL; | ||
601 | |||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static u8 lm4857_state; | ||
606 | |||
607 | static int lm4857_suspend(struct i2c_client *dev, pm_message_t state) | ||
608 | { | ||
609 | pr_debug("Entered %s\n", __func__); | ||
610 | |||
611 | dev_dbg(&dev->dev, "lm4857_suspend\n"); | ||
612 | lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf; | ||
613 | if (lm4857_state) { | ||
614 | lm4857_regs[LM4857_CTRL] &= 0xf0; | ||
615 | lm4857_write_regs(); | ||
616 | } | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | static int lm4857_resume(struct i2c_client *dev) | ||
621 | { | ||
622 | pr_debug("Entered %s\n", __func__); | ||
623 | |||
624 | if (lm4857_state) { | ||
625 | lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f); | ||
626 | lm4857_write_regs(); | ||
627 | } | ||
628 | return 0; | ||
629 | } | ||
630 | |||
631 | static void lm4857_shutdown(struct i2c_client *dev) | ||
632 | { | ||
633 | pr_debug("Entered %s\n", __func__); | ||
634 | |||
635 | dev_dbg(&dev->dev, "lm4857_shutdown\n"); | ||
636 | lm4857_regs[LM4857_CTRL] &= 0xf0; | ||
637 | lm4857_write_regs(); | ||
638 | } | ||
639 | 461 | ||
640 | static const struct i2c_device_id lm4857_i2c_id[] = { | 462 | #ifdef CONFIG_MACH_NEO1973_GTA02 |
641 | { "neo1973_lm4857", 0 }, | 463 | static const struct gpio neo1973_gta02_gpios[] = { |
642 | { } | 464 | { GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" }, |
465 | { GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" }, | ||
643 | }; | 466 | }; |
467 | #else | ||
468 | static const struct gpio neo1973_gta02_gpios[] = {}; | ||
469 | #endif | ||
644 | 470 | ||
645 | static struct i2c_driver lm4857_i2c_driver = { | 471 | static struct snd_soc_card neo1973 = { |
646 | .driver = { | 472 | .name = "neo1973", |
647 | .name = "LM4857 I2C Amp", | 473 | .dai_link = neo1973_dai, |
648 | .owner = THIS_MODULE, | 474 | .num_links = ARRAY_SIZE(neo1973_dai), |
649 | }, | 475 | .aux_dev = neo1973_aux_devs, |
650 | .suspend = lm4857_suspend, | 476 | .num_aux_devs = ARRAY_SIZE(neo1973_aux_devs), |
651 | .resume = lm4857_resume, | 477 | .codec_conf = neo1973_codec_conf, |
652 | .shutdown = lm4857_shutdown, | 478 | .num_configs = ARRAY_SIZE(neo1973_codec_conf), |
653 | .probe = lm4857_i2c_probe, | ||
654 | .remove = lm4857_i2c_remove, | ||
655 | .id_table = lm4857_i2c_id, | ||
656 | }; | 479 | }; |
657 | 480 | ||
658 | static struct platform_device *neo1973_snd_device; | 481 | static struct platform_device *neo1973_snd_device; |
@@ -661,46 +484,56 @@ static int __init neo1973_init(void) | |||
661 | { | 484 | { |
662 | int ret; | 485 | int ret; |
663 | 486 | ||
664 | pr_debug("Entered %s\n", __func__); | 487 | if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02()) |
665 | |||
666 | if (!machine_is_neo1973_gta01()) { | ||
667 | printk(KERN_INFO | ||
668 | "Only GTA01 hardware supported by ASoC driver\n"); | ||
669 | return -ENODEV; | 488 | return -ENODEV; |
489 | |||
490 | if (machine_is_neo1973_gta02()) { | ||
491 | neo1973.name = "neo1973gta02"; | ||
492 | neo1973.num_aux_devs = 1; | ||
493 | |||
494 | ret = gpio_request_array(neo1973_gta02_gpios, | ||
495 | ARRAY_SIZE(neo1973_gta02_gpios)); | ||
496 | if (ret) | ||
497 | return ret; | ||
670 | } | 498 | } |
671 | 499 | ||
672 | neo1973_snd_device = platform_device_alloc("soc-audio", -1); | 500 | neo1973_snd_device = platform_device_alloc("soc-audio", -1); |
673 | if (!neo1973_snd_device) | 501 | if (!neo1973_snd_device) { |
674 | return -ENOMEM; | 502 | ret = -ENOMEM; |
503 | goto err_gpio_free; | ||
504 | } | ||
675 | 505 | ||
676 | platform_set_drvdata(neo1973_snd_device, &neo1973); | 506 | platform_set_drvdata(neo1973_snd_device, &neo1973); |
677 | ret = platform_device_add(neo1973_snd_device); | 507 | ret = platform_device_add(neo1973_snd_device); |
678 | 508 | ||
679 | if (ret) { | 509 | if (ret) |
680 | platform_device_put(neo1973_snd_device); | 510 | goto err_put_device; |
681 | return ret; | ||
682 | } | ||
683 | |||
684 | ret = i2c_add_driver(&lm4857_i2c_driver); | ||
685 | 511 | ||
686 | if (ret != 0) | 512 | return 0; |
687 | platform_device_unregister(neo1973_snd_device); | ||
688 | 513 | ||
514 | err_put_device: | ||
515 | platform_device_put(neo1973_snd_device); | ||
516 | err_gpio_free: | ||
517 | if (machine_is_neo1973_gta02()) { | ||
518 | gpio_free_array(neo1973_gta02_gpios, | ||
519 | ARRAY_SIZE(neo1973_gta02_gpios)); | ||
520 | } | ||
689 | return ret; | 521 | return ret; |
690 | } | 522 | } |
523 | module_init(neo1973_init); | ||
691 | 524 | ||
692 | static void __exit neo1973_exit(void) | 525 | static void __exit neo1973_exit(void) |
693 | { | 526 | { |
694 | pr_debug("Entered %s\n", __func__); | ||
695 | |||
696 | i2c_del_driver(&lm4857_i2c_driver); | ||
697 | platform_device_unregister(neo1973_snd_device); | 527 | platform_device_unregister(neo1973_snd_device); |
698 | } | ||
699 | 528 | ||
700 | module_init(neo1973_init); | 529 | if (machine_is_neo1973_gta02()) { |
530 | gpio_free_array(neo1973_gta02_gpios, | ||
531 | ARRAY_SIZE(neo1973_gta02_gpios)); | ||
532 | } | ||
533 | } | ||
701 | module_exit(neo1973_exit); | 534 | module_exit(neo1973_exit); |
702 | 535 | ||
703 | /* Module information */ | 536 | /* Module information */ |
704 | MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org"); | 537 | MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org"); |
705 | MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973"); | 538 | MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner"); |
706 | MODULE_LICENSE("GPL"); | 539 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c index 48d0b750406b..38aac7d57a59 100644 --- a/sound/soc/samsung/pcm.c +++ b/sound/soc/samsung/pcm.c | |||
@@ -11,20 +11,11 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
19 | #include <linux/kernel.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/io.h> | 15 | #include <linux/io.h> |
22 | 16 | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/soc.h> | 17 | #include <sound/soc.h> |
18 | #include <sound/pcm_params.h> | ||
28 | 19 | ||
29 | #include <plat/audio.h> | 20 | #include <plat/audio.h> |
30 | #include <plat/dma.h> | 21 | #include <plat/dma.h> |
@@ -32,6 +23,113 @@ | |||
32 | #include "dma.h" | 23 | #include "dma.h" |
33 | #include "pcm.h" | 24 | #include "pcm.h" |
34 | 25 | ||
26 | /*Register Offsets */ | ||
27 | #define S3C_PCM_CTL 0x00 | ||
28 | #define S3C_PCM_CLKCTL 0x04 | ||
29 | #define S3C_PCM_TXFIFO 0x08 | ||
30 | #define S3C_PCM_RXFIFO 0x0C | ||
31 | #define S3C_PCM_IRQCTL 0x10 | ||
32 | #define S3C_PCM_IRQSTAT 0x14 | ||
33 | #define S3C_PCM_FIFOSTAT 0x18 | ||
34 | #define S3C_PCM_CLRINT 0x20 | ||
35 | |||
36 | /* PCM_CTL Bit-Fields */ | ||
37 | #define S3C_PCM_CTL_TXDIPSTICK_MASK 0x3f | ||
38 | #define S3C_PCM_CTL_TXDIPSTICK_SHIFT 13 | ||
39 | #define S3C_PCM_CTL_RXDIPSTICK_MASK 0x3f | ||
40 | #define S3C_PCM_CTL_RXDIPSTICK_SHIFT 7 | ||
41 | #define S3C_PCM_CTL_TXDMA_EN (0x1 << 6) | ||
42 | #define S3C_PCM_CTL_RXDMA_EN (0x1 << 5) | ||
43 | #define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1 << 4) | ||
44 | #define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1 << 3) | ||
45 | #define S3C_PCM_CTL_TXFIFO_EN (0x1 << 2) | ||
46 | #define S3C_PCM_CTL_RXFIFO_EN (0x1 << 1) | ||
47 | #define S3C_PCM_CTL_ENABLE (0x1 << 0) | ||
48 | |||
49 | /* PCM_CLKCTL Bit-Fields */ | ||
50 | #define S3C_PCM_CLKCTL_SERCLK_EN (0x1 << 19) | ||
51 | #define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1 << 18) | ||
52 | #define S3C_PCM_CLKCTL_SCLKDIV_MASK 0x1ff | ||
53 | #define S3C_PCM_CLKCTL_SYNCDIV_MASK 0x1ff | ||
54 | #define S3C_PCM_CLKCTL_SCLKDIV_SHIFT 9 | ||
55 | #define S3C_PCM_CLKCTL_SYNCDIV_SHIFT 0 | ||
56 | |||
57 | /* PCM_TXFIFO Bit-Fields */ | ||
58 | #define S3C_PCM_TXFIFO_DVALID (0x1 << 16) | ||
59 | #define S3C_PCM_TXFIFO_DATA_MSK (0xffff << 0) | ||
60 | |||
61 | /* PCM_RXFIFO Bit-Fields */ | ||
62 | #define S3C_PCM_RXFIFO_DVALID (0x1 << 16) | ||
63 | #define S3C_PCM_RXFIFO_DATA_MSK (0xffff << 0) | ||
64 | |||
65 | /* PCM_IRQCTL Bit-Fields */ | ||
66 | #define S3C_PCM_IRQCTL_IRQEN (0x1 << 14) | ||
67 | #define S3C_PCM_IRQCTL_WRDEN (0x1 << 12) | ||
68 | #define S3C_PCM_IRQCTL_TXEMPTYEN (0x1 << 11) | ||
69 | #define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1 << 10) | ||
70 | #define S3C_PCM_IRQCTL_TXFULLEN (0x1 << 9) | ||
71 | #define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1 << 8) | ||
72 | #define S3C_PCM_IRQCTL_TXSTARVEN (0x1 << 7) | ||
73 | #define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1 << 6) | ||
74 | #define S3C_PCM_IRQCTL_RXEMPTEN (0x1 << 5) | ||
75 | #define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1 << 4) | ||
76 | #define S3C_PCM_IRQCTL_RXFULLEN (0x1 << 3) | ||
77 | #define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1 << 2) | ||
78 | #define S3C_PCM_IRQCTL_RXSTARVEN (0x1 << 1) | ||
79 | #define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1 << 0) | ||
80 | |||
81 | /* PCM_IRQSTAT Bit-Fields */ | ||
82 | #define S3C_PCM_IRQSTAT_IRQPND (0x1 << 13) | ||
83 | #define S3C_PCM_IRQSTAT_WRD_XFER (0x1 << 12) | ||
84 | #define S3C_PCM_IRQSTAT_TXEMPTY (0x1 << 11) | ||
85 | #define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1 << 10) | ||
86 | #define S3C_PCM_IRQSTAT_TXFULL (0x1 << 9) | ||
87 | #define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1 << 8) | ||
88 | #define S3C_PCM_IRQSTAT_TXSTARV (0x1 << 7) | ||
89 | #define S3C_PCM_IRQSTAT_TXERROVRFL (0x1 << 6) | ||
90 | #define S3C_PCM_IRQSTAT_RXEMPT (0x1 << 5) | ||
91 | #define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1 << 4) | ||
92 | #define S3C_PCM_IRQSTAT_RXFULL (0x1 << 3) | ||
93 | #define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1 << 2) | ||
94 | #define S3C_PCM_IRQSTAT_RXSTARV (0x1 << 1) | ||
95 | #define S3C_PCM_IRQSTAT_RXERROVRFL (0x1 << 0) | ||
96 | |||
97 | /* PCM_FIFOSTAT Bit-Fields */ | ||
98 | #define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f << 14) | ||
99 | #define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1 << 13) | ||
100 | #define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1 << 12) | ||
101 | #define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1 << 11) | ||
102 | #define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1 << 10) | ||
103 | #define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f << 4) | ||
104 | #define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1 << 3) | ||
105 | #define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1 << 2) | ||
106 | #define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1 << 1) | ||
107 | #define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1 << 0) | ||
108 | |||
109 | /** | ||
110 | * struct s3c_pcm_info - S3C PCM Controller information | ||
111 | * @dev: The parent device passed to use from the probe. | ||
112 | * @regs: The pointer to the device register block. | ||
113 | * @dma_playback: DMA information for playback channel. | ||
114 | * @dma_capture: DMA information for capture channel. | ||
115 | */ | ||
116 | struct s3c_pcm_info { | ||
117 | spinlock_t lock; | ||
118 | struct device *dev; | ||
119 | void __iomem *regs; | ||
120 | |||
121 | unsigned int sclk_per_fs; | ||
122 | |||
123 | /* Whether to keep PCMSCLK enabled even when idle(no active xfer) */ | ||
124 | unsigned int idleclk; | ||
125 | |||
126 | struct clk *pclk; | ||
127 | struct clk *cclk; | ||
128 | |||
129 | struct s3c_dma_params *dma_playback; | ||
130 | struct s3c_dma_params *dma_capture; | ||
131 | }; | ||
132 | |||
35 | static struct s3c2410_dma_client s3c_pcm_dma_client_out = { | 133 | static struct s3c2410_dma_client s3c_pcm_dma_client_out = { |
36 | .name = "PCM Stereo out" | 134 | .name = "PCM Stereo out" |
37 | }; | 135 | }; |
diff --git a/sound/soc/samsung/pcm.h b/sound/soc/samsung/pcm.h index 03393dcf852d..726baf814613 100644 --- a/sound/soc/samsung/pcm.h +++ b/sound/soc/samsung/pcm.h | |||
@@ -9,116 +9,9 @@ | |||
9 | #ifndef __S3C_PCM_H | 9 | #ifndef __S3C_PCM_H |
10 | #define __S3C_PCM_H __FILE__ | 10 | #define __S3C_PCM_H __FILE__ |
11 | 11 | ||
12 | /*Register Offsets */ | ||
13 | #define S3C_PCM_CTL (0x00) | ||
14 | #define S3C_PCM_CLKCTL (0x04) | ||
15 | #define S3C_PCM_TXFIFO (0x08) | ||
16 | #define S3C_PCM_RXFIFO (0x0C) | ||
17 | #define S3C_PCM_IRQCTL (0x10) | ||
18 | #define S3C_PCM_IRQSTAT (0x14) | ||
19 | #define S3C_PCM_FIFOSTAT (0x18) | ||
20 | #define S3C_PCM_CLRINT (0x20) | ||
21 | |||
22 | /* PCM_CTL Bit-Fields */ | ||
23 | #define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f) | ||
24 | #define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13) | ||
25 | #define S3C_PCM_CTL_RXDIPSTICK_MASK (0x3f) | ||
26 | #define S3C_PCM_CTL_RXDIPSTICK_SHIFT (7) | ||
27 | #define S3C_PCM_CTL_TXDMA_EN (0x1<<6) | ||
28 | #define S3C_PCM_CTL_RXDMA_EN (0x1<<5) | ||
29 | #define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4) | ||
30 | #define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1<<3) | ||
31 | #define S3C_PCM_CTL_TXFIFO_EN (0x1<<2) | ||
32 | #define S3C_PCM_CTL_RXFIFO_EN (0x1<<1) | ||
33 | #define S3C_PCM_CTL_ENABLE (0x1<<0) | ||
34 | |||
35 | /* PCM_CLKCTL Bit-Fields */ | ||
36 | #define S3C_PCM_CLKCTL_SERCLK_EN (0x1<<19) | ||
37 | #define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1<<18) | ||
38 | #define S3C_PCM_CLKCTL_SCLKDIV_MASK (0x1ff) | ||
39 | #define S3C_PCM_CLKCTL_SYNCDIV_MASK (0x1ff) | ||
40 | #define S3C_PCM_CLKCTL_SCLKDIV_SHIFT (9) | ||
41 | #define S3C_PCM_CLKCTL_SYNCDIV_SHIFT (0) | ||
42 | |||
43 | /* PCM_TXFIFO Bit-Fields */ | ||
44 | #define S3C_PCM_TXFIFO_DVALID (0x1<<16) | ||
45 | #define S3C_PCM_TXFIFO_DATA_MSK (0xffff<<0) | ||
46 | |||
47 | /* PCM_RXFIFO Bit-Fields */ | ||
48 | #define S3C_PCM_RXFIFO_DVALID (0x1<<16) | ||
49 | #define S3C_PCM_RXFIFO_DATA_MSK (0xffff<<0) | ||
50 | |||
51 | /* PCM_IRQCTL Bit-Fields */ | ||
52 | #define S3C_PCM_IRQCTL_IRQEN (0x1<<14) | ||
53 | #define S3C_PCM_IRQCTL_WRDEN (0x1<<12) | ||
54 | #define S3C_PCM_IRQCTL_TXEMPTYEN (0x1<<11) | ||
55 | #define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1<<10) | ||
56 | #define S3C_PCM_IRQCTL_TXFULLEN (0x1<<9) | ||
57 | #define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1<<8) | ||
58 | #define S3C_PCM_IRQCTL_TXSTARVEN (0x1<<7) | ||
59 | #define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1<<6) | ||
60 | #define S3C_PCM_IRQCTL_RXEMPTEN (0x1<<5) | ||
61 | #define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1<<4) | ||
62 | #define S3C_PCM_IRQCTL_RXFULLEN (0x1<<3) | ||
63 | #define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1<<2) | ||
64 | #define S3C_PCM_IRQCTL_RXSTARVEN (0x1<<1) | ||
65 | #define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1<<0) | ||
66 | |||
67 | /* PCM_IRQSTAT Bit-Fields */ | ||
68 | #define S3C_PCM_IRQSTAT_IRQPND (0x1<<13) | ||
69 | #define S3C_PCM_IRQSTAT_WRD_XFER (0x1<<12) | ||
70 | #define S3C_PCM_IRQSTAT_TXEMPTY (0x1<<11) | ||
71 | #define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1<<10) | ||
72 | #define S3C_PCM_IRQSTAT_TXFULL (0x1<<9) | ||
73 | #define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1<<8) | ||
74 | #define S3C_PCM_IRQSTAT_TXSTARV (0x1<<7) | ||
75 | #define S3C_PCM_IRQSTAT_TXERROVRFL (0x1<<6) | ||
76 | #define S3C_PCM_IRQSTAT_RXEMPT (0x1<<5) | ||
77 | #define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1<<4) | ||
78 | #define S3C_PCM_IRQSTAT_RXFULL (0x1<<3) | ||
79 | #define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1<<2) | ||
80 | #define S3C_PCM_IRQSTAT_RXSTARV (0x1<<1) | ||
81 | #define S3C_PCM_IRQSTAT_RXERROVRFL (0x1<<0) | ||
82 | |||
83 | /* PCM_FIFOSTAT Bit-Fields */ | ||
84 | #define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f<<14) | ||
85 | #define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1<<13) | ||
86 | #define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1<<12) | ||
87 | #define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1<<11) | ||
88 | #define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1<<10) | ||
89 | #define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f<<4) | ||
90 | #define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1<<3) | ||
91 | #define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1<<2) | ||
92 | #define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1<<1) | ||
93 | #define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1<<0) | ||
94 | |||
95 | #define S3C_PCM_CLKSRC_PCLK 0 | 12 | #define S3C_PCM_CLKSRC_PCLK 0 |
96 | #define S3C_PCM_CLKSRC_MUX 1 | 13 | #define S3C_PCM_CLKSRC_MUX 1 |
97 | 14 | ||
98 | #define S3C_PCM_SCLK_PER_FS 0 | 15 | #define S3C_PCM_SCLK_PER_FS 0 |
99 | 16 | ||
100 | /** | ||
101 | * struct s3c_pcm_info - S3C PCM Controller information | ||
102 | * @dev: The parent device passed to use from the probe. | ||
103 | * @regs: The pointer to the device register block. | ||
104 | * @dma_playback: DMA information for playback channel. | ||
105 | * @dma_capture: DMA information for capture channel. | ||
106 | */ | ||
107 | struct s3c_pcm_info { | ||
108 | spinlock_t lock; | ||
109 | struct device *dev; | ||
110 | void __iomem *regs; | ||
111 | |||
112 | unsigned int sclk_per_fs; | ||
113 | |||
114 | /* Whether to keep PCMSCLK enabled even when idle(no active xfer) */ | ||
115 | unsigned int idleclk; | ||
116 | |||
117 | struct clk *pclk; | ||
118 | struct clk *cclk; | ||
119 | |||
120 | struct s3c_dma_params *dma_playback; | ||
121 | struct s3c_dma_params *dma_capture; | ||
122 | }; | ||
123 | |||
124 | #endif /* __S3C_PCM_H */ | 17 | #endif /* __S3C_PCM_H */ |
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c index f40027445dda..1e574a5d440d 100644 --- a/sound/soc/samsung/rx1950_uda1380.c +++ b/sound/soc/samsung/rx1950_uda1380.c | |||
@@ -17,26 +17,15 @@ | |||
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/moduleparam.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
25 | #include <linux/clk.h> | ||
26 | 21 | ||
27 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
28 | #include <sound/uda1380.h> | ||
29 | #include <sound/jack.h> | 23 | #include <sound/jack.h> |
30 | 24 | ||
31 | #include <plat/regs-iis.h> | 25 | #include <plat/regs-iis.h> |
32 | |||
33 | #include <mach/regs-clock.h> | ||
34 | |||
35 | #include <asm/mach-types.h> | 26 | #include <asm/mach-types.h> |
36 | 27 | ||
37 | #include "dma.h" | ||
38 | #include "s3c24xx-i2s.h" | 28 | #include "s3c24xx-i2s.h" |
39 | #include "../codecs/uda1380.h" | ||
40 | 29 | ||
41 | static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); | 30 | static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd); |
42 | static int rx1950_startup(struct snd_pcm_substream *substream); | 31 | static int rx1950_startup(struct snd_pcm_substream *substream); |
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c index 094f36e41e83..52074a2b0696 100644 --- a/sound/soc/samsung/s3c-i2s-v2.c +++ b/sound/soc/samsung/s3c-i2s-v2.c | |||
@@ -20,9 +20,8 @@ | |||
20 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | 22 | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | #include <sound/pcm_params.h> | ||
26 | 25 | ||
27 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
28 | 27 | ||
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c index 7ea837867124..841ab14c1100 100644 --- a/sound/soc/samsung/s3c2412-i2s.c +++ b/sound/soc/samsung/s3c2412-i2s.c | |||
@@ -16,21 +16,13 @@ | |||
16 | * option) any later version. | 16 | * option) any later version. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/device.h> | ||
22 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
23 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
24 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
25 | #include <linux/kernel.h> | ||
26 | #include <linux/io.h> | 22 | #include <linux/io.h> |
27 | 23 | ||
28 | #include <sound/core.h> | ||
29 | #include <sound/pcm.h> | ||
30 | #include <sound/pcm_params.h> | ||
31 | #include <sound/initval.h> | ||
32 | #include <sound/soc.h> | 24 | #include <sound/soc.h> |
33 | #include <mach/hardware.h> | 25 | #include <sound/pcm_params.h> |
34 | 26 | ||
35 | #include <mach/regs-gpio.h> | 27 | #include <mach/regs-gpio.h> |
36 | #include <mach/dma.h> | 28 | #include <mach/dma.h> |
@@ -39,8 +31,6 @@ | |||
39 | #include "regs-i2s-v2.h" | 31 | #include "regs-i2s-v2.h" |
40 | #include "s3c2412-i2s.h" | 32 | #include "s3c2412-i2s.h" |
41 | 33 | ||
42 | #define S3C2412_I2S_DEBUG 0 | ||
43 | |||
44 | static struct s3c2410_dma_client s3c2412_dma_client_out = { | 34 | static struct s3c2410_dma_client s3c2412_dma_client_out = { |
45 | .name = "I2S PCM Stereo out" | 35 | .name = "I2S PCM Stereo out" |
46 | }; | 36 | }; |
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c index 13e41ed8e22b..63d8849d80bd 100644 --- a/sound/soc/samsung/s3c24xx-i2s.c +++ b/sound/soc/samsung/s3c24xx-i2s.c | |||
@@ -14,28 +14,16 @@ | |||
14 | * option) any later version. | 14 | * option) any later version. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
21 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
22 | #include <linux/jiffies.h> | ||
23 | #include <linux/io.h> | 19 | #include <linux/io.h> |
24 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
25 | 21 | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/initval.h> | ||
30 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | #include <sound/pcm_params.h> | ||
31 | 24 | ||
32 | #include <mach/hardware.h> | ||
33 | #include <mach/regs-gpio.h> | 25 | #include <mach/regs-gpio.h> |
34 | #include <mach/regs-clock.h> | ||
35 | |||
36 | #include <asm/dma.h> | ||
37 | #include <mach/dma.h> | 26 | #include <mach/dma.h> |
38 | |||
39 | #include <plat/regs-iis.h> | 27 | #include <plat/regs-iis.h> |
40 | 28 | ||
41 | #include "dma.h" | 29 | #include "dma.h" |
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c index a434032d1832..349566f0686b 100644 --- a/sound/soc/samsung/s3c24xx_simtec.c +++ b/sound/soc/samsung/s3c24xx_simtec.c | |||
@@ -7,20 +7,13 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/moduleparam.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/gpio.h> | 10 | #include <linux/gpio.h> |
14 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
15 | #include <linux/i2c.h> | ||
16 | 12 | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/soc.h> | 13 | #include <sound/soc.h> |
20 | 14 | ||
21 | #include <plat/audio-simtec.h> | 15 | #include <plat/audio-simtec.h> |
22 | 16 | ||
23 | #include "dma.h" | ||
24 | #include "s3c24xx-i2s.h" | 17 | #include "s3c24xx-i2s.h" |
25 | #include "s3c24xx_simtec.h" | 18 | #include "s3c24xx_simtec.h" |
26 | 19 | ||
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c index 08fcaaa66907..ce6aef604179 100644 --- a/sound/soc/samsung/s3c24xx_simtec_hermes.c +++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c | |||
@@ -7,18 +7,8 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/clk.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <sound/core.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/soc.h> | 10 | #include <sound/soc.h> |
17 | 11 | ||
18 | #include <plat/audio-simtec.h> | ||
19 | |||
20 | #include "dma.h" | ||
21 | #include "s3c24xx-i2s.h" | ||
22 | #include "s3c24xx_simtec.h" | 12 | #include "s3c24xx_simtec.h" |
23 | 13 | ||
24 | static const struct snd_soc_dapm_widget dapm_widgets[] = { | 14 | static const struct snd_soc_dapm_widget dapm_widgets[] = { |
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c index 116e3e670167..a7ef7db54687 100644 --- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c | |||
@@ -7,22 +7,10 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/clk.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <sound/core.h> | ||
15 | #include <sound/pcm.h> | ||
16 | #include <sound/soc.h> | 10 | #include <sound/soc.h> |
17 | 11 | ||
18 | #include <plat/audio-simtec.h> | ||
19 | |||
20 | #include "dma.h" | ||
21 | #include "s3c24xx-i2s.h" | ||
22 | #include "s3c24xx_simtec.h" | 12 | #include "s3c24xx_simtec.h" |
23 | 13 | ||
24 | #include "../codecs/tlv320aic23.h" | ||
25 | |||
26 | /* supported machines: | 14 | /* supported machines: |
27 | * | 15 | * |
28 | * Machine Connections AMP | 16 | * Machine Connections AMP |
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index 2c09e93dd566..3cb700751078 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c | |||
@@ -11,22 +11,15 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
16 | #include <linux/mutex.h> | ||
17 | #include <linux/gpio.h> | 15 | #include <linux/gpio.h> |
18 | #include <sound/pcm.h> | 16 | |
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | 17 | #include <sound/soc.h> |
21 | #include <sound/s3c24xx_uda134x.h> | 18 | #include <sound/s3c24xx_uda134x.h> |
22 | #include <sound/uda134x.h> | ||
23 | 19 | ||
24 | #include <plat/regs-iis.h> | 20 | #include <plat/regs-iis.h> |
25 | 21 | ||
26 | #include "dma.h" | ||
27 | #include "s3c24xx-i2s.h" | 22 | #include "s3c24xx-i2s.h" |
28 | #include "../codecs/uda134x.h" | ||
29 | |||
30 | 23 | ||
31 | /* #define ENFORCE_RATES 1 */ | 24 | /* #define ENFORCE_RATES 1 */ |
32 | /* | 25 | /* |
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c index 61e2b5219d42..0a2c4f223038 100644 --- a/sound/soc/samsung/smartq_wm8987.c +++ b/sound/soc/samsung/smartq_wm8987.c | |||
@@ -13,20 +13,14 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
19 | 17 | ||
20 | #include <sound/pcm.h> | ||
21 | #include <sound/pcm_params.h> | ||
22 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
23 | #include <sound/jack.h> | 19 | #include <sound/jack.h> |
24 | 20 | ||
25 | #include <asm/mach-types.h> | 21 | #include <asm/mach-types.h> |
26 | 22 | ||
27 | #include "dma.h" | ||
28 | #include "i2s.h" | 23 | #include "i2s.h" |
29 | |||
30 | #include "../codecs/wm8750.h" | 24 | #include "../codecs/wm8750.h" |
31 | 25 | ||
32 | /* | 26 | /* |
diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c index 3be7e7e92d6e..3a0dbfc793f0 100644 --- a/sound/soc/samsung/smdk2443_wm9710.c +++ b/sound/soc/samsung/smdk2443_wm9710.c | |||
@@ -12,15 +12,8 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <sound/core.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
20 | 16 | ||
21 | #include "dma.h" | ||
22 | #include "ac97.h" | ||
23 | |||
24 | static struct snd_soc_card smdk2443; | 17 | static struct snd_soc_card smdk2443; |
25 | 18 | ||
26 | static struct snd_soc_dai_link smdk2443_dai[] = { | 19 | static struct snd_soc_dai_link smdk2443_dai[] = { |
diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c index b5c3fad01bb8..e8ac961c6ba1 100644 --- a/sound/soc/samsung/smdk_spdif.c +++ b/sound/soc/samsung/smdk_spdif.c | |||
@@ -10,15 +10,10 @@ | |||
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
16 | 14 | ||
17 | #include <plat/devs.h> | ||
18 | |||
19 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
20 | 16 | ||
21 | #include "dma.h" | ||
22 | #include "spdif.h" | 17 | #include "spdif.h" |
23 | 18 | ||
24 | /* Audio clock settings are belonged to board specific part. Every | 19 | /* Audio clock settings are belonged to board specific part. Every |
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c index b2cff1a44aed..8aacf23d6f3a 100644 --- a/sound/soc/samsung/smdk_wm8580.c +++ b/sound/soc/samsung/smdk_wm8580.c | |||
@@ -10,17 +10,12 @@ | |||
10 | * option) any later version. | 10 | * option) any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/clk.h> | ||
15 | #include <sound/core.h> | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | 13 | #include <sound/soc.h> |
14 | #include <sound/pcm_params.h> | ||
19 | 15 | ||
20 | #include <asm/mach-types.h> | 16 | #include <asm/mach-types.h> |
21 | 17 | ||
22 | #include "../codecs/wm8580.h" | 18 | #include "../codecs/wm8580.h" |
23 | #include "dma.h" | ||
24 | #include "i2s.h" | 19 | #include "i2s.h" |
25 | 20 | ||
26 | /* | 21 | /* |
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c index ae5fed6f772f..fffe3c1dd1bd 100644 --- a/sound/soc/samsung/smdk_wm9713.c +++ b/sound/soc/samsung/smdk_wm9713.c | |||
@@ -11,13 +11,8 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <sound/soc.h> | 14 | #include <sound/soc.h> |
17 | 15 | ||
18 | #include "dma.h" | ||
19 | #include "ac97.h" | ||
20 | |||
21 | static struct snd_soc_card smdk; | 16 | static struct snd_soc_card smdk; |
22 | 17 | ||
23 | /* | 18 | /* |
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c index f0816404ea3e..28c491dacf7a 100644 --- a/sound/soc/samsung/spdif.c +++ b/sound/soc/samsung/spdif.c | |||
@@ -13,9 +13,8 @@ | |||
13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | 15 | ||
16 | #include <sound/pcm.h> | ||
17 | #include <sound/pcm_params.h> | ||
18 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | #include <sound/pcm_params.h> | ||
19 | 18 | ||
20 | #include <plat/audio.h> | 19 | #include <plat/audio.h> |
21 | #include <mach/dma.h> | 20 | #include <mach/dma.h> |
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index a14820ac9665..d6f4703b3c07 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c | |||
@@ -18,18 +18,26 @@ struct fsi_ak4642_data { | |||
18 | const char *cpu_dai; | 18 | const char *cpu_dai; |
19 | const char *codec; | 19 | const char *codec; |
20 | const char *platform; | 20 | const char *platform; |
21 | int id; | ||
21 | }; | 22 | }; |
22 | 23 | ||
23 | static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) | 24 | static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) |
24 | { | 25 | { |
25 | struct snd_soc_dai *dai = rtd->codec_dai; | 26 | struct snd_soc_dai *codec = rtd->codec_dai; |
27 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
26 | int ret; | 28 | int ret; |
27 | 29 | ||
28 | ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM); | 30 | ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J | |
31 | SND_SOC_DAIFMT_CBM_CFM); | ||
29 | if (ret < 0) | 32 | if (ret < 0) |
30 | return ret; | 33 | return ret; |
31 | 34 | ||
32 | ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0); | 35 | ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0); |
36 | if (ret < 0) | ||
37 | return ret; | ||
38 | |||
39 | ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J | | ||
40 | SND_SOC_DAIFMT_CBS_CFS); | ||
33 | 41 | ||
34 | return ret; | 42 | return ret; |
35 | } | 43 | } |
@@ -60,7 +68,7 @@ static int fsi_ak4642_probe(struct platform_device *pdev) | |||
60 | 68 | ||
61 | pdata = (struct fsi_ak4642_data *)id_entry->driver_data; | 69 | pdata = (struct fsi_ak4642_data *)id_entry->driver_data; |
62 | 70 | ||
63 | fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_A); | 71 | fsi_snd_device = platform_device_alloc("soc-audio", pdata->id); |
64 | if (!fsi_snd_device) | 72 | if (!fsi_snd_device) |
65 | goto out; | 73 | goto out; |
66 | 74 | ||
@@ -93,6 +101,7 @@ static struct fsi_ak4642_data fsi_a_ak4642 = { | |||
93 | .cpu_dai = "fsia-dai", | 101 | .cpu_dai = "fsia-dai", |
94 | .codec = "ak4642-codec.0-0012", | 102 | .codec = "ak4642-codec.0-0012", |
95 | .platform = "sh_fsi.0", | 103 | .platform = "sh_fsi.0", |
104 | .id = FSI_PORT_A, | ||
96 | }; | 105 | }; |
97 | 106 | ||
98 | static struct fsi_ak4642_data fsi_b_ak4642 = { | 107 | static struct fsi_ak4642_data fsi_b_ak4642 = { |
@@ -101,6 +110,7 @@ static struct fsi_ak4642_data fsi_b_ak4642 = { | |||
101 | .cpu_dai = "fsib-dai", | 110 | .cpu_dai = "fsib-dai", |
102 | .codec = "ak4642-codec.0-0012", | 111 | .codec = "ak4642-codec.0-0012", |
103 | .platform = "sh_fsi.0", | 112 | .platform = "sh_fsi.0", |
113 | .id = FSI_PORT_B, | ||
104 | }; | 114 | }; |
105 | 115 | ||
106 | static struct fsi_ak4642_data fsi_a_ak4643 = { | 116 | static struct fsi_ak4642_data fsi_a_ak4643 = { |
@@ -109,6 +119,7 @@ static struct fsi_ak4642_data fsi_a_ak4643 = { | |||
109 | .cpu_dai = "fsia-dai", | 119 | .cpu_dai = "fsia-dai", |
110 | .codec = "ak4642-codec.0-0013", | 120 | .codec = "ak4642-codec.0-0013", |
111 | .platform = "sh_fsi.0", | 121 | .platform = "sh_fsi.0", |
122 | .id = FSI_PORT_A, | ||
112 | }; | 123 | }; |
113 | 124 | ||
114 | static struct fsi_ak4642_data fsi_b_ak4643 = { | 125 | static struct fsi_ak4642_data fsi_b_ak4643 = { |
@@ -117,6 +128,7 @@ static struct fsi_ak4642_data fsi_b_ak4643 = { | |||
117 | .cpu_dai = "fsib-dai", | 128 | .cpu_dai = "fsib-dai", |
118 | .codec = "ak4642-codec.0-0013", | 129 | .codec = "ak4642-codec.0-0013", |
119 | .platform = "sh_fsi.0", | 130 | .platform = "sh_fsi.0", |
131 | .id = FSI_PORT_B, | ||
120 | }; | 132 | }; |
121 | 133 | ||
122 | static struct fsi_ak4642_data fsi2_a_ak4642 = { | 134 | static struct fsi_ak4642_data fsi2_a_ak4642 = { |
@@ -125,6 +137,7 @@ static struct fsi_ak4642_data fsi2_a_ak4642 = { | |||
125 | .cpu_dai = "fsia-dai", | 137 | .cpu_dai = "fsia-dai", |
126 | .codec = "ak4642-codec.0-0012", | 138 | .codec = "ak4642-codec.0-0012", |
127 | .platform = "sh_fsi2", | 139 | .platform = "sh_fsi2", |
140 | .id = FSI_PORT_A, | ||
128 | }; | 141 | }; |
129 | 142 | ||
130 | static struct fsi_ak4642_data fsi2_b_ak4642 = { | 143 | static struct fsi_ak4642_data fsi2_b_ak4642 = { |
@@ -133,6 +146,7 @@ static struct fsi_ak4642_data fsi2_b_ak4642 = { | |||
133 | .cpu_dai = "fsib-dai", | 146 | .cpu_dai = "fsib-dai", |
134 | .codec = "ak4642-codec.0-0012", | 147 | .codec = "ak4642-codec.0-0012", |
135 | .platform = "sh_fsi2", | 148 | .platform = "sh_fsi2", |
149 | .id = FSI_PORT_B, | ||
136 | }; | 150 | }; |
137 | 151 | ||
138 | static struct fsi_ak4642_data fsi2_a_ak4643 = { | 152 | static struct fsi_ak4642_data fsi2_a_ak4643 = { |
@@ -141,6 +155,7 @@ static struct fsi_ak4642_data fsi2_a_ak4643 = { | |||
141 | .cpu_dai = "fsia-dai", | 155 | .cpu_dai = "fsia-dai", |
142 | .codec = "ak4642-codec.0-0013", | 156 | .codec = "ak4642-codec.0-0013", |
143 | .platform = "sh_fsi2", | 157 | .platform = "sh_fsi2", |
158 | .id = FSI_PORT_A, | ||
144 | }; | 159 | }; |
145 | 160 | ||
146 | static struct fsi_ak4642_data fsi2_b_ak4643 = { | 161 | static struct fsi_ak4642_data fsi2_b_ak4643 = { |
@@ -149,6 +164,7 @@ static struct fsi_ak4642_data fsi2_b_ak4643 = { | |||
149 | .cpu_dai = "fsib-dai", | 164 | .cpu_dai = "fsib-dai", |
150 | .codec = "ak4642-codec.0-0013", | 165 | .codec = "ak4642-codec.0-0013", |
151 | .platform = "sh_fsi2", | 166 | .platform = "sh_fsi2", |
167 | .id = FSI_PORT_B, | ||
152 | }; | 168 | }; |
153 | 169 | ||
154 | static struct platform_device_id fsi_id_table[] = { | 170 | static struct platform_device_id fsi_id_table[] = { |
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index e8df9da92f71..dbafd7ac5590 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c | |||
@@ -15,11 +15,20 @@ | |||
15 | 15 | ||
16 | static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) | 16 | static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) |
17 | { | 17 | { |
18 | struct snd_soc_dai *dai = rtd->codec_dai; | 18 | struct snd_soc_dai *codec = rtd->codec_dai; |
19 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
20 | int ret; | ||
19 | 21 | ||
20 | return snd_soc_dai_set_fmt(dai, | 22 | ret = snd_soc_dai_set_fmt(codec, |
21 | SND_SOC_DAIFMT_I2S | | 23 | SND_SOC_DAIFMT_I2S | |
22 | SND_SOC_DAIFMT_CBM_CFM); | 24 | SND_SOC_DAIFMT_CBM_CFM); |
25 | if (ret < 0) | ||
26 | return ret; | ||
27 | |||
28 | ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S | | ||
29 | SND_SOC_DAIFMT_CBS_CFS); | ||
30 | |||
31 | return ret; | ||
23 | } | 32 | } |
24 | 33 | ||
25 | static struct snd_soc_dai_link fsi_da7210_dai = { | 34 | static struct snd_soc_dai_link fsi_da7210_dai = { |
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c index a52dd8ec71d3..9719985eb82d 100644 --- a/sound/soc/sh/fsi-hdmi.c +++ b/sound/soc/sh/fsi-hdmi.c | |||
@@ -12,31 +12,59 @@ | |||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <sound/sh_fsi.h> | 13 | #include <sound/sh_fsi.h> |
14 | 14 | ||
15 | struct fsi_hdmi_data { | ||
16 | const char *cpu_dai; | ||
17 | const char *card; | ||
18 | int id; | ||
19 | }; | ||
20 | |||
21 | static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
22 | { | ||
23 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
24 | int ret; | ||
25 | |||
26 | ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM); | ||
27 | |||
28 | return ret; | ||
29 | } | ||
30 | |||
15 | static struct snd_soc_dai_link fsi_dai_link = { | 31 | static struct snd_soc_dai_link fsi_dai_link = { |
16 | .name = "HDMI", | 32 | .name = "HDMI", |
17 | .stream_name = "HDMI", | 33 | .stream_name = "HDMI", |
18 | .cpu_dai_name = "fsib-dai", /* fsi B */ | ||
19 | .codec_dai_name = "sh_mobile_hdmi-hifi", | 34 | .codec_dai_name = "sh_mobile_hdmi-hifi", |
20 | .platform_name = "sh_fsi2", | 35 | .platform_name = "sh_fsi2", |
21 | .codec_name = "sh-mobile-hdmi", | 36 | .codec_name = "sh-mobile-hdmi", |
37 | .init = fsi_hdmi_dai_init, | ||
22 | }; | 38 | }; |
23 | 39 | ||
24 | static struct snd_soc_card fsi_soc_card = { | 40 | static struct snd_soc_card fsi_soc_card = { |
25 | .name = "FSI (SH MOBILE HDMI)", | ||
26 | .dai_link = &fsi_dai_link, | 41 | .dai_link = &fsi_dai_link, |
27 | .num_links = 1, | 42 | .num_links = 1, |
28 | }; | 43 | }; |
29 | 44 | ||
30 | static struct platform_device *fsi_snd_device; | 45 | static struct platform_device *fsi_snd_device; |
31 | 46 | ||
32 | static int __init fsi_hdmi_init(void) | 47 | static int fsi_hdmi_probe(struct platform_device *pdev) |
33 | { | 48 | { |
34 | int ret = -ENOMEM; | 49 | int ret = -ENOMEM; |
50 | const struct platform_device_id *id_entry; | ||
51 | struct fsi_hdmi_data *pdata; | ||
52 | |||
53 | id_entry = pdev->id_entry; | ||
54 | if (!id_entry) { | ||
55 | dev_err(&pdev->dev, "unknown fsi hdmi\n"); | ||
56 | return -ENODEV; | ||
57 | } | ||
35 | 58 | ||
36 | fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B); | 59 | pdata = (struct fsi_hdmi_data *)id_entry->driver_data; |
60 | |||
61 | fsi_snd_device = platform_device_alloc("soc-audio", pdata->id); | ||
37 | if (!fsi_snd_device) | 62 | if (!fsi_snd_device) |
38 | goto out; | 63 | goto out; |
39 | 64 | ||
65 | fsi_dai_link.cpu_dai_name = pdata->cpu_dai; | ||
66 | fsi_soc_card.name = pdata->card; | ||
67 | |||
40 | platform_set_drvdata(fsi_snd_device, &fsi_soc_card); | 68 | platform_set_drvdata(fsi_snd_device, &fsi_soc_card); |
41 | ret = platform_device_add(fsi_snd_device); | 69 | ret = platform_device_add(fsi_snd_device); |
42 | 70 | ||
@@ -47,9 +75,48 @@ out: | |||
47 | return ret; | 75 | return ret; |
48 | } | 76 | } |
49 | 77 | ||
50 | static void __exit fsi_hdmi_exit(void) | 78 | static int fsi_hdmi_remove(struct platform_device *pdev) |
51 | { | 79 | { |
52 | platform_device_unregister(fsi_snd_device); | 80 | platform_device_unregister(fsi_snd_device); |
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static struct fsi_hdmi_data fsi2_a_hdmi = { | ||
85 | .cpu_dai = "fsia-dai", | ||
86 | .card = "FSI2A (SH MOBILE HDMI)", | ||
87 | .id = FSI_PORT_A, | ||
88 | }; | ||
89 | |||
90 | static struct fsi_hdmi_data fsi2_b_hdmi = { | ||
91 | .cpu_dai = "fsib-dai", | ||
92 | .card = "FSI2B (SH MOBILE HDMI)", | ||
93 | .id = FSI_PORT_B, | ||
94 | }; | ||
95 | |||
96 | static struct platform_device_id fsi_id_table[] = { | ||
97 | /* FSI 2 */ | ||
98 | { "sh_fsi2_a_hdmi", (kernel_ulong_t)&fsi2_a_hdmi }, | ||
99 | { "sh_fsi2_b_hdmi", (kernel_ulong_t)&fsi2_b_hdmi }, | ||
100 | {}, | ||
101 | }; | ||
102 | |||
103 | static struct platform_driver fsi_hdmi = { | ||
104 | .driver = { | ||
105 | .name = "fsi-hdmi-audio", | ||
106 | }, | ||
107 | .probe = fsi_hdmi_probe, | ||
108 | .remove = fsi_hdmi_remove, | ||
109 | .id_table = fsi_id_table, | ||
110 | }; | ||
111 | |||
112 | static int __init fsi_hdmi_init(void) | ||
113 | { | ||
114 | return platform_driver_register(&fsi_hdmi); | ||
115 | } | ||
116 | |||
117 | static void __exit fsi_hdmi_exit(void) | ||
118 | { | ||
119 | platform_driver_unregister(&fsi_hdmi); | ||
53 | } | 120 | } |
54 | 121 | ||
55 | module_init(fsi_hdmi_init); | 122 | module_init(fsi_hdmi_init); |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 2b06402801ef..0c9997e2d8c0 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -78,6 +78,8 @@ | |||
78 | /* CKG1 */ | 78 | /* CKG1 */ |
79 | #define ACKMD_MASK 0x00007000 | 79 | #define ACKMD_MASK 0x00007000 |
80 | #define BPFMD_MASK 0x00000700 | 80 | #define BPFMD_MASK 0x00000700 |
81 | #define DIMD (1 << 4) | ||
82 | #define DOMD (1 << 0) | ||
81 | 83 | ||
82 | /* A/B MST_CTLR */ | 84 | /* A/B MST_CTLR */ |
83 | #define BP (1 << 4) /* Fix the signal of Biphase output */ | 85 | #define BP (1 << 4) /* Fix the signal of Biphase output */ |
@@ -111,6 +113,8 @@ | |||
111 | 113 | ||
112 | #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) | 114 | #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) |
113 | 115 | ||
116 | typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable); | ||
117 | |||
114 | /* | 118 | /* |
115 | * FSI driver use below type name for variable | 119 | * FSI driver use below type name for variable |
116 | * | 120 | * |
@@ -128,7 +132,6 @@ struct fsi_stream { | |||
128 | struct snd_pcm_substream *substream; | 132 | struct snd_pcm_substream *substream; |
129 | 133 | ||
130 | int fifo_max_num; | 134 | int fifo_max_num; |
131 | int chan_num; | ||
132 | 135 | ||
133 | int buff_offset; | 136 | int buff_offset; |
134 | int buff_len; | 137 | int buff_len; |
@@ -143,6 +146,7 @@ struct fsi_priv { | |||
143 | void __iomem *base; | 146 | void __iomem *base; |
144 | struct fsi_master *master; | 147 | struct fsi_master *master; |
145 | 148 | ||
149 | int chan_num; | ||
146 | struct fsi_stream playback; | 150 | struct fsi_stream playback; |
147 | struct fsi_stream capture; | 151 | struct fsi_stream capture; |
148 | 152 | ||
@@ -252,9 +256,8 @@ static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) | |||
252 | return rtd->cpu_dai; | 256 | return rtd->cpu_dai; |
253 | } | 257 | } |
254 | 258 | ||
255 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | 259 | static struct fsi_priv *fsi_get_priv_frm_dai(struct snd_soc_dai *dai) |
256 | { | 260 | { |
257 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
258 | struct fsi_master *master = snd_soc_dai_get_drvdata(dai); | 261 | struct fsi_master *master = snd_soc_dai_get_drvdata(dai); |
259 | 262 | ||
260 | if (dai->id == 0) | 263 | if (dai->id == 0) |
@@ -263,11 +266,27 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | |||
263 | return &master->fsib; | 266 | return &master->fsib; |
264 | } | 267 | } |
265 | 268 | ||
269 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | ||
270 | { | ||
271 | return fsi_get_priv_frm_dai(fsi_get_dai(substream)); | ||
272 | } | ||
273 | |||
274 | static set_rate_func fsi_get_info_set_rate(struct fsi_master *master) | ||
275 | { | ||
276 | if (!master->info) | ||
277 | return NULL; | ||
278 | |||
279 | return master->info->set_rate; | ||
280 | } | ||
281 | |||
266 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) | 282 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) |
267 | { | 283 | { |
268 | int is_porta = fsi_is_port_a(fsi); | 284 | int is_porta = fsi_is_port_a(fsi); |
269 | struct fsi_master *master = fsi_get_master(fsi); | 285 | struct fsi_master *master = fsi_get_master(fsi); |
270 | 286 | ||
287 | if (!master->info) | ||
288 | return 0; | ||
289 | |||
271 | return is_porta ? master->info->porta_flags : | 290 | return is_porta ? master->info->porta_flags : |
272 | master->info->portb_flags; | 291 | master->info->portb_flags; |
273 | } | 292 | } |
@@ -288,21 +307,6 @@ static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi, | |||
288 | return is_play ? &fsi->playback : &fsi->capture; | 307 | return is_play ? &fsi->playback : &fsi->capture; |
289 | } | 308 | } |
290 | 309 | ||
291 | static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play) | ||
292 | { | ||
293 | u32 mode; | ||
294 | u32 flags = fsi_get_info_flags(fsi); | ||
295 | |||
296 | mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE; | ||
297 | |||
298 | /* return | ||
299 | * 1 : master mode | ||
300 | * 0 : slave mode | ||
301 | */ | ||
302 | |||
303 | return (mode & flags) != mode; | ||
304 | } | ||
305 | |||
306 | static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) | 310 | static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) |
307 | { | 311 | { |
308 | int is_porta = fsi_is_port_a(fsi); | 312 | int is_porta = fsi_is_port_a(fsi); |
@@ -357,7 +361,6 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) | |||
357 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | 361 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) |
358 | { | 362 | { |
359 | u32 status; | 363 | u32 status; |
360 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
361 | int data_num; | 364 | int data_num; |
362 | 365 | ||
363 | status = is_play ? | 366 | status = is_play ? |
@@ -365,7 +368,7 @@ static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | |||
365 | fsi_reg_read(fsi, DIFF_ST); | 368 | fsi_reg_read(fsi, DIFF_ST); |
366 | 369 | ||
367 | data_num = 0x1ff & (status >> 8); | 370 | data_num = 0x1ff & (status >> 8); |
368 | data_num *= io->chan_num; | 371 | data_num *= fsi->chan_num; |
369 | 372 | ||
370 | return data_num; | 373 | return data_num; |
371 | } | 374 | } |
@@ -387,7 +390,7 @@ static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play) | |||
387 | struct snd_pcm_substream *substream = io->substream; | 390 | struct snd_pcm_substream *substream = io->substream; |
388 | struct snd_pcm_runtime *runtime = substream->runtime; | 391 | struct snd_pcm_runtime *runtime = substream->runtime; |
389 | 392 | ||
390 | return frames_to_bytes(runtime, 1) / io->chan_num; | 393 | return frames_to_bytes(runtime, 1) / fsi->chan_num; |
391 | } | 394 | } |
392 | 395 | ||
393 | static void fsi_count_fifo_err(struct fsi_priv *fsi) | 396 | static void fsi_count_fifo_err(struct fsi_priv *fsi) |
@@ -580,10 +583,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
580 | * 7 channels: 32 ( 32 x 7 = 224) | 583 | * 7 channels: 32 ( 32 x 7 = 224) |
581 | * 8 channels: 32 ( 32 x 8 = 256) | 584 | * 8 channels: 32 ( 32 x 8 = 256) |
582 | */ | 585 | */ |
583 | for (i = 1; i < io->chan_num; i <<= 1) | 586 | for (i = 1; i < fsi->chan_num; i <<= 1) |
584 | io->fifo_max_num >>= 1; | 587 | io->fifo_max_num >>= 1; |
585 | dev_dbg(dai->dev, "%d channel %d store\n", | 588 | dev_dbg(dai->dev, "%d channel %d store\n", |
586 | io->chan_num, io->fifo_max_num); | 589 | fsi->chan_num, io->fifo_max_num); |
587 | 590 | ||
588 | /* | 591 | /* |
589 | * set interrupt generation factor | 592 | * set interrupt generation factor |
@@ -659,7 +662,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | |||
659 | * data_num_max : number of FSI fifo free space | 662 | * data_num_max : number of FSI fifo free space |
660 | * data_num : number of ALSA residue data | 663 | * data_num : number of ALSA residue data |
661 | */ | 664 | */ |
662 | data_num_max = io->fifo_max_num * io->chan_num; | 665 | data_num_max = io->fifo_max_num * fsi->chan_num; |
663 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); | 666 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); |
664 | 667 | ||
665 | data_num = data_residue_num; | 668 | data_num = data_residue_num; |
@@ -754,25 +757,12 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
754 | struct snd_soc_dai *dai) | 757 | struct snd_soc_dai *dai) |
755 | { | 758 | { |
756 | struct fsi_priv *fsi = fsi_get_priv(substream); | 759 | struct fsi_priv *fsi = fsi_get_priv(substream); |
757 | struct fsi_master *master = fsi_get_master(fsi); | ||
758 | struct fsi_stream *io; | ||
759 | u32 flags = fsi_get_info_flags(fsi); | 760 | u32 flags = fsi_get_info_flags(fsi); |
760 | u32 fmt; | ||
761 | u32 data; | 761 | u32 data; |
762 | int is_play = fsi_is_play(substream); | 762 | int is_play = fsi_is_play(substream); |
763 | int is_master; | ||
764 | |||
765 | io = fsi_get_stream(fsi, is_play); | ||
766 | 763 | ||
767 | pm_runtime_get_sync(dai->dev); | 764 | pm_runtime_get_sync(dai->dev); |
768 | 765 | ||
769 | /* CKG1 */ | ||
770 | data = is_play ? (1 << 0) : (1 << 4); | ||
771 | is_master = fsi_is_master_mode(fsi, is_play); | ||
772 | if (is_master) | ||
773 | fsi_reg_mask_set(fsi, CKG1, data, data); | ||
774 | else | ||
775 | fsi_reg_mask_set(fsi, CKG1, data, 0); | ||
776 | 766 | ||
777 | /* clock inversion (CKG2) */ | 767 | /* clock inversion (CKG2) */ |
778 | data = 0; | 768 | data = 0; |
@@ -787,54 +777,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
787 | 777 | ||
788 | fsi_reg_write(fsi, CKG2, data); | 778 | fsi_reg_write(fsi, CKG2, data); |
789 | 779 | ||
790 | /* do fmt, di fmt */ | ||
791 | data = 0; | ||
792 | fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); | ||
793 | switch (fmt) { | ||
794 | case SH_FSI_FMT_MONO: | ||
795 | data = CR_MONO; | ||
796 | io->chan_num = 1; | ||
797 | break; | ||
798 | case SH_FSI_FMT_MONO_DELAY: | ||
799 | data = CR_MONO_D; | ||
800 | io->chan_num = 1; | ||
801 | break; | ||
802 | case SH_FSI_FMT_PCM: | ||
803 | data = CR_PCM; | ||
804 | io->chan_num = 2; | ||
805 | break; | ||
806 | case SH_FSI_FMT_I2S: | ||
807 | data = CR_I2S; | ||
808 | io->chan_num = 2; | ||
809 | break; | ||
810 | case SH_FSI_FMT_TDM: | ||
811 | io->chan_num = is_play ? | ||
812 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | ||
813 | data = CR_TDM | (io->chan_num - 1); | ||
814 | break; | ||
815 | case SH_FSI_FMT_TDM_DELAY: | ||
816 | io->chan_num = is_play ? | ||
817 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | ||
818 | data = CR_TDM_D | (io->chan_num - 1); | ||
819 | break; | ||
820 | case SH_FSI_FMT_SPDIF: | ||
821 | if (master->core->ver < 2) { | ||
822 | dev_err(dai->dev, "This FSI can not use SPDIF\n"); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; | ||
826 | io->chan_num = 2; | ||
827 | fsi_spdif_clk_ctrl(fsi, 1); | ||
828 | fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); | ||
829 | break; | ||
830 | default: | ||
831 | dev_err(dai->dev, "unknown format.\n"); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | is_play ? | ||
835 | fsi_reg_write(fsi, DO_FMT, data) : | ||
836 | fsi_reg_write(fsi, DI_FMT, data); | ||
837 | |||
838 | /* irq clear */ | 780 | /* irq clear */ |
839 | fsi_irq_disable(fsi, is_play); | 781 | fsi_irq_disable(fsi, is_play); |
840 | fsi_irq_clear_status(fsi); | 782 | fsi_irq_clear_status(fsi); |
@@ -851,12 +793,12 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
851 | struct fsi_priv *fsi = fsi_get_priv(substream); | 793 | struct fsi_priv *fsi = fsi_get_priv(substream); |
852 | int is_play = fsi_is_play(substream); | 794 | int is_play = fsi_is_play(substream); |
853 | struct fsi_master *master = fsi_get_master(fsi); | 795 | struct fsi_master *master = fsi_get_master(fsi); |
854 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); | 796 | set_rate_func set_rate; |
855 | 797 | ||
856 | fsi_irq_disable(fsi, is_play); | 798 | fsi_irq_disable(fsi, is_play); |
857 | fsi_clk_ctrl(fsi, 0); | 799 | fsi_clk_ctrl(fsi, 0); |
858 | 800 | ||
859 | set_rate = master->info->set_rate; | 801 | set_rate = fsi_get_info_set_rate(master); |
860 | if (set_rate && fsi->rate) | 802 | if (set_rate && fsi->rate) |
861 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | 803 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); |
862 | fsi->rate = 0; | 804 | fsi->rate = 0; |
@@ -889,18 +831,100 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
889 | return ret; | 831 | return ret; |
890 | } | 832 | } |
891 | 833 | ||
834 | static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt) | ||
835 | { | ||
836 | u32 data = 0; | ||
837 | |||
838 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
839 | case SND_SOC_DAIFMT_I2S: | ||
840 | data = CR_I2S; | ||
841 | fsi->chan_num = 2; | ||
842 | break; | ||
843 | case SND_SOC_DAIFMT_LEFT_J: | ||
844 | data = CR_PCM; | ||
845 | fsi->chan_num = 2; | ||
846 | break; | ||
847 | default: | ||
848 | return -EINVAL; | ||
849 | } | ||
850 | |||
851 | fsi_reg_write(fsi, DO_FMT, data); | ||
852 | fsi_reg_write(fsi, DI_FMT, data); | ||
853 | |||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | static int fsi_set_fmt_spdif(struct fsi_priv *fsi) | ||
858 | { | ||
859 | struct fsi_master *master = fsi_get_master(fsi); | ||
860 | u32 data = 0; | ||
861 | |||
862 | if (master->core->ver < 2) | ||
863 | return -EINVAL; | ||
864 | |||
865 | data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; | ||
866 | fsi->chan_num = 2; | ||
867 | fsi_spdif_clk_ctrl(fsi, 1); | ||
868 | fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); | ||
869 | |||
870 | fsi_reg_write(fsi, DO_FMT, data); | ||
871 | fsi_reg_write(fsi, DI_FMT, data); | ||
872 | |||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
877 | { | ||
878 | struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); | ||
879 | u32 flags = fsi_get_info_flags(fsi); | ||
880 | u32 data = 0; | ||
881 | int ret; | ||
882 | |||
883 | pm_runtime_get_sync(dai->dev); | ||
884 | |||
885 | /* set master/slave audio interface */ | ||
886 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
887 | case SND_SOC_DAIFMT_CBM_CFM: | ||
888 | data = DIMD | DOMD; | ||
889 | break; | ||
890 | case SND_SOC_DAIFMT_CBS_CFS: | ||
891 | break; | ||
892 | default: | ||
893 | ret = -EINVAL; | ||
894 | goto set_fmt_exit; | ||
895 | } | ||
896 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); | ||
897 | |||
898 | /* set format */ | ||
899 | switch (flags & SH_FSI_FMT_MASK) { | ||
900 | case SH_FSI_FMT_DAI: | ||
901 | ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK); | ||
902 | break; | ||
903 | case SH_FSI_FMT_SPDIF: | ||
904 | ret = fsi_set_fmt_spdif(fsi); | ||
905 | break; | ||
906 | default: | ||
907 | ret = -EINVAL; | ||
908 | } | ||
909 | |||
910 | set_fmt_exit: | ||
911 | pm_runtime_put_sync(dai->dev); | ||
912 | |||
913 | return ret; | ||
914 | } | ||
915 | |||
892 | static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | 916 | static int fsi_dai_hw_params(struct snd_pcm_substream *substream, |
893 | struct snd_pcm_hw_params *params, | 917 | struct snd_pcm_hw_params *params, |
894 | struct snd_soc_dai *dai) | 918 | struct snd_soc_dai *dai) |
895 | { | 919 | { |
896 | struct fsi_priv *fsi = fsi_get_priv(substream); | 920 | struct fsi_priv *fsi = fsi_get_priv(substream); |
897 | struct fsi_master *master = fsi_get_master(fsi); | 921 | struct fsi_master *master = fsi_get_master(fsi); |
898 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); | 922 | set_rate_func set_rate; |
899 | int fsi_ver = master->core->ver; | 923 | int fsi_ver = master->core->ver; |
900 | long rate = params_rate(params); | 924 | long rate = params_rate(params); |
901 | int ret; | 925 | int ret; |
902 | 926 | ||
903 | set_rate = master->info->set_rate; | 927 | set_rate = fsi_get_info_set_rate(master); |
904 | if (!set_rate) | 928 | if (!set_rate) |
905 | return 0; | 929 | return 0; |
906 | 930 | ||
@@ -975,6 +999,7 @@ static struct snd_soc_dai_ops fsi_dai_ops = { | |||
975 | .startup = fsi_dai_startup, | 999 | .startup = fsi_dai_startup, |
976 | .shutdown = fsi_dai_shutdown, | 1000 | .shutdown = fsi_dai_shutdown, |
977 | .trigger = fsi_dai_trigger, | 1001 | .trigger = fsi_dai_trigger, |
1002 | .set_fmt = fsi_dai_set_fmt, | ||
978 | .hw_params = fsi_dai_hw_params, | 1003 | .hw_params = fsi_dai_hw_params, |
979 | }; | 1004 | }; |
980 | 1005 | ||
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 8c2a21a978ac..5d76da43b14c 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/bitmap.h> | 18 | #include <linux/bitmap.h> |
19 | #include <linux/rbtree.h> | 19 | #include <linux/rbtree.h> |
20 | 20 | ||
21 | #include <trace/events/asoc.h> | ||
22 | |||
21 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | 23 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, |
22 | unsigned int reg) | 24 | unsigned int reg) |
23 | { | 25 | { |
@@ -25,7 +27,8 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | |||
25 | unsigned int val; | 27 | unsigned int val; |
26 | 28 | ||
27 | if (reg >= codec->driver->reg_cache_size || | 29 | if (reg >= codec->driver->reg_cache_size || |
28 | snd_soc_codec_volatile_register(codec, reg)) { | 30 | snd_soc_codec_volatile_register(codec, reg) || |
31 | codec->cache_bypass) { | ||
29 | if (codec->cache_only) | 32 | if (codec->cache_only) |
30 | return -1; | 33 | return -1; |
31 | 34 | ||
@@ -49,7 +52,8 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | |||
49 | data[1] = value & 0x00ff; | 52 | data[1] = value & 0x00ff; |
50 | 53 | ||
51 | if (!snd_soc_codec_volatile_register(codec, reg) && | 54 | if (!snd_soc_codec_volatile_register(codec, reg) && |
52 | reg < codec->driver->reg_cache_size) { | 55 | reg < codec->driver->reg_cache_size && |
56 | !codec->cache_bypass) { | ||
53 | ret = snd_soc_cache_write(codec, reg, value); | 57 | ret = snd_soc_cache_write(codec, reg, value); |
54 | if (ret < 0) | 58 | if (ret < 0) |
55 | return -1; | 59 | return -1; |
@@ -106,7 +110,8 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | |||
106 | unsigned int val; | 110 | unsigned int val; |
107 | 111 | ||
108 | if (reg >= codec->driver->reg_cache_size || | 112 | if (reg >= codec->driver->reg_cache_size || |
109 | snd_soc_codec_volatile_register(codec, reg)) { | 113 | snd_soc_codec_volatile_register(codec, reg) || |
114 | codec->cache_bypass) { | ||
110 | if (codec->cache_only) | 115 | if (codec->cache_only) |
111 | return -1; | 116 | return -1; |
112 | 117 | ||
@@ -130,7 +135,8 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, | |||
130 | data[1] = value & 0x00ff; | 135 | data[1] = value & 0x00ff; |
131 | 136 | ||
132 | if (!snd_soc_codec_volatile_register(codec, reg) && | 137 | if (!snd_soc_codec_volatile_register(codec, reg) && |
133 | reg < codec->driver->reg_cache_size) { | 138 | reg < codec->driver->reg_cache_size && |
139 | !codec->cache_bypass) { | ||
134 | ret = snd_soc_cache_write(codec, reg, value); | 140 | ret = snd_soc_cache_write(codec, reg, value); |
135 | if (ret < 0) | 141 | if (ret < 0) |
136 | return -1; | 142 | return -1; |
@@ -191,7 +197,8 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, | |||
191 | data[1] = value & 0xff; | 197 | data[1] = value & 0xff; |
192 | 198 | ||
193 | if (!snd_soc_codec_volatile_register(codec, reg) && | 199 | if (!snd_soc_codec_volatile_register(codec, reg) && |
194 | reg < codec->driver->reg_cache_size) { | 200 | reg < codec->driver->reg_cache_size && |
201 | !codec->cache_bypass) { | ||
195 | ret = snd_soc_cache_write(codec, reg, value); | 202 | ret = snd_soc_cache_write(codec, reg, value); |
196 | if (ret < 0) | 203 | if (ret < 0) |
197 | return -1; | 204 | return -1; |
@@ -216,7 +223,8 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, | |||
216 | 223 | ||
217 | reg &= 0xff; | 224 | reg &= 0xff; |
218 | if (reg >= codec->driver->reg_cache_size || | 225 | if (reg >= codec->driver->reg_cache_size || |
219 | snd_soc_codec_volatile_register(codec, reg)) { | 226 | snd_soc_codec_volatile_register(codec, reg) || |
227 | codec->cache_bypass) { | ||
220 | if (codec->cache_only) | 228 | if (codec->cache_only) |
221 | return -1; | 229 | return -1; |
222 | 230 | ||
@@ -271,7 +279,8 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, | |||
271 | data[2] = value & 0xff; | 279 | data[2] = value & 0xff; |
272 | 280 | ||
273 | if (!snd_soc_codec_volatile_register(codec, reg) && | 281 | if (!snd_soc_codec_volatile_register(codec, reg) && |
274 | reg < codec->driver->reg_cache_size) { | 282 | reg < codec->driver->reg_cache_size && |
283 | !codec->cache_bypass) { | ||
275 | ret = snd_soc_cache_write(codec, reg, value); | 284 | ret = snd_soc_cache_write(codec, reg, value); |
276 | if (ret < 0) | 285 | if (ret < 0) |
277 | return -1; | 286 | return -1; |
@@ -295,7 +304,8 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, | |||
295 | unsigned int val; | 304 | unsigned int val; |
296 | 305 | ||
297 | if (reg >= codec->driver->reg_cache_size || | 306 | if (reg >= codec->driver->reg_cache_size || |
298 | snd_soc_codec_volatile_register(codec, reg)) { | 307 | snd_soc_codec_volatile_register(codec, reg) || |
308 | codec->cache_bypass) { | ||
299 | if (codec->cache_only) | 309 | if (codec->cache_only) |
300 | return -1; | 310 | return -1; |
301 | 311 | ||
@@ -450,7 +460,8 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, | |||
450 | 460 | ||
451 | reg &= 0xff; | 461 | reg &= 0xff; |
452 | if (reg >= codec->driver->reg_cache_size || | 462 | if (reg >= codec->driver->reg_cache_size || |
453 | snd_soc_codec_volatile_register(codec, reg)) { | 463 | snd_soc_codec_volatile_register(codec, reg) || |
464 | codec->cache_bypass) { | ||
454 | if (codec->cache_only) | 465 | if (codec->cache_only) |
455 | return -1; | 466 | return -1; |
456 | 467 | ||
@@ -476,7 +487,8 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, | |||
476 | 487 | ||
477 | reg &= 0xff; | 488 | reg &= 0xff; |
478 | if (!snd_soc_codec_volatile_register(codec, reg) && | 489 | if (!snd_soc_codec_volatile_register(codec, reg) && |
479 | reg < codec->driver->reg_cache_size) { | 490 | reg < codec->driver->reg_cache_size && |
491 | !codec->cache_bypass) { | ||
480 | ret = snd_soc_cache_write(codec, reg, value); | 492 | ret = snd_soc_cache_write(codec, reg, value); |
481 | if (ret < 0) | 493 | if (ret < 0) |
482 | return -1; | 494 | return -1; |
@@ -568,7 +580,8 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, | |||
568 | unsigned int val; | 580 | unsigned int val; |
569 | 581 | ||
570 | if (reg >= codec->driver->reg_cache_size || | 582 | if (reg >= codec->driver->reg_cache_size || |
571 | snd_soc_codec_volatile_register(codec, reg)) { | 583 | snd_soc_codec_volatile_register(codec, reg) || |
584 | codec->cache_bypass) { | ||
572 | if (codec->cache_only) | 585 | if (codec->cache_only) |
573 | return -1; | 586 | return -1; |
574 | 587 | ||
@@ -595,7 +608,8 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, | |||
595 | data[3] = value & 0xff; | 608 | data[3] = value & 0xff; |
596 | 609 | ||
597 | if (!snd_soc_codec_volatile_register(codec, reg) && | 610 | if (!snd_soc_codec_volatile_register(codec, reg) && |
598 | reg < codec->driver->reg_cache_size) { | 611 | reg < codec->driver->reg_cache_size && |
612 | !codec->cache_bypass) { | ||
599 | ret = snd_soc_cache_write(codec, reg, value); | 613 | ret = snd_soc_cache_write(codec, reg, value); |
600 | if (ret < 0) | 614 | if (ret < 0) |
601 | return -1; | 615 | return -1; |
@@ -761,6 +775,49 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, | |||
761 | } | 775 | } |
762 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | 776 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); |
763 | 777 | ||
778 | static bool snd_soc_set_cache_val(void *base, unsigned int idx, | ||
779 | unsigned int val, unsigned int word_size) | ||
780 | { | ||
781 | switch (word_size) { | ||
782 | case 1: { | ||
783 | u8 *cache = base; | ||
784 | if (cache[idx] == val) | ||
785 | return true; | ||
786 | cache[idx] = val; | ||
787 | break; | ||
788 | } | ||
789 | case 2: { | ||
790 | u16 *cache = base; | ||
791 | if (cache[idx] == val) | ||
792 | return true; | ||
793 | cache[idx] = val; | ||
794 | break; | ||
795 | } | ||
796 | default: | ||
797 | BUG(); | ||
798 | } | ||
799 | return false; | ||
800 | } | ||
801 | |||
802 | static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx, | ||
803 | unsigned int word_size) | ||
804 | { | ||
805 | switch (word_size) { | ||
806 | case 1: { | ||
807 | const u8 *cache = base; | ||
808 | return cache[idx]; | ||
809 | } | ||
810 | case 2: { | ||
811 | const u16 *cache = base; | ||
812 | return cache[idx]; | ||
813 | } | ||
814 | default: | ||
815 | BUG(); | ||
816 | } | ||
817 | /* unreachable */ | ||
818 | return -1; | ||
819 | } | ||
820 | |||
764 | struct snd_soc_rbtree_node { | 821 | struct snd_soc_rbtree_node { |
765 | struct rb_node node; | 822 | struct rb_node node; |
766 | unsigned int reg; | 823 | unsigned int reg; |
@@ -835,7 +892,9 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec) | |||
835 | ret = snd_soc_cache_read(codec, rbnode->reg, &val); | 892 | ret = snd_soc_cache_read(codec, rbnode->reg, &val); |
836 | if (ret) | 893 | if (ret) |
837 | return ret; | 894 | return ret; |
895 | codec->cache_bypass = 1; | ||
838 | ret = snd_soc_write(codec, rbnode->reg, val); | 896 | ret = snd_soc_write(codec, rbnode->reg, val); |
897 | codec->cache_bypass = 0; | ||
839 | if (ret) | 898 | if (ret) |
840 | return ret; | 899 | return ret; |
841 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", | 900 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", |
@@ -924,7 +983,12 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec) | |||
924 | 983 | ||
925 | static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) | 984 | static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) |
926 | { | 985 | { |
986 | struct snd_soc_rbtree_node *rbtree_node; | ||
927 | struct snd_soc_rbtree_ctx *rbtree_ctx; | 987 | struct snd_soc_rbtree_ctx *rbtree_ctx; |
988 | unsigned int val; | ||
989 | unsigned int word_size; | ||
990 | int i; | ||
991 | int ret; | ||
928 | 992 | ||
929 | codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL); | 993 | codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL); |
930 | if (!codec->reg_cache) | 994 | if (!codec->reg_cache) |
@@ -936,53 +1000,25 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) | |||
936 | if (!codec->reg_def_copy) | 1000 | if (!codec->reg_def_copy) |
937 | return 0; | 1001 | return 0; |
938 | 1002 | ||
939 | /* | 1003 | /* |
940 | * populate the rbtree with the initialized registers. All other | 1004 | * populate the rbtree with the initialized registers. All other |
941 | * registers will be inserted into the tree when they are first written. | 1005 | * registers will be inserted when they are first modified. |
942 | * | 1006 | */ |
943 | * The reasoning behind this, is that we need to step through and | 1007 | word_size = codec->driver->reg_word_size; |
944 | * dereference the cache in u8/u16 increments without sacrificing | 1008 | for (i = 0; i < codec->driver->reg_cache_size; ++i) { |
945 | * portability. This could also be done using memcpy() but that would | 1009 | val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size); |
946 | * be slightly more cryptic. | 1010 | if (!val) |
947 | */ | 1011 | continue; |
948 | #define snd_soc_rbtree_populate(cache) \ | 1012 | rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL); |
949 | ({ \ | 1013 | if (!rbtree_node) { |
950 | int ret, i; \ | 1014 | ret = -ENOMEM; |
951 | struct snd_soc_rbtree_node *rbtree_node; \ | 1015 | snd_soc_cache_exit(codec); |
952 | \ | 1016 | break; |
953 | ret = 0; \ | 1017 | } |
954 | cache = codec->reg_def_copy; \ | 1018 | rbtree_node->reg = i; |
955 | for (i = 0; i < codec->driver->reg_cache_size; ++i) { \ | 1019 | rbtree_node->value = val; |
956 | if (!cache[i]) \ | 1020 | rbtree_node->defval = val; |
957 | continue; \ | 1021 | snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node); |
958 | rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL); \ | ||
959 | if (!rbtree_node) { \ | ||
960 | ret = -ENOMEM; \ | ||
961 | snd_soc_cache_exit(codec); \ | ||
962 | break; \ | ||
963 | } \ | ||
964 | rbtree_node->reg = i; \ | ||
965 | rbtree_node->value = cache[i]; \ | ||
966 | rbtree_node->defval = cache[i]; \ | ||
967 | snd_soc_rbtree_insert(&rbtree_ctx->root, \ | ||
968 | rbtree_node); \ | ||
969 | } \ | ||
970 | ret; \ | ||
971 | }) | ||
972 | |||
973 | switch (codec->driver->reg_word_size) { | ||
974 | case 1: { | ||
975 | const u8 *cache; | ||
976 | |||
977 | return snd_soc_rbtree_populate(cache); | ||
978 | } | ||
979 | case 2: { | ||
980 | const u16 *cache; | ||
981 | |||
982 | return snd_soc_rbtree_populate(cache); | ||
983 | } | ||
984 | default: | ||
985 | BUG(); | ||
986 | } | 1022 | } |
987 | 1023 | ||
988 | return 0; | 1024 | return 0; |
@@ -1080,34 +1116,28 @@ static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec, | |||
1080 | unsigned int reg) | 1116 | unsigned int reg) |
1081 | { | 1117 | { |
1082 | const struct snd_soc_codec_driver *codec_drv; | 1118 | const struct snd_soc_codec_driver *codec_drv; |
1083 | size_t reg_size; | ||
1084 | 1119 | ||
1085 | codec_drv = codec->driver; | 1120 | codec_drv = codec->driver; |
1086 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; | ||
1087 | return (reg * codec_drv->reg_word_size) / | 1121 | return (reg * codec_drv->reg_word_size) / |
1088 | DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()); | 1122 | DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()); |
1089 | } | 1123 | } |
1090 | 1124 | ||
1091 | static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec, | 1125 | static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec, |
1092 | unsigned int reg) | 1126 | unsigned int reg) |
1093 | { | 1127 | { |
1094 | const struct snd_soc_codec_driver *codec_drv; | 1128 | const struct snd_soc_codec_driver *codec_drv; |
1095 | size_t reg_size; | ||
1096 | 1129 | ||
1097 | codec_drv = codec->driver; | 1130 | codec_drv = codec->driver; |
1098 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; | 1131 | return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) / |
1099 | return reg % (DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()) / | ||
1100 | codec_drv->reg_word_size); | 1132 | codec_drv->reg_word_size); |
1101 | } | 1133 | } |
1102 | 1134 | ||
1103 | static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec) | 1135 | static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec) |
1104 | { | 1136 | { |
1105 | const struct snd_soc_codec_driver *codec_drv; | 1137 | const struct snd_soc_codec_driver *codec_drv; |
1106 | size_t reg_size; | ||
1107 | 1138 | ||
1108 | codec_drv = codec->driver; | 1139 | codec_drv = codec->driver; |
1109 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; | 1140 | return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()); |
1110 | return DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()); | ||
1111 | } | 1141 | } |
1112 | 1142 | ||
1113 | static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) | 1143 | static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) |
@@ -1122,7 +1152,9 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) | |||
1122 | ret = snd_soc_cache_read(codec, i, &val); | 1152 | ret = snd_soc_cache_read(codec, i, &val); |
1123 | if (ret) | 1153 | if (ret) |
1124 | return ret; | 1154 | return ret; |
1155 | codec->cache_bypass = 1; | ||
1125 | ret = snd_soc_write(codec, i, val); | 1156 | ret = snd_soc_write(codec, i, val); |
1157 | codec->cache_bypass = 0; | ||
1126 | if (ret) | 1158 | if (ret) |
1127 | return ret; | 1159 | return ret; |
1128 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", | 1160 | dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", |
@@ -1165,29 +1197,10 @@ static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec, | |||
1165 | } | 1197 | } |
1166 | 1198 | ||
1167 | /* write the new value to the cache */ | 1199 | /* write the new value to the cache */ |
1168 | switch (codec->driver->reg_word_size) { | 1200 | if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value, |
1169 | case 1: { | 1201 | codec->driver->reg_word_size)) { |
1170 | u8 *cache; | 1202 | kfree(lzo_block->dst); |
1171 | cache = lzo_block->dst; | 1203 | goto out; |
1172 | if (cache[blkpos] == value) { | ||
1173 | kfree(lzo_block->dst); | ||
1174 | goto out; | ||
1175 | } | ||
1176 | cache[blkpos] = value; | ||
1177 | } | ||
1178 | break; | ||
1179 | case 2: { | ||
1180 | u16 *cache; | ||
1181 | cache = lzo_block->dst; | ||
1182 | if (cache[blkpos] == value) { | ||
1183 | kfree(lzo_block->dst); | ||
1184 | goto out; | ||
1185 | } | ||
1186 | cache[blkpos] = value; | ||
1187 | } | ||
1188 | break; | ||
1189 | default: | ||
1190 | BUG(); | ||
1191 | } | 1204 | } |
1192 | 1205 | ||
1193 | /* prepare the source to be the decompressed block */ | 1206 | /* prepare the source to be the decompressed block */ |
@@ -1241,25 +1254,10 @@ static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec, | |||
1241 | 1254 | ||
1242 | /* decompress the block */ | 1255 | /* decompress the block */ |
1243 | ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block); | 1256 | ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block); |
1244 | if (ret >= 0) { | 1257 | if (ret >= 0) |
1245 | /* fetch the value from the cache */ | 1258 | /* fetch the value from the cache */ |
1246 | switch (codec->driver->reg_word_size) { | 1259 | *value = snd_soc_get_cache_val(lzo_block->dst, blkpos, |
1247 | case 1: { | 1260 | codec->driver->reg_word_size); |
1248 | u8 *cache; | ||
1249 | cache = lzo_block->dst; | ||
1250 | *value = cache[blkpos]; | ||
1251 | } | ||
1252 | break; | ||
1253 | case 2: { | ||
1254 | u16 *cache; | ||
1255 | cache = lzo_block->dst; | ||
1256 | *value = cache[blkpos]; | ||
1257 | } | ||
1258 | break; | ||
1259 | default: | ||
1260 | BUG(); | ||
1261 | } | ||
1262 | } | ||
1263 | 1261 | ||
1264 | kfree(lzo_block->dst); | 1262 | kfree(lzo_block->dst); |
1265 | /* restore the pointer and length of the compressed block */ | 1263 | /* restore the pointer and length of the compressed block */ |
@@ -1301,7 +1299,7 @@ static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec) | |||
1301 | static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec) | 1299 | static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec) |
1302 | { | 1300 | { |
1303 | struct snd_soc_lzo_ctx **lzo_blocks; | 1301 | struct snd_soc_lzo_ctx **lzo_blocks; |
1304 | size_t reg_size, bmp_size; | 1302 | size_t bmp_size; |
1305 | const struct snd_soc_codec_driver *codec_drv; | 1303 | const struct snd_soc_codec_driver *codec_drv; |
1306 | int ret, tofree, i, blksize, blkcount; | 1304 | int ret, tofree, i, blksize, blkcount; |
1307 | const char *p, *end; | 1305 | const char *p, *end; |
@@ -1309,7 +1307,6 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec) | |||
1309 | 1307 | ||
1310 | ret = 0; | 1308 | ret = 0; |
1311 | codec_drv = codec->driver; | 1309 | codec_drv = codec->driver; |
1312 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; | ||
1313 | 1310 | ||
1314 | /* | 1311 | /* |
1315 | * If we have not been given a default register cache | 1312 | * If we have not been given a default register cache |
@@ -1321,8 +1318,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec) | |||
1321 | tofree = 1; | 1318 | tofree = 1; |
1322 | 1319 | ||
1323 | if (!codec->reg_def_copy) { | 1320 | if (!codec->reg_def_copy) { |
1324 | codec->reg_def_copy = kzalloc(reg_size, | 1321 | codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL); |
1325 | GFP_KERNEL); | ||
1326 | if (!codec->reg_def_copy) | 1322 | if (!codec->reg_def_copy) |
1327 | return -ENOMEM; | 1323 | return -ENOMEM; |
1328 | } | 1324 | } |
@@ -1370,7 +1366,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec) | |||
1370 | 1366 | ||
1371 | blksize = snd_soc_lzo_get_blksize(codec); | 1367 | blksize = snd_soc_lzo_get_blksize(codec); |
1372 | p = codec->reg_def_copy; | 1368 | p = codec->reg_def_copy; |
1373 | end = codec->reg_def_copy + reg_size; | 1369 | end = codec->reg_def_copy + codec->reg_size; |
1374 | /* compress the register map and fill the lzo blocks */ | 1370 | /* compress the register map and fill the lzo blocks */ |
1375 | for (i = 0; i < blkcount; ++i, p += blksize) { | 1371 | for (i = 0; i < blkcount; ++i, p += blksize) { |
1376 | lzo_blocks[i]->src = p; | 1372 | lzo_blocks[i]->src = p; |
@@ -1414,28 +1410,10 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) | |||
1414 | ret = snd_soc_cache_read(codec, i, &val); | 1410 | ret = snd_soc_cache_read(codec, i, &val); |
1415 | if (ret) | 1411 | if (ret) |
1416 | return ret; | 1412 | return ret; |
1417 | if (codec_drv->reg_cache_default) { | 1413 | if (codec->reg_def_copy) |
1418 | switch (codec_drv->reg_word_size) { | 1414 | if (snd_soc_get_cache_val(codec->reg_def_copy, |
1419 | case 1: { | 1415 | i, codec_drv->reg_word_size) == val) |
1420 | const u8 *cache; | 1416 | continue; |
1421 | |||
1422 | cache = codec_drv->reg_cache_default; | ||
1423 | if (cache[i] == val) | ||
1424 | continue; | ||
1425 | } | ||
1426 | break; | ||
1427 | case 2: { | ||
1428 | const u16 *cache; | ||
1429 | |||
1430 | cache = codec_drv->reg_cache_default; | ||
1431 | if (cache[i] == val) | ||
1432 | continue; | ||
1433 | } | ||
1434 | break; | ||
1435 | default: | ||
1436 | BUG(); | ||
1437 | } | ||
1438 | } | ||
1439 | ret = snd_soc_write(codec, i, val); | 1417 | ret = snd_soc_write(codec, i, val); |
1440 | if (ret) | 1418 | if (ret) |
1441 | return ret; | 1419 | return ret; |
@@ -1448,50 +1426,16 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) | |||
1448 | static int snd_soc_flat_cache_write(struct snd_soc_codec *codec, | 1426 | static int snd_soc_flat_cache_write(struct snd_soc_codec *codec, |
1449 | unsigned int reg, unsigned int value) | 1427 | unsigned int reg, unsigned int value) |
1450 | { | 1428 | { |
1451 | switch (codec->driver->reg_word_size) { | 1429 | snd_soc_set_cache_val(codec->reg_cache, reg, value, |
1452 | case 1: { | 1430 | codec->driver->reg_word_size); |
1453 | u8 *cache; | ||
1454 | |||
1455 | cache = codec->reg_cache; | ||
1456 | cache[reg] = value; | ||
1457 | } | ||
1458 | break; | ||
1459 | case 2: { | ||
1460 | u16 *cache; | ||
1461 | |||
1462 | cache = codec->reg_cache; | ||
1463 | cache[reg] = value; | ||
1464 | } | ||
1465 | break; | ||
1466 | default: | ||
1467 | BUG(); | ||
1468 | } | ||
1469 | |||
1470 | return 0; | 1431 | return 0; |
1471 | } | 1432 | } |
1472 | 1433 | ||
1473 | static int snd_soc_flat_cache_read(struct snd_soc_codec *codec, | 1434 | static int snd_soc_flat_cache_read(struct snd_soc_codec *codec, |
1474 | unsigned int reg, unsigned int *value) | 1435 | unsigned int reg, unsigned int *value) |
1475 | { | 1436 | { |
1476 | switch (codec->driver->reg_word_size) { | 1437 | *value = snd_soc_get_cache_val(codec->reg_cache, reg, |
1477 | case 1: { | 1438 | codec->driver->reg_word_size); |
1478 | u8 *cache; | ||
1479 | |||
1480 | cache = codec->reg_cache; | ||
1481 | *value = cache[reg]; | ||
1482 | } | ||
1483 | break; | ||
1484 | case 2: { | ||
1485 | u16 *cache; | ||
1486 | |||
1487 | cache = codec->reg_cache; | ||
1488 | *value = cache[reg]; | ||
1489 | } | ||
1490 | break; | ||
1491 | default: | ||
1492 | BUG(); | ||
1493 | } | ||
1494 | |||
1495 | return 0; | 1439 | return 0; |
1496 | } | 1440 | } |
1497 | 1441 | ||
@@ -1507,24 +1451,14 @@ static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec) | |||
1507 | static int snd_soc_flat_cache_init(struct snd_soc_codec *codec) | 1451 | static int snd_soc_flat_cache_init(struct snd_soc_codec *codec) |
1508 | { | 1452 | { |
1509 | const struct snd_soc_codec_driver *codec_drv; | 1453 | const struct snd_soc_codec_driver *codec_drv; |
1510 | size_t reg_size; | ||
1511 | 1454 | ||
1512 | codec_drv = codec->driver; | 1455 | codec_drv = codec->driver; |
1513 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; | ||
1514 | 1456 | ||
1515 | /* | 1457 | if (codec->reg_def_copy) |
1516 | * for flat compression, we don't need to keep a copy of the | 1458 | codec->reg_cache = kmemdup(codec->reg_def_copy, |
1517 | * original defaults register cache as it will definitely not | 1459 | codec->reg_size, GFP_KERNEL); |
1518 | * be marked as __devinitconst | ||
1519 | */ | ||
1520 | kfree(codec->reg_def_copy); | ||
1521 | codec->reg_def_copy = NULL; | ||
1522 | |||
1523 | if (codec_drv->reg_cache_default) | ||
1524 | codec->reg_cache = kmemdup(codec_drv->reg_cache_default, | ||
1525 | reg_size, GFP_KERNEL); | ||
1526 | else | 1460 | else |
1527 | codec->reg_cache = kzalloc(reg_size, GFP_KERNEL); | 1461 | codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL); |
1528 | if (!codec->reg_cache) | 1462 | if (!codec->reg_cache) |
1529 | return -ENOMEM; | 1463 | return -ENOMEM; |
1530 | 1464 | ||
@@ -1669,21 +1603,77 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write); | |||
1669 | int snd_soc_cache_sync(struct snd_soc_codec *codec) | 1603 | int snd_soc_cache_sync(struct snd_soc_codec *codec) |
1670 | { | 1604 | { |
1671 | int ret; | 1605 | int ret; |
1606 | const char *name; | ||
1672 | 1607 | ||
1673 | if (!codec->cache_sync) { | 1608 | if (!codec->cache_sync) { |
1674 | return 0; | 1609 | return 0; |
1675 | } | 1610 | } |
1676 | 1611 | ||
1677 | if (codec->cache_ops && codec->cache_ops->sync) { | 1612 | if (!codec->cache_ops || !codec->cache_ops->sync) |
1678 | if (codec->cache_ops->name) | 1613 | return -EINVAL; |
1679 | dev_dbg(codec->dev, "Syncing %s cache for %s codec\n", | ||
1680 | codec->cache_ops->name, codec->name); | ||
1681 | ret = codec->cache_ops->sync(codec); | ||
1682 | if (!ret) | ||
1683 | codec->cache_sync = 0; | ||
1684 | return ret; | ||
1685 | } | ||
1686 | 1614 | ||
1687 | return -EINVAL; | 1615 | if (codec->cache_ops->name) |
1616 | name = codec->cache_ops->name; | ||
1617 | else | ||
1618 | name = "unknown"; | ||
1619 | |||
1620 | if (codec->cache_ops->name) | ||
1621 | dev_dbg(codec->dev, "Syncing %s cache for %s codec\n", | ||
1622 | codec->cache_ops->name, codec->name); | ||
1623 | trace_snd_soc_cache_sync(codec, name, "start"); | ||
1624 | ret = codec->cache_ops->sync(codec); | ||
1625 | if (!ret) | ||
1626 | codec->cache_sync = 0; | ||
1627 | trace_snd_soc_cache_sync(codec, name, "end"); | ||
1628 | return ret; | ||
1688 | } | 1629 | } |
1689 | EXPORT_SYMBOL_GPL(snd_soc_cache_sync); | 1630 | EXPORT_SYMBOL_GPL(snd_soc_cache_sync); |
1631 | |||
1632 | static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec, | ||
1633 | unsigned int reg) | ||
1634 | { | ||
1635 | const struct snd_soc_codec_driver *codec_drv; | ||
1636 | unsigned int min, max, index; | ||
1637 | |||
1638 | codec_drv = codec->driver; | ||
1639 | min = 0; | ||
1640 | max = codec_drv->reg_access_size - 1; | ||
1641 | do { | ||
1642 | index = (min + max) / 2; | ||
1643 | if (codec_drv->reg_access_default[index].reg == reg) | ||
1644 | return index; | ||
1645 | if (codec_drv->reg_access_default[index].reg < reg) | ||
1646 | min = index + 1; | ||
1647 | else | ||
1648 | max = index; | ||
1649 | } while (min <= max); | ||
1650 | return -1; | ||
1651 | } | ||
1652 | |||
1653 | int snd_soc_default_volatile_register(struct snd_soc_codec *codec, | ||
1654 | unsigned int reg) | ||
1655 | { | ||
1656 | int index; | ||
1657 | |||
1658 | if (reg >= codec->driver->reg_cache_size) | ||
1659 | return 1; | ||
1660 | index = snd_soc_get_reg_access_index(codec, reg); | ||
1661 | if (index < 0) | ||
1662 | return 0; | ||
1663 | return codec->driver->reg_access_default[index].vol; | ||
1664 | } | ||
1665 | EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register); | ||
1666 | |||
1667 | int snd_soc_default_readable_register(struct snd_soc_codec *codec, | ||
1668 | unsigned int reg) | ||
1669 | { | ||
1670 | int index; | ||
1671 | |||
1672 | if (reg >= codec->driver->reg_cache_size) | ||
1673 | return 1; | ||
1674 | index = snd_soc_get_reg_access_index(codec, reg); | ||
1675 | if (index < 0) | ||
1676 | return 0; | ||
1677 | return codec->driver->reg_access_default[index].read; | ||
1678 | } | ||
1679 | EXPORT_SYMBOL_GPL(snd_soc_default_readable_register); | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c3f6f1e72790..17efacdb248a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -48,7 +48,8 @@ static DEFINE_MUTEX(pcm_mutex); | |||
48 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); | 48 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); |
49 | 49 | ||
50 | #ifdef CONFIG_DEBUG_FS | 50 | #ifdef CONFIG_DEBUG_FS |
51 | static struct dentry *debugfs_root; | 51 | struct dentry *snd_soc_debugfs_root; |
52 | EXPORT_SYMBOL_GPL(snd_soc_debugfs_root); | ||
52 | #endif | 53 | #endif |
53 | 54 | ||
54 | static DEFINE_MUTEX(client_mutex); | 55 | static DEFINE_MUTEX(client_mutex); |
@@ -57,8 +58,6 @@ static LIST_HEAD(dai_list); | |||
57 | static LIST_HEAD(platform_list); | 58 | static LIST_HEAD(platform_list); |
58 | static LIST_HEAD(codec_list); | 59 | static LIST_HEAD(codec_list); |
59 | 60 | ||
60 | static int snd_soc_register_card(struct snd_soc_card *card); | ||
61 | static int snd_soc_unregister_card(struct snd_soc_card *card); | ||
62 | static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); | 61 | static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); |
63 | 62 | ||
64 | /* | 63 | /* |
@@ -70,10 +69,73 @@ static int pmdown_time = 5000; | |||
70 | module_param(pmdown_time, int, 0); | 69 | module_param(pmdown_time, int, 0); |
71 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
72 | 71 | ||
72 | /* returns the minimum number of bytes needed to represent | ||
73 | * a particular given value */ | ||
74 | static int min_bytes_needed(unsigned long val) | ||
75 | { | ||
76 | int c = 0; | ||
77 | int i; | ||
78 | |||
79 | for (i = (sizeof val * 8) - 1; i >= 0; --i, ++c) | ||
80 | if (val & (1UL << i)) | ||
81 | break; | ||
82 | c = (sizeof val * 8) - c; | ||
83 | if (!c || (c % 8)) | ||
84 | c = (c + 8) / 8; | ||
85 | else | ||
86 | c /= 8; | ||
87 | return c; | ||
88 | } | ||
89 | |||
90 | /* fill buf which is 'len' bytes with a formatted | ||
91 | * string of the form 'reg: value\n' */ | ||
92 | static int format_register_str(struct snd_soc_codec *codec, | ||
93 | unsigned int reg, char *buf, size_t len) | ||
94 | { | ||
95 | int wordsize = codec->driver->reg_word_size * 2; | ||
96 | int regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2; | ||
97 | int ret; | ||
98 | char tmpbuf[len + 1]; | ||
99 | char regbuf[regsize + 1]; | ||
100 | |||
101 | /* since tmpbuf is allocated on the stack, warn the callers if they | ||
102 | * try to abuse this function */ | ||
103 | WARN_ON(len > 63); | ||
104 | |||
105 | /* +2 for ': ' and + 1 for '\n' */ | ||
106 | if (wordsize + regsize + 2 + 1 != len) | ||
107 | return -EINVAL; | ||
108 | |||
109 | ret = snd_soc_read(codec , reg); | ||
110 | if (ret < 0) { | ||
111 | memset(regbuf, 'X', regsize); | ||
112 | regbuf[regsize] = '\0'; | ||
113 | } else { | ||
114 | snprintf(regbuf, regsize + 1, "%.*x", regsize, ret); | ||
115 | } | ||
116 | |||
117 | /* prepare the buffer */ | ||
118 | snprintf(tmpbuf, len + 1, "%.*x: %s\n", wordsize, reg, regbuf); | ||
119 | /* copy it back to the caller without the '\0' */ | ||
120 | memcpy(buf, tmpbuf, len); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
73 | /* codec register dump */ | 125 | /* codec register dump */ |
74 | static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | 126 | static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf, |
127 | size_t count, loff_t pos) | ||
75 | { | 128 | { |
76 | int ret, i, step = 1, count = 0; | 129 | int i, step = 1; |
130 | int wordsize, regsize; | ||
131 | int len; | ||
132 | size_t total = 0; | ||
133 | loff_t p = 0; | ||
134 | |||
135 | wordsize = codec->driver->reg_word_size * 2; | ||
136 | regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2; | ||
137 | |||
138 | len = wordsize + regsize + 2 + 1; | ||
77 | 139 | ||
78 | if (!codec->driver->reg_cache_size) | 140 | if (!codec->driver->reg_cache_size) |
79 | return 0; | 141 | return 0; |
@@ -81,55 +143,37 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | |||
81 | if (codec->driver->reg_cache_step) | 143 | if (codec->driver->reg_cache_step) |
82 | step = codec->driver->reg_cache_step; | 144 | step = codec->driver->reg_cache_step; |
83 | 145 | ||
84 | count += sprintf(buf, "%s registers\n", codec->name); | ||
85 | for (i = 0; i < codec->driver->reg_cache_size; i += step) { | 146 | for (i = 0; i < codec->driver->reg_cache_size; i += step) { |
86 | if (codec->driver->readable_register && !codec->driver->readable_register(i)) | 147 | if (codec->readable_register && !codec->readable_register(codec, i)) |
87 | continue; | 148 | continue; |
88 | |||
89 | count += sprintf(buf + count, "%2x: ", i); | ||
90 | if (count >= PAGE_SIZE - 1) | ||
91 | break; | ||
92 | |||
93 | if (codec->driver->display_register) { | 149 | if (codec->driver->display_register) { |
94 | count += codec->driver->display_register(codec, buf + count, | 150 | count += codec->driver->display_register(codec, buf + count, |
95 | PAGE_SIZE - count, i); | 151 | PAGE_SIZE - count, i); |
96 | } else { | 152 | } else { |
97 | /* If the read fails it's almost certainly due to | 153 | /* only support larger than PAGE_SIZE bytes debugfs |
98 | * the register being volatile and the device being | 154 | * entries for the default case */ |
99 | * powered off. | 155 | if (p >= pos) { |
100 | */ | 156 | if (total + len >= count - 1) |
101 | ret = snd_soc_read(codec, i); | 157 | break; |
102 | if (ret >= 0) | 158 | format_register_str(codec, i, buf + total, len); |
103 | count += snprintf(buf + count, | 159 | total += len; |
104 | PAGE_SIZE - count, | 160 | } |
105 | "%4x", ret); | 161 | p += len; |
106 | else | ||
107 | count += snprintf(buf + count, | ||
108 | PAGE_SIZE - count, | ||
109 | "<no data: %d>", ret); | ||
110 | } | 162 | } |
111 | |||
112 | if (count >= PAGE_SIZE - 1) | ||
113 | break; | ||
114 | |||
115 | count += snprintf(buf + count, PAGE_SIZE - count, "\n"); | ||
116 | if (count >= PAGE_SIZE - 1) | ||
117 | break; | ||
118 | } | 163 | } |
119 | 164 | ||
120 | /* Truncate count; min() would cause a warning */ | 165 | total = min(total, count - 1); |
121 | if (count >= PAGE_SIZE) | ||
122 | count = PAGE_SIZE - 1; | ||
123 | 166 | ||
124 | return count; | 167 | return total; |
125 | } | 168 | } |
169 | |||
126 | static ssize_t codec_reg_show(struct device *dev, | 170 | static ssize_t codec_reg_show(struct device *dev, |
127 | struct device_attribute *attr, char *buf) | 171 | struct device_attribute *attr, char *buf) |
128 | { | 172 | { |
129 | struct snd_soc_pcm_runtime *rtd = | 173 | struct snd_soc_pcm_runtime *rtd = |
130 | container_of(dev, struct snd_soc_pcm_runtime, dev); | 174 | container_of(dev, struct snd_soc_pcm_runtime, dev); |
131 | 175 | ||
132 | return soc_codec_reg_show(rtd->codec, buf); | 176 | return soc_codec_reg_show(rtd->codec, buf, PAGE_SIZE, 0); |
133 | } | 177 | } |
134 | 178 | ||
135 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 179 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
@@ -168,16 +212,28 @@ static int codec_reg_open_file(struct inode *inode, struct file *file) | |||
168 | } | 212 | } |
169 | 213 | ||
170 | static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, | 214 | static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, |
171 | size_t count, loff_t *ppos) | 215 | size_t count, loff_t *ppos) |
172 | { | 216 | { |
173 | ssize_t ret; | 217 | ssize_t ret; |
174 | struct snd_soc_codec *codec = file->private_data; | 218 | struct snd_soc_codec *codec = file->private_data; |
175 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | 219 | char *buf; |
220 | |||
221 | if (*ppos < 0 || !count) | ||
222 | return -EINVAL; | ||
223 | |||
224 | buf = kmalloc(count, GFP_KERNEL); | ||
176 | if (!buf) | 225 | if (!buf) |
177 | return -ENOMEM; | 226 | return -ENOMEM; |
178 | ret = soc_codec_reg_show(codec, buf); | 227 | |
179 | if (ret >= 0) | 228 | ret = soc_codec_reg_show(codec, buf, count, *ppos); |
180 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | 229 | if (ret >= 0) { |
230 | if (copy_to_user(user_buf, buf, ret)) { | ||
231 | kfree(buf); | ||
232 | return -EFAULT; | ||
233 | } | ||
234 | *ppos += ret; | ||
235 | } | ||
236 | |||
181 | kfree(buf); | 237 | kfree(buf); |
182 | return ret; | 238 | return ret; |
183 | } | 239 | } |
@@ -209,6 +265,10 @@ static ssize_t codec_reg_write_file(struct file *file, | |||
209 | start++; | 265 | start++; |
210 | if (strict_strtoul(start, 16, &value)) | 266 | if (strict_strtoul(start, 16, &value)) |
211 | return -EINVAL; | 267 | return -EINVAL; |
268 | |||
269 | /* Userspace has been fiddling around behind the kernel's back */ | ||
270 | add_taint(TAINT_USER); | ||
271 | |||
212 | snd_soc_write(codec, reg, value); | 272 | snd_soc_write(codec, reg, value); |
213 | return buf_size; | 273 | return buf_size; |
214 | } | 274 | } |
@@ -232,6 +292,11 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | |||
232 | return; | 292 | return; |
233 | } | 293 | } |
234 | 294 | ||
295 | debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root, | ||
296 | &codec->cache_sync); | ||
297 | debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root, | ||
298 | &codec->cache_only); | ||
299 | |||
235 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | 300 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, |
236 | codec->debugfs_codec_root, | 301 | codec->debugfs_codec_root, |
237 | codec, &codec_reg_fops); | 302 | codec, &codec_reg_fops); |
@@ -356,7 +421,7 @@ static const struct file_operations platform_list_fops = { | |||
356 | static void soc_init_card_debugfs(struct snd_soc_card *card) | 421 | static void soc_init_card_debugfs(struct snd_soc_card *card) |
357 | { | 422 | { |
358 | card->debugfs_card_root = debugfs_create_dir(card->name, | 423 | card->debugfs_card_root = debugfs_create_dir(card->name, |
359 | debugfs_root); | 424 | snd_soc_debugfs_root); |
360 | if (!card->debugfs_card_root) { | 425 | if (!card->debugfs_card_root) { |
361 | dev_warn(card->dev, | 426 | dev_warn(card->dev, |
362 | "ASoC: Failed to create codec debugfs directory\n"); | 427 | "ASoC: Failed to create codec debugfs directory\n"); |
@@ -435,20 +500,30 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) | |||
435 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 500 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
436 | int ret; | 501 | int ret; |
437 | 502 | ||
438 | if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates || | 503 | if (!codec_dai->driver->symmetric_rates && |
439 | rtd->dai_link->symmetric_rates) { | 504 | !cpu_dai->driver->symmetric_rates && |
440 | dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", | 505 | !rtd->dai_link->symmetric_rates) |
441 | rtd->rate); | 506 | return 0; |
442 | 507 | ||
443 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | 508 | /* This can happen if multiple streams are starting simultaneously - |
444 | SNDRV_PCM_HW_PARAM_RATE, | 509 | * the second can need to get its constraints before the first has |
445 | rtd->rate, | 510 | * picked a rate. Complain and allow the application to carry on. |
446 | rtd->rate); | 511 | */ |
447 | if (ret < 0) { | 512 | if (!rtd->rate) { |
448 | dev_err(&rtd->dev, | 513 | dev_warn(&rtd->dev, |
449 | "Unable to apply rate symmetry constraint: %d\n", ret); | 514 | "Not enforcing symmetric_rates due to race\n"); |
450 | return ret; | 515 | return 0; |
451 | } | 516 | } |
517 | |||
518 | dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate); | ||
519 | |||
520 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, | ||
521 | SNDRV_PCM_HW_PARAM_RATE, | ||
522 | rtd->rate, rtd->rate); | ||
523 | if (ret < 0) { | ||
524 | dev_err(&rtd->dev, | ||
525 | "Unable to apply rate symmetry constraint: %d\n", ret); | ||
526 | return ret; | ||
452 | } | 527 | } |
453 | 528 | ||
454 | return 0; | 529 | return 0; |
@@ -962,12 +1037,11 @@ static struct snd_pcm_ops soc_pcm_ops = { | |||
962 | .pointer = soc_pcm_pointer, | 1037 | .pointer = soc_pcm_pointer, |
963 | }; | 1038 | }; |
964 | 1039 | ||
965 | #ifdef CONFIG_PM | 1040 | #ifdef CONFIG_PM_SLEEP |
966 | /* powers down audio subsystem for suspend */ | 1041 | /* powers down audio subsystem for suspend */ |
967 | static int soc_suspend(struct device *dev) | 1042 | int snd_soc_suspend(struct device *dev) |
968 | { | 1043 | { |
969 | struct platform_device *pdev = to_platform_device(dev); | 1044 | struct snd_soc_card *card = dev_get_drvdata(dev); |
970 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
971 | struct snd_soc_codec *codec; | 1045 | struct snd_soc_codec *codec; |
972 | int i; | 1046 | int i; |
973 | 1047 | ||
@@ -1008,7 +1082,7 @@ static int soc_suspend(struct device *dev) | |||
1008 | } | 1082 | } |
1009 | 1083 | ||
1010 | if (card->suspend_pre) | 1084 | if (card->suspend_pre) |
1011 | card->suspend_pre(pdev, PMSG_SUSPEND); | 1085 | card->suspend_pre(card); |
1012 | 1086 | ||
1013 | for (i = 0; i < card->num_rtd; i++) { | 1087 | for (i = 0; i < card->num_rtd; i++) { |
1014 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 1088 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
@@ -1075,10 +1149,11 @@ static int soc_suspend(struct device *dev) | |||
1075 | } | 1149 | } |
1076 | 1150 | ||
1077 | if (card->suspend_post) | 1151 | if (card->suspend_post) |
1078 | card->suspend_post(pdev, PMSG_SUSPEND); | 1152 | card->suspend_post(card); |
1079 | 1153 | ||
1080 | return 0; | 1154 | return 0; |
1081 | } | 1155 | } |
1156 | EXPORT_SYMBOL_GPL(snd_soc_suspend); | ||
1082 | 1157 | ||
1083 | /* deferred resume work, so resume can complete before we finished | 1158 | /* deferred resume work, so resume can complete before we finished |
1084 | * setting our codec back up, which can be very slow on I2C | 1159 | * setting our codec back up, which can be very slow on I2C |
@@ -1087,7 +1162,6 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1087 | { | 1162 | { |
1088 | struct snd_soc_card *card = | 1163 | struct snd_soc_card *card = |
1089 | container_of(work, struct snd_soc_card, deferred_resume_work); | 1164 | container_of(work, struct snd_soc_card, deferred_resume_work); |
1090 | struct platform_device *pdev = to_platform_device(card->dev); | ||
1091 | struct snd_soc_codec *codec; | 1165 | struct snd_soc_codec *codec; |
1092 | int i; | 1166 | int i; |
1093 | 1167 | ||
@@ -1101,7 +1175,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1101 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); | 1175 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2); |
1102 | 1176 | ||
1103 | if (card->resume_pre) | 1177 | if (card->resume_pre) |
1104 | card->resume_pre(pdev); | 1178 | card->resume_pre(card); |
1105 | 1179 | ||
1106 | /* resume AC97 DAIs */ | 1180 | /* resume AC97 DAIs */ |
1107 | for (i = 0; i < card->num_rtd; i++) { | 1181 | for (i = 0; i < card->num_rtd; i++) { |
@@ -1176,7 +1250,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1176 | } | 1250 | } |
1177 | 1251 | ||
1178 | if (card->resume_post) | 1252 | if (card->resume_post) |
1179 | card->resume_post(pdev); | 1253 | card->resume_post(card); |
1180 | 1254 | ||
1181 | dev_dbg(card->dev, "resume work completed\n"); | 1255 | dev_dbg(card->dev, "resume work completed\n"); |
1182 | 1256 | ||
@@ -1185,10 +1259,9 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1185 | } | 1259 | } |
1186 | 1260 | ||
1187 | /* powers up audio subsystem after a suspend */ | 1261 | /* powers up audio subsystem after a suspend */ |
1188 | static int soc_resume(struct device *dev) | 1262 | int snd_soc_resume(struct device *dev) |
1189 | { | 1263 | { |
1190 | struct platform_device *pdev = to_platform_device(dev); | 1264 | struct snd_soc_card *card = dev_get_drvdata(dev); |
1191 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1192 | int i; | 1265 | int i; |
1193 | 1266 | ||
1194 | /* AC97 devices might have other drivers hanging off them so | 1267 | /* AC97 devices might have other drivers hanging off them so |
@@ -1210,9 +1283,10 @@ static int soc_resume(struct device *dev) | |||
1210 | 1283 | ||
1211 | return 0; | 1284 | return 0; |
1212 | } | 1285 | } |
1286 | EXPORT_SYMBOL_GPL(snd_soc_resume); | ||
1213 | #else | 1287 | #else |
1214 | #define soc_suspend NULL | 1288 | #define snd_soc_suspend NULL |
1215 | #define soc_resume NULL | 1289 | #define snd_soc_resume NULL |
1216 | #endif | 1290 | #endif |
1217 | 1291 | ||
1218 | static struct snd_soc_dai_ops null_dai_ops = { | 1292 | static struct snd_soc_dai_ops null_dai_ops = { |
@@ -1400,31 +1474,44 @@ static int soc_probe_codec(struct snd_soc_card *card, | |||
1400 | struct snd_soc_codec *codec) | 1474 | struct snd_soc_codec *codec) |
1401 | { | 1475 | { |
1402 | int ret = 0; | 1476 | int ret = 0; |
1477 | const struct snd_soc_codec_driver *driver = codec->driver; | ||
1403 | 1478 | ||
1404 | codec->card = card; | 1479 | codec->card = card; |
1405 | codec->dapm.card = card; | 1480 | codec->dapm.card = card; |
1406 | soc_set_name_prefix(card, codec); | 1481 | soc_set_name_prefix(card, codec); |
1407 | 1482 | ||
1408 | if (codec->driver->probe) { | 1483 | if (!try_module_get(codec->dev->driver->owner)) |
1409 | ret = codec->driver->probe(codec); | 1484 | return -ENODEV; |
1485 | |||
1486 | if (driver->probe) { | ||
1487 | ret = driver->probe(codec); | ||
1410 | if (ret < 0) { | 1488 | if (ret < 0) { |
1411 | dev_err(codec->dev, | 1489 | dev_err(codec->dev, |
1412 | "asoc: failed to probe CODEC %s: %d\n", | 1490 | "asoc: failed to probe CODEC %s: %d\n", |
1413 | codec->name, ret); | 1491 | codec->name, ret); |
1414 | return ret; | 1492 | goto err_probe; |
1415 | } | 1493 | } |
1416 | } | 1494 | } |
1417 | 1495 | ||
1496 | if (driver->dapm_widgets) | ||
1497 | snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets, | ||
1498 | driver->num_dapm_widgets); | ||
1499 | if (driver->dapm_routes) | ||
1500 | snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes, | ||
1501 | driver->num_dapm_routes); | ||
1502 | |||
1418 | soc_init_codec_debugfs(codec); | 1503 | soc_init_codec_debugfs(codec); |
1419 | 1504 | ||
1420 | /* mark codec as probed and add to card codec list */ | 1505 | /* mark codec as probed and add to card codec list */ |
1421 | if (!try_module_get(codec->dev->driver->owner)) | ||
1422 | return -ENODEV; | ||
1423 | |||
1424 | codec->probed = 1; | 1506 | codec->probed = 1; |
1425 | list_add(&codec->card_list, &card->codec_dev_list); | 1507 | list_add(&codec->card_list, &card->codec_dev_list); |
1426 | list_add(&codec->dapm.list, &card->dapm_list); | 1508 | list_add(&codec->dapm.list, &card->dapm_list); |
1427 | 1509 | ||
1510 | return 0; | ||
1511 | |||
1512 | err_probe: | ||
1513 | module_put(codec->dev->driver->owner); | ||
1514 | |||
1428 | return ret; | 1515 | return ret; |
1429 | } | 1516 | } |
1430 | 1517 | ||
@@ -1468,7 +1555,6 @@ static int soc_post_component_init(struct snd_soc_card *card, | |||
1468 | 1555 | ||
1469 | /* Make sure all DAPM widgets are instantiated */ | 1556 | /* Make sure all DAPM widgets are instantiated */ |
1470 | snd_soc_dapm_new_widgets(&codec->dapm); | 1557 | snd_soc_dapm_new_widgets(&codec->dapm); |
1471 | snd_soc_dapm_sync(&codec->dapm); | ||
1472 | 1558 | ||
1473 | /* register the rtd device */ | 1559 | /* register the rtd device */ |
1474 | rtd->codec = codec; | 1560 | rtd->codec = codec; |
@@ -1543,19 +1629,19 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1543 | 1629 | ||
1544 | /* probe the platform */ | 1630 | /* probe the platform */ |
1545 | if (!platform->probed) { | 1631 | if (!platform->probed) { |
1632 | if (!try_module_get(platform->dev->driver->owner)) | ||
1633 | return -ENODEV; | ||
1634 | |||
1546 | if (platform->driver->probe) { | 1635 | if (platform->driver->probe) { |
1547 | ret = platform->driver->probe(platform); | 1636 | ret = platform->driver->probe(platform); |
1548 | if (ret < 0) { | 1637 | if (ret < 0) { |
1549 | printk(KERN_ERR "asoc: failed to probe platform %s\n", | 1638 | printk(KERN_ERR "asoc: failed to probe platform %s\n", |
1550 | platform->name); | 1639 | platform->name); |
1640 | module_put(platform->dev->driver->owner); | ||
1551 | return ret; | 1641 | return ret; |
1552 | } | 1642 | } |
1553 | } | 1643 | } |
1554 | /* mark platform as probed and add to card platform list */ | 1644 | /* mark platform as probed and add to card platform list */ |
1555 | |||
1556 | if (!try_module_get(platform->dev->driver->owner)) | ||
1557 | return -ENODEV; | ||
1558 | |||
1559 | platform->probed = 1; | 1645 | platform->probed = 1; |
1560 | list_add(&platform->card_list, &card->platform_dev_list); | 1646 | list_add(&platform->card_list, &card->platform_dev_list); |
1561 | } | 1647 | } |
@@ -1713,7 +1799,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, | |||
1713 | 1799 | ||
1714 | static void snd_soc_instantiate_card(struct snd_soc_card *card) | 1800 | static void snd_soc_instantiate_card(struct snd_soc_card *card) |
1715 | { | 1801 | { |
1716 | struct platform_device *pdev = to_platform_device(card->dev); | ||
1717 | struct snd_soc_codec *codec; | 1802 | struct snd_soc_codec *codec; |
1718 | struct snd_soc_codec_conf *codec_conf; | 1803 | struct snd_soc_codec_conf *codec_conf; |
1719 | enum snd_soc_compress_type compress_type; | 1804 | enum snd_soc_compress_type compress_type; |
@@ -1740,6 +1825,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1740 | list_for_each_entry(codec, &codec_list, list) { | 1825 | list_for_each_entry(codec, &codec_list, list) { |
1741 | if (codec->cache_init) | 1826 | if (codec->cache_init) |
1742 | continue; | 1827 | continue; |
1828 | /* by default we don't override the compress_type */ | ||
1829 | compress_type = 0; | ||
1743 | /* check to see if we need to override the compress_type */ | 1830 | /* check to see if we need to override the compress_type */ |
1744 | for (i = 0; i < card->num_configs; ++i) { | 1831 | for (i = 0; i < card->num_configs; ++i) { |
1745 | codec_conf = &card->codec_conf[i]; | 1832 | codec_conf = &card->codec_conf[i]; |
@@ -1750,18 +1837,6 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1750 | break; | 1837 | break; |
1751 | } | 1838 | } |
1752 | } | 1839 | } |
1753 | if (i == card->num_configs) { | ||
1754 | /* no need to override the compress_type so | ||
1755 | * go ahead and do the standard thing */ | ||
1756 | ret = snd_soc_init_codec_cache(codec, 0); | ||
1757 | if (ret < 0) { | ||
1758 | mutex_unlock(&card->mutex); | ||
1759 | return; | ||
1760 | } | ||
1761 | continue; | ||
1762 | } | ||
1763 | /* override the compress_type with the one supplied in | ||
1764 | * the machine driver */ | ||
1765 | ret = snd_soc_init_codec_cache(codec, compress_type); | 1840 | ret = snd_soc_init_codec_cache(codec, compress_type); |
1766 | if (ret < 0) { | 1841 | if (ret < 0) { |
1767 | mutex_unlock(&card->mutex); | 1842 | mutex_unlock(&card->mutex); |
@@ -1780,14 +1855,19 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1780 | } | 1855 | } |
1781 | card->snd_card->dev = card->dev; | 1856 | card->snd_card->dev = card->dev; |
1782 | 1857 | ||
1783 | #ifdef CONFIG_PM | 1858 | card->dapm.bias_level = SND_SOC_BIAS_OFF; |
1859 | card->dapm.dev = card->dev; | ||
1860 | card->dapm.card = card; | ||
1861 | list_add(&card->dapm.list, &card->dapm_list); | ||
1862 | |||
1863 | #ifdef CONFIG_PM_SLEEP | ||
1784 | /* deferred resume work */ | 1864 | /* deferred resume work */ |
1785 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); | 1865 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); |
1786 | #endif | 1866 | #endif |
1787 | 1867 | ||
1788 | /* initialise the sound card only once */ | 1868 | /* initialise the sound card only once */ |
1789 | if (card->probe) { | 1869 | if (card->probe) { |
1790 | ret = card->probe(pdev); | 1870 | ret = card->probe(card); |
1791 | if (ret < 0) | 1871 | if (ret < 0) |
1792 | goto card_probe_error; | 1872 | goto card_probe_error; |
1793 | } | 1873 | } |
@@ -1810,11 +1890,37 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1810 | } | 1890 | } |
1811 | } | 1891 | } |
1812 | 1892 | ||
1893 | if (card->dapm_widgets) | ||
1894 | snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets, | ||
1895 | card->num_dapm_widgets); | ||
1896 | if (card->dapm_routes) | ||
1897 | snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes, | ||
1898 | card->num_dapm_routes); | ||
1899 | |||
1900 | #ifdef CONFIG_DEBUG_FS | ||
1901 | card->dapm.debugfs_dapm = debugfs_create_dir("dapm", | ||
1902 | card->debugfs_card_root); | ||
1903 | if (!card->dapm.debugfs_dapm) | ||
1904 | printk(KERN_WARNING | ||
1905 | "Failed to create card DAPM debugfs directory\n"); | ||
1906 | |||
1907 | snd_soc_dapm_debugfs_init(&card->dapm); | ||
1908 | #endif | ||
1909 | |||
1813 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), | 1910 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), |
1814 | "%s", card->name); | 1911 | "%s", card->name); |
1815 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), | 1912 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), |
1816 | "%s", card->name); | 1913 | "%s", card->name); |
1817 | 1914 | ||
1915 | if (card->late_probe) { | ||
1916 | ret = card->late_probe(card); | ||
1917 | if (ret < 0) { | ||
1918 | dev_err(card->dev, "%s late_probe() failed: %d\n", | ||
1919 | card->name, ret); | ||
1920 | goto probe_aux_dev_err; | ||
1921 | } | ||
1922 | } | ||
1923 | |||
1818 | ret = snd_card_register(card->snd_card); | 1924 | ret = snd_card_register(card->snd_card); |
1819 | if (ret < 0) { | 1925 | if (ret < 0) { |
1820 | printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); | 1926 | printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); |
@@ -1848,7 +1954,7 @@ probe_dai_err: | |||
1848 | 1954 | ||
1849 | card_probe_error: | 1955 | card_probe_error: |
1850 | if (card->remove) | 1956 | if (card->remove) |
1851 | card->remove(pdev); | 1957 | card->remove(card); |
1852 | 1958 | ||
1853 | snd_card_free(card->snd_card); | 1959 | snd_card_free(card->snd_card); |
1854 | 1960 | ||
@@ -1872,16 +1978,15 @@ static int soc_probe(struct platform_device *pdev) | |||
1872 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 1978 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
1873 | int ret = 0; | 1979 | int ret = 0; |
1874 | 1980 | ||
1981 | /* | ||
1982 | * no card, so machine driver should be registering card | ||
1983 | * we should not be here in that case so ret error | ||
1984 | */ | ||
1985 | if (!card) | ||
1986 | return -EINVAL; | ||
1987 | |||
1875 | /* Bodge while we unpick instantiation */ | 1988 | /* Bodge while we unpick instantiation */ |
1876 | card->dev = &pdev->dev; | 1989 | card->dev = &pdev->dev; |
1877 | INIT_LIST_HEAD(&card->dai_dev_list); | ||
1878 | INIT_LIST_HEAD(&card->codec_dev_list); | ||
1879 | INIT_LIST_HEAD(&card->platform_dev_list); | ||
1880 | INIT_LIST_HEAD(&card->widgets); | ||
1881 | INIT_LIST_HEAD(&card->paths); | ||
1882 | INIT_LIST_HEAD(&card->dapm_list); | ||
1883 | |||
1884 | soc_init_card_debugfs(card); | ||
1885 | 1990 | ||
1886 | ret = snd_soc_register_card(card); | 1991 | ret = snd_soc_register_card(card); |
1887 | if (ret != 0) { | 1992 | if (ret != 0) { |
@@ -1892,45 +1997,48 @@ static int soc_probe(struct platform_device *pdev) | |||
1892 | return 0; | 1997 | return 0; |
1893 | } | 1998 | } |
1894 | 1999 | ||
1895 | /* removes a socdev */ | 2000 | static int soc_cleanup_card_resources(struct snd_soc_card *card) |
1896 | static int soc_remove(struct platform_device *pdev) | ||
1897 | { | 2001 | { |
1898 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1899 | int i; | 2002 | int i; |
1900 | 2003 | ||
1901 | if (card->instantiated) { | 2004 | /* make sure any delayed work runs */ |
2005 | for (i = 0; i < card->num_rtd; i++) { | ||
2006 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | ||
2007 | flush_delayed_work_sync(&rtd->delayed_work); | ||
2008 | } | ||
1902 | 2009 | ||
1903 | /* make sure any delayed work runs */ | 2010 | /* remove auxiliary devices */ |
1904 | for (i = 0; i < card->num_rtd; i++) { | 2011 | for (i = 0; i < card->num_aux_devs; i++) |
1905 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | 2012 | soc_remove_aux_dev(card, i); |
1906 | flush_delayed_work_sync(&rtd->delayed_work); | ||
1907 | } | ||
1908 | 2013 | ||
1909 | /* remove auxiliary devices */ | 2014 | /* remove and free each DAI */ |
1910 | for (i = 0; i < card->num_aux_devs; i++) | 2015 | for (i = 0; i < card->num_rtd; i++) |
1911 | soc_remove_aux_dev(card, i); | 2016 | soc_remove_dai_link(card, i); |
1912 | 2017 | ||
1913 | /* remove and free each DAI */ | 2018 | soc_cleanup_card_debugfs(card); |
1914 | for (i = 0; i < card->num_rtd; i++) | ||
1915 | soc_remove_dai_link(card, i); | ||
1916 | 2019 | ||
1917 | soc_cleanup_card_debugfs(card); | 2020 | /* remove the card */ |
2021 | if (card->remove) | ||
2022 | card->remove(card); | ||
2023 | |||
2024 | kfree(card->rtd); | ||
2025 | snd_card_free(card->snd_card); | ||
2026 | return 0; | ||
1918 | 2027 | ||
1919 | /* remove the card */ | 2028 | } |
1920 | if (card->remove) | 2029 | |
1921 | card->remove(pdev); | 2030 | /* removes a socdev */ |
2031 | static int soc_remove(struct platform_device *pdev) | ||
2032 | { | ||
2033 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1922 | 2034 | ||
1923 | kfree(card->rtd); | ||
1924 | snd_card_free(card->snd_card); | ||
1925 | } | ||
1926 | snd_soc_unregister_card(card); | 2035 | snd_soc_unregister_card(card); |
1927 | return 0; | 2036 | return 0; |
1928 | } | 2037 | } |
1929 | 2038 | ||
1930 | static int soc_poweroff(struct device *dev) | 2039 | int snd_soc_poweroff(struct device *dev) |
1931 | { | 2040 | { |
1932 | struct platform_device *pdev = to_platform_device(dev); | 2041 | struct snd_soc_card *card = dev_get_drvdata(dev); |
1933 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
1934 | int i; | 2042 | int i; |
1935 | 2043 | ||
1936 | if (!card->instantiated) | 2044 | if (!card->instantiated) |
@@ -1947,11 +2055,12 @@ static int soc_poweroff(struct device *dev) | |||
1947 | 2055 | ||
1948 | return 0; | 2056 | return 0; |
1949 | } | 2057 | } |
2058 | EXPORT_SYMBOL_GPL(snd_soc_poweroff); | ||
1950 | 2059 | ||
1951 | static const struct dev_pm_ops soc_pm_ops = { | 2060 | const struct dev_pm_ops snd_soc_pm_ops = { |
1952 | .suspend = soc_suspend, | 2061 | .suspend = snd_soc_suspend, |
1953 | .resume = soc_resume, | 2062 | .resume = snd_soc_resume, |
1954 | .poweroff = soc_poweroff, | 2063 | .poweroff = snd_soc_poweroff, |
1955 | }; | 2064 | }; |
1956 | 2065 | ||
1957 | /* ASoC platform driver */ | 2066 | /* ASoC platform driver */ |
@@ -1959,7 +2068,7 @@ static struct platform_driver soc_driver = { | |||
1959 | .driver = { | 2068 | .driver = { |
1960 | .name = "soc-audio", | 2069 | .name = "soc-audio", |
1961 | .owner = THIS_MODULE, | 2070 | .owner = THIS_MODULE, |
1962 | .pm = &soc_pm_ops, | 2071 | .pm = &snd_soc_pm_ops, |
1963 | }, | 2072 | }, |
1964 | .probe = soc_probe, | 2073 | .probe = soc_probe, |
1965 | .remove = soc_remove, | 2074 | .remove = soc_remove, |
@@ -2029,10 +2138,11 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) | |||
2029 | * | 2138 | * |
2030 | * Boolean function indiciating if a CODEC register is volatile. | 2139 | * Boolean function indiciating if a CODEC register is volatile. |
2031 | */ | 2140 | */ |
2032 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) | 2141 | int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, |
2142 | unsigned int reg) | ||
2033 | { | 2143 | { |
2034 | if (codec->driver->volatile_register) | 2144 | if (codec->volatile_register) |
2035 | return codec->driver->volatile_register(reg); | 2145 | return codec->volatile_register(codec, reg); |
2036 | else | 2146 | else |
2037 | return 0; | 2147 | return 0; |
2038 | } | 2148 | } |
@@ -2129,19 +2239,27 @@ EXPORT_SYMBOL_GPL(snd_soc_write); | |||
2129 | * | 2239 | * |
2130 | * Writes new register value. | 2240 | * Writes new register value. |
2131 | * | 2241 | * |
2132 | * Returns 1 for change else 0. | 2242 | * Returns 1 for change, 0 for no change, or negative error code. |
2133 | */ | 2243 | */ |
2134 | int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, | 2244 | int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, |
2135 | unsigned int mask, unsigned int value) | 2245 | unsigned int mask, unsigned int value) |
2136 | { | 2246 | { |
2137 | int change; | 2247 | int change; |
2138 | unsigned int old, new; | 2248 | unsigned int old, new; |
2249 | int ret; | ||
2139 | 2250 | ||
2140 | old = snd_soc_read(codec, reg); | 2251 | ret = snd_soc_read(codec, reg); |
2252 | if (ret < 0) | ||
2253 | return ret; | ||
2254 | |||
2255 | old = ret; | ||
2141 | new = (old & ~mask) | value; | 2256 | new = (old & ~mask) | value; |
2142 | change = old != new; | 2257 | change = old != new; |
2143 | if (change) | 2258 | if (change) { |
2144 | snd_soc_write(codec, reg, new); | 2259 | ret = snd_soc_write(codec, reg, new); |
2260 | if (ret < 0) | ||
2261 | return ret; | ||
2262 | } | ||
2145 | 2263 | ||
2146 | return change; | 2264 | return change; |
2147 | } | 2265 | } |
@@ -2226,22 +2344,45 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); | |||
2226 | * @_template: control template | 2344 | * @_template: control template |
2227 | * @data: control private data | 2345 | * @data: control private data |
2228 | * @long_name: control long name | 2346 | * @long_name: control long name |
2347 | * @prefix: control name prefix | ||
2229 | * | 2348 | * |
2230 | * Create a new mixer control from a template control. | 2349 | * Create a new mixer control from a template control. |
2231 | * | 2350 | * |
2232 | * Returns 0 for success, else error. | 2351 | * Returns 0 for success, else error. |
2233 | */ | 2352 | */ |
2234 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | 2353 | struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, |
2235 | void *data, char *long_name) | 2354 | void *data, char *long_name, |
2355 | const char *prefix) | ||
2236 | { | 2356 | { |
2237 | struct snd_kcontrol_new template; | 2357 | struct snd_kcontrol_new template; |
2358 | struct snd_kcontrol *kcontrol; | ||
2359 | char *name = NULL; | ||
2360 | int name_len; | ||
2238 | 2361 | ||
2239 | memcpy(&template, _template, sizeof(template)); | 2362 | memcpy(&template, _template, sizeof(template)); |
2240 | if (long_name) | ||
2241 | template.name = long_name; | ||
2242 | template.index = 0; | 2363 | template.index = 0; |
2243 | 2364 | ||
2244 | return snd_ctl_new1(&template, data); | 2365 | if (!long_name) |
2366 | long_name = template.name; | ||
2367 | |||
2368 | if (prefix) { | ||
2369 | name_len = strlen(long_name) + strlen(prefix) + 2; | ||
2370 | name = kmalloc(name_len, GFP_ATOMIC); | ||
2371 | if (!name) | ||
2372 | return NULL; | ||
2373 | |||
2374 | snprintf(name, name_len, "%s %s", prefix, long_name); | ||
2375 | |||
2376 | template.name = name; | ||
2377 | } else { | ||
2378 | template.name = long_name; | ||
2379 | } | ||
2380 | |||
2381 | kcontrol = snd_ctl_new1(&template, data); | ||
2382 | |||
2383 | kfree(name); | ||
2384 | |||
2385 | return kcontrol; | ||
2245 | } | 2386 | } |
2246 | EXPORT_SYMBOL_GPL(snd_soc_cnew); | 2387 | EXPORT_SYMBOL_GPL(snd_soc_cnew); |
2247 | 2388 | ||
@@ -2260,22 +2401,16 @@ int snd_soc_add_controls(struct snd_soc_codec *codec, | |||
2260 | const struct snd_kcontrol_new *controls, int num_controls) | 2401 | const struct snd_kcontrol_new *controls, int num_controls) |
2261 | { | 2402 | { |
2262 | struct snd_card *card = codec->card->snd_card; | 2403 | struct snd_card *card = codec->card->snd_card; |
2263 | char prefixed_name[44], *name; | ||
2264 | int err, i; | 2404 | int err, i; |
2265 | 2405 | ||
2266 | for (i = 0; i < num_controls; i++) { | 2406 | for (i = 0; i < num_controls; i++) { |
2267 | const struct snd_kcontrol_new *control = &controls[i]; | 2407 | const struct snd_kcontrol_new *control = &controls[i]; |
2268 | if (codec->name_prefix) { | 2408 | err = snd_ctl_add(card, snd_soc_cnew(control, codec, |
2269 | snprintf(prefixed_name, sizeof(prefixed_name), "%s %s", | 2409 | control->name, |
2270 | codec->name_prefix, control->name); | 2410 | codec->name_prefix)); |
2271 | name = prefixed_name; | ||
2272 | } else { | ||
2273 | name = control->name; | ||
2274 | } | ||
2275 | err = snd_ctl_add(card, snd_soc_cnew(control, codec, name)); | ||
2276 | if (err < 0) { | 2411 | if (err < 0) { |
2277 | dev_err(codec->dev, "%s: Failed to add %s: %d\n", | 2412 | dev_err(codec->dev, "%s: Failed to add %s: %d\n", |
2278 | codec->name, name, err); | 2413 | codec->name, control->name, err); |
2279 | return err; | 2414 | return err; |
2280 | } | 2415 | } |
2281 | } | 2416 | } |
@@ -2956,12 +3091,34 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | |||
2956 | { | 3091 | { |
2957 | if (dai->driver && dai->driver->ops->set_sysclk) | 3092 | if (dai->driver && dai->driver->ops->set_sysclk) |
2958 | return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); | 3093 | return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir); |
3094 | else if (dai->codec && dai->codec->driver->set_sysclk) | ||
3095 | return dai->codec->driver->set_sysclk(dai->codec, clk_id, | ||
3096 | freq, dir); | ||
2959 | else | 3097 | else |
2960 | return -EINVAL; | 3098 | return -EINVAL; |
2961 | } | 3099 | } |
2962 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | 3100 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); |
2963 | 3101 | ||
2964 | /** | 3102 | /** |
3103 | * snd_soc_codec_set_sysclk - configure CODEC system or master clock. | ||
3104 | * @codec: CODEC | ||
3105 | * @clk_id: DAI specific clock ID | ||
3106 | * @freq: new clock frequency in Hz | ||
3107 | * @dir: new clock direction - input/output. | ||
3108 | * | ||
3109 | * Configures the CODEC master (MCLK) or system (SYSCLK) clocking. | ||
3110 | */ | ||
3111 | int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id, | ||
3112 | unsigned int freq, int dir) | ||
3113 | { | ||
3114 | if (codec->driver->set_sysclk) | ||
3115 | return codec->driver->set_sysclk(codec, clk_id, freq, dir); | ||
3116 | else | ||
3117 | return -EINVAL; | ||
3118 | } | ||
3119 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk); | ||
3120 | |||
3121 | /** | ||
2965 | * snd_soc_dai_set_clkdiv - configure DAI clock dividers. | 3122 | * snd_soc_dai_set_clkdiv - configure DAI clock dividers. |
2966 | * @dai: DAI | 3123 | * @dai: DAI |
2967 | * @div_id: DAI specific clock divider ID | 3124 | * @div_id: DAI specific clock divider ID |
@@ -2997,11 +3154,35 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, | |||
2997 | if (dai->driver && dai->driver->ops->set_pll) | 3154 | if (dai->driver && dai->driver->ops->set_pll) |
2998 | return dai->driver->ops->set_pll(dai, pll_id, source, | 3155 | return dai->driver->ops->set_pll(dai, pll_id, source, |
2999 | freq_in, freq_out); | 3156 | freq_in, freq_out); |
3157 | else if (dai->codec && dai->codec->driver->set_pll) | ||
3158 | return dai->codec->driver->set_pll(dai->codec, pll_id, source, | ||
3159 | freq_in, freq_out); | ||
3000 | else | 3160 | else |
3001 | return -EINVAL; | 3161 | return -EINVAL; |
3002 | } | 3162 | } |
3003 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); | 3163 | EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); |
3004 | 3164 | ||
3165 | /* | ||
3166 | * snd_soc_codec_set_pll - configure codec PLL. | ||
3167 | * @codec: CODEC | ||
3168 | * @pll_id: DAI specific PLL ID | ||
3169 | * @source: DAI specific source for the PLL | ||
3170 | * @freq_in: PLL input clock frequency in Hz | ||
3171 | * @freq_out: requested PLL output clock frequency in Hz | ||
3172 | * | ||
3173 | * Configures and enables PLL to generate output clock based on input clock. | ||
3174 | */ | ||
3175 | int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source, | ||
3176 | unsigned int freq_in, unsigned int freq_out) | ||
3177 | { | ||
3178 | if (codec->driver->set_pll) | ||
3179 | return codec->driver->set_pll(codec, pll_id, source, | ||
3180 | freq_in, freq_out); | ||
3181 | else | ||
3182 | return -EINVAL; | ||
3183 | } | ||
3184 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll); | ||
3185 | |||
3005 | /** | 3186 | /** |
3006 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. | 3187 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. |
3007 | * @dai: DAI | 3188 | * @dai: DAI |
@@ -3101,17 +3282,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | |||
3101 | * | 3282 | * |
3102 | * @card: Card to register | 3283 | * @card: Card to register |
3103 | * | 3284 | * |
3104 | * Note that currently this is an internal only function: it will be | ||
3105 | * exposed to machine drivers after further backporting of ASoC v2 | ||
3106 | * registration APIs. | ||
3107 | */ | 3285 | */ |
3108 | static int snd_soc_register_card(struct snd_soc_card *card) | 3286 | int snd_soc_register_card(struct snd_soc_card *card) |
3109 | { | 3287 | { |
3110 | int i; | 3288 | int i; |
3111 | 3289 | ||
3112 | if (!card->name || !card->dev) | 3290 | if (!card->name || !card->dev) |
3113 | return -EINVAL; | 3291 | return -EINVAL; |
3114 | 3292 | ||
3293 | snd_soc_initialize_card_lists(card); | ||
3294 | |||
3295 | soc_init_card_debugfs(card); | ||
3296 | |||
3115 | card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * | 3297 | card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * |
3116 | (card->num_links + card->num_aux_devs), | 3298 | (card->num_links + card->num_aux_devs), |
3117 | GFP_KERNEL); | 3299 | GFP_KERNEL); |
@@ -3135,18 +3317,18 @@ static int snd_soc_register_card(struct snd_soc_card *card) | |||
3135 | 3317 | ||
3136 | return 0; | 3318 | return 0; |
3137 | } | 3319 | } |
3320 | EXPORT_SYMBOL_GPL(snd_soc_register_card); | ||
3138 | 3321 | ||
3139 | /** | 3322 | /** |
3140 | * snd_soc_unregister_card - Unregister a card with the ASoC core | 3323 | * snd_soc_unregister_card - Unregister a card with the ASoC core |
3141 | * | 3324 | * |
3142 | * @card: Card to unregister | 3325 | * @card: Card to unregister |
3143 | * | 3326 | * |
3144 | * Note that currently this is an internal only function: it will be | ||
3145 | * exposed to machine drivers after further backporting of ASoC v2 | ||
3146 | * registration APIs. | ||
3147 | */ | 3327 | */ |
3148 | static int snd_soc_unregister_card(struct snd_soc_card *card) | 3328 | int snd_soc_unregister_card(struct snd_soc_card *card) |
3149 | { | 3329 | { |
3330 | if (card->instantiated) | ||
3331 | soc_cleanup_card_resources(card); | ||
3150 | mutex_lock(&client_mutex); | 3332 | mutex_lock(&client_mutex); |
3151 | list_del(&card->list); | 3333 | list_del(&card->list); |
3152 | mutex_unlock(&client_mutex); | 3334 | mutex_unlock(&client_mutex); |
@@ -3154,6 +3336,7 @@ static int snd_soc_unregister_card(struct snd_soc_card *card) | |||
3154 | 3336 | ||
3155 | return 0; | 3337 | return 0; |
3156 | } | 3338 | } |
3339 | EXPORT_SYMBOL_GPL(snd_soc_unregister_card); | ||
3157 | 3340 | ||
3158 | /* | 3341 | /* |
3159 | * Simplify DAI link configuration by removing ".-1" from device names | 3342 | * Simplify DAI link configuration by removing ".-1" from device names |
@@ -3483,9 +3666,12 @@ int snd_soc_register_codec(struct device *dev, | |||
3483 | 3666 | ||
3484 | codec->write = codec_drv->write; | 3667 | codec->write = codec_drv->write; |
3485 | codec->read = codec_drv->read; | 3668 | codec->read = codec_drv->read; |
3669 | codec->volatile_register = codec_drv->volatile_register; | ||
3670 | codec->readable_register = codec_drv->readable_register; | ||
3486 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | 3671 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; |
3487 | codec->dapm.dev = dev; | 3672 | codec->dapm.dev = dev; |
3488 | codec->dapm.codec = codec; | 3673 | codec->dapm.codec = codec; |
3674 | codec->dapm.seq_notifier = codec_drv->seq_notifier; | ||
3489 | codec->dev = dev; | 3675 | codec->dev = dev; |
3490 | codec->driver = codec_drv; | 3676 | codec->driver = codec_drv; |
3491 | codec->num_dai = num_dai; | 3677 | codec->num_dai = num_dai; |
@@ -3494,20 +3680,30 @@ int snd_soc_register_codec(struct device *dev, | |||
3494 | /* allocate CODEC register cache */ | 3680 | /* allocate CODEC register cache */ |
3495 | if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { | 3681 | if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { |
3496 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; | 3682 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; |
3683 | codec->reg_size = reg_size; | ||
3497 | /* it is necessary to make a copy of the default register cache | 3684 | /* it is necessary to make a copy of the default register cache |
3498 | * because in the case of using a compression type that requires | 3685 | * because in the case of using a compression type that requires |
3499 | * the default register cache to be marked as __devinitconst the | 3686 | * the default register cache to be marked as __devinitconst the |
3500 | * kernel might have freed the array by the time we initialize | 3687 | * kernel might have freed the array by the time we initialize |
3501 | * the cache. | 3688 | * the cache. |
3502 | */ | 3689 | */ |
3503 | codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default, | 3690 | if (codec_drv->reg_cache_default) { |
3504 | reg_size, GFP_KERNEL); | 3691 | codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default, |
3505 | if (!codec->reg_def_copy) { | 3692 | reg_size, GFP_KERNEL); |
3506 | ret = -ENOMEM; | 3693 | if (!codec->reg_def_copy) { |
3507 | goto fail; | 3694 | ret = -ENOMEM; |
3695 | goto fail; | ||
3696 | } | ||
3508 | } | 3697 | } |
3509 | } | 3698 | } |
3510 | 3699 | ||
3700 | if (codec_drv->reg_access_size && codec_drv->reg_access_default) { | ||
3701 | if (!codec->volatile_register) | ||
3702 | codec->volatile_register = snd_soc_default_volatile_register; | ||
3703 | if (!codec->readable_register) | ||
3704 | codec->readable_register = snd_soc_default_readable_register; | ||
3705 | } | ||
3706 | |||
3511 | for (i = 0; i < num_dai; i++) { | 3707 | for (i = 0; i < num_dai; i++) { |
3512 | fixup_codec_formats(&dai_drv[i].playback); | 3708 | fixup_codec_formats(&dai_drv[i].playback); |
3513 | fixup_codec_formats(&dai_drv[i].capture); | 3709 | fixup_codec_formats(&dai_drv[i].capture); |
@@ -3574,22 +3770,22 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | |||
3574 | static int __init snd_soc_init(void) | 3770 | static int __init snd_soc_init(void) |
3575 | { | 3771 | { |
3576 | #ifdef CONFIG_DEBUG_FS | 3772 | #ifdef CONFIG_DEBUG_FS |
3577 | debugfs_root = debugfs_create_dir("asoc", NULL); | 3773 | snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL); |
3578 | if (IS_ERR(debugfs_root) || !debugfs_root) { | 3774 | if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) { |
3579 | printk(KERN_WARNING | 3775 | printk(KERN_WARNING |
3580 | "ASoC: Failed to create debugfs directory\n"); | 3776 | "ASoC: Failed to create debugfs directory\n"); |
3581 | debugfs_root = NULL; | 3777 | snd_soc_debugfs_root = NULL; |
3582 | } | 3778 | } |
3583 | 3779 | ||
3584 | if (!debugfs_create_file("codecs", 0444, debugfs_root, NULL, | 3780 | if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL, |
3585 | &codec_list_fops)) | 3781 | &codec_list_fops)) |
3586 | pr_warn("ASoC: Failed to create CODEC list debugfs file\n"); | 3782 | pr_warn("ASoC: Failed to create CODEC list debugfs file\n"); |
3587 | 3783 | ||
3588 | if (!debugfs_create_file("dais", 0444, debugfs_root, NULL, | 3784 | if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, |
3589 | &dai_list_fops)) | 3785 | &dai_list_fops)) |
3590 | pr_warn("ASoC: Failed to create DAI list debugfs file\n"); | 3786 | pr_warn("ASoC: Failed to create DAI list debugfs file\n"); |
3591 | 3787 | ||
3592 | if (!debugfs_create_file("platforms", 0444, debugfs_root, NULL, | 3788 | if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL, |
3593 | &platform_list_fops)) | 3789 | &platform_list_fops)) |
3594 | pr_warn("ASoC: Failed to create platform list debugfs file\n"); | 3790 | pr_warn("ASoC: Failed to create platform list debugfs file\n"); |
3595 | #endif | 3791 | #endif |
@@ -3601,7 +3797,7 @@ module_init(snd_soc_init); | |||
3601 | static void __exit snd_soc_exit(void) | 3797 | static void __exit snd_soc_exit(void) |
3602 | { | 3798 | { |
3603 | #ifdef CONFIG_DEBUG_FS | 3799 | #ifdef CONFIG_DEBUG_FS |
3604 | debugfs_remove_recursive(debugfs_root); | 3800 | debugfs_remove_recursive(snd_soc_debugfs_root); |
3605 | #endif | 3801 | #endif |
3606 | platform_driver_unregister(&soc_driver); | 3802 | platform_driver_unregister(&soc_driver); |
3607 | } | 3803 | } |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1790f83ee665..81c4052c127c 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/moduleparam.h> | 33 | #include <linux/moduleparam.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/async.h> | ||
35 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
36 | #include <linux/pm.h> | 37 | #include <linux/pm.h> |
37 | #include <linux/bitops.h> | 38 | #include <linux/bitops.h> |
@@ -125,17 +126,17 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | |||
125 | 126 | ||
126 | /** | 127 | /** |
127 | * snd_soc_dapm_set_bias_level - set the bias level for the system | 128 | * snd_soc_dapm_set_bias_level - set the bias level for the system |
128 | * @card: audio device | 129 | * @dapm: DAPM context |
129 | * @level: level to configure | 130 | * @level: level to configure |
130 | * | 131 | * |
131 | * Configure the bias (power) levels for the SoC audio device. | 132 | * Configure the bias (power) levels for the SoC audio device. |
132 | * | 133 | * |
133 | * Returns 0 for success else error. | 134 | * Returns 0 for success else error. |
134 | */ | 135 | */ |
135 | static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card, | 136 | static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm, |
136 | struct snd_soc_dapm_context *dapm, | ||
137 | enum snd_soc_bias_level level) | 137 | enum snd_soc_bias_level level) |
138 | { | 138 | { |
139 | struct snd_soc_card *card = dapm->card; | ||
139 | int ret = 0; | 140 | int ret = 0; |
140 | 141 | ||
141 | switch (level) { | 142 | switch (level) { |
@@ -365,9 +366,20 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
365 | struct snd_soc_dapm_widget *w) | 366 | struct snd_soc_dapm_widget *w) |
366 | { | 367 | { |
367 | int i, ret = 0; | 368 | int i, ret = 0; |
368 | size_t name_len; | 369 | size_t name_len, prefix_len; |
369 | struct snd_soc_dapm_path *path; | 370 | struct snd_soc_dapm_path *path; |
370 | struct snd_card *card = dapm->codec->card->snd_card; | 371 | struct snd_card *card = dapm->card->snd_card; |
372 | const char *prefix; | ||
373 | |||
374 | if (dapm->codec) | ||
375 | prefix = dapm->codec->name_prefix; | ||
376 | else | ||
377 | prefix = NULL; | ||
378 | |||
379 | if (prefix) | ||
380 | prefix_len = strlen(prefix) + 1; | ||
381 | else | ||
382 | prefix_len = 0; | ||
371 | 383 | ||
372 | /* add kcontrol */ | 384 | /* add kcontrol */ |
373 | for (i = 0; i < w->num_kcontrols; i++) { | 385 | for (i = 0; i < w->num_kcontrols; i++) { |
@@ -396,8 +408,15 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
396 | 408 | ||
397 | switch (w->id) { | 409 | switch (w->id) { |
398 | default: | 410 | default: |
411 | /* The control will get a prefix from | ||
412 | * the control creation process but | ||
413 | * we're also using the same prefix | ||
414 | * for widgets so cut the prefix off | ||
415 | * the front of the widget name. | ||
416 | */ | ||
399 | snprintf(path->long_name, name_len, "%s %s", | 417 | snprintf(path->long_name, name_len, "%s %s", |
400 | w->name, w->kcontrols[i].name); | 418 | w->name + prefix_len, |
419 | w->kcontrols[i].name); | ||
401 | break; | 420 | break; |
402 | case snd_soc_dapm_mixer_named_ctl: | 421 | case snd_soc_dapm_mixer_named_ctl: |
403 | snprintf(path->long_name, name_len, "%s", | 422 | snprintf(path->long_name, name_len, "%s", |
@@ -408,7 +427,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm, | |||
408 | path->long_name[name_len - 1] = '\0'; | 427 | path->long_name[name_len - 1] = '\0'; |
409 | 428 | ||
410 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 429 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, |
411 | path->long_name); | 430 | path->long_name, prefix); |
412 | ret = snd_ctl_add(card, path->kcontrol); | 431 | ret = snd_ctl_add(card, path->kcontrol); |
413 | if (ret < 0) { | 432 | if (ret < 0) { |
414 | dev_err(dapm->dev, | 433 | dev_err(dapm->dev, |
@@ -429,7 +448,9 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, | |||
429 | { | 448 | { |
430 | struct snd_soc_dapm_path *path = NULL; | 449 | struct snd_soc_dapm_path *path = NULL; |
431 | struct snd_kcontrol *kcontrol; | 450 | struct snd_kcontrol *kcontrol; |
432 | struct snd_card *card = dapm->codec->card->snd_card; | 451 | struct snd_card *card = dapm->card->snd_card; |
452 | const char *prefix; | ||
453 | size_t prefix_len; | ||
433 | int ret = 0; | 454 | int ret = 0; |
434 | 455 | ||
435 | if (!w->num_kcontrols) { | 456 | if (!w->num_kcontrols) { |
@@ -437,7 +458,22 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm, | |||
437 | return -EINVAL; | 458 | return -EINVAL; |
438 | } | 459 | } |
439 | 460 | ||
440 | kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); | 461 | if (dapm->codec) |
462 | prefix = dapm->codec->name_prefix; | ||
463 | else | ||
464 | prefix = NULL; | ||
465 | |||
466 | if (prefix) | ||
467 | prefix_len = strlen(prefix) + 1; | ||
468 | else | ||
469 | prefix_len = 0; | ||
470 | |||
471 | /* The control will get a prefix from the control creation | ||
472 | * process but we're also using the same prefix for widgets so | ||
473 | * cut the prefix off the front of the widget name. | ||
474 | */ | ||
475 | kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name + prefix_len, | ||
476 | prefix); | ||
441 | ret = snd_ctl_add(card, kcontrol); | 477 | ret = snd_ctl_add(card, kcontrol); |
442 | 478 | ||
443 | if (ret < 0) | 479 | if (ret < 0) |
@@ -479,7 +515,7 @@ static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm) | |||
479 | */ | 515 | */ |
480 | static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) | 516 | static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) |
481 | { | 517 | { |
482 | int level = snd_power_get_state(widget->dapm->codec->card->snd_card); | 518 | int level = snd_power_get_state(widget->dapm->card->snd_card); |
483 | 519 | ||
484 | switch (level) { | 520 | switch (level) { |
485 | case SNDRV_CTL_POWER_D3hot: | 521 | case SNDRV_CTL_POWER_D3hot: |
@@ -734,10 +770,23 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) | |||
734 | 770 | ||
735 | static int dapm_seq_compare(struct snd_soc_dapm_widget *a, | 771 | static int dapm_seq_compare(struct snd_soc_dapm_widget *a, |
736 | struct snd_soc_dapm_widget *b, | 772 | struct snd_soc_dapm_widget *b, |
737 | int sort[]) | 773 | bool power_up) |
738 | { | 774 | { |
775 | int *sort; | ||
776 | |||
777 | if (power_up) | ||
778 | sort = dapm_up_seq; | ||
779 | else | ||
780 | sort = dapm_down_seq; | ||
781 | |||
739 | if (sort[a->id] != sort[b->id]) | 782 | if (sort[a->id] != sort[b->id]) |
740 | return sort[a->id] - sort[b->id]; | 783 | return sort[a->id] - sort[b->id]; |
784 | if (a->subseq != b->subseq) { | ||
785 | if (power_up) | ||
786 | return a->subseq - b->subseq; | ||
787 | else | ||
788 | return b->subseq - a->subseq; | ||
789 | } | ||
741 | if (a->reg != b->reg) | 790 | if (a->reg != b->reg) |
742 | return a->reg - b->reg; | 791 | return a->reg - b->reg; |
743 | if (a->dapm != b->dapm) | 792 | if (a->dapm != b->dapm) |
@@ -749,12 +798,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a, | |||
749 | /* Insert a widget in order into a DAPM power sequence. */ | 798 | /* Insert a widget in order into a DAPM power sequence. */ |
750 | static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, | 799 | static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, |
751 | struct list_head *list, | 800 | struct list_head *list, |
752 | int sort[]) | 801 | bool power_up) |
753 | { | 802 | { |
754 | struct snd_soc_dapm_widget *w; | 803 | struct snd_soc_dapm_widget *w; |
755 | 804 | ||
756 | list_for_each_entry(w, list, power_list) | 805 | list_for_each_entry(w, list, power_list) |
757 | if (dapm_seq_compare(new_widget, w, sort) < 0) { | 806 | if (dapm_seq_compare(new_widget, w, power_up) < 0) { |
758 | list_add_tail(&new_widget->power_list, &w->power_list); | 807 | list_add_tail(&new_widget->power_list, &w->power_list); |
759 | return; | 808 | return; |
760 | } | 809 | } |
@@ -865,26 +914,42 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm, | |||
865 | * handled. | 914 | * handled. |
866 | */ | 915 | */ |
867 | static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | 916 | static void dapm_seq_run(struct snd_soc_dapm_context *dapm, |
868 | struct list_head *list, int event, int sort[]) | 917 | struct list_head *list, int event, bool power_up) |
869 | { | 918 | { |
870 | struct snd_soc_dapm_widget *w, *n; | 919 | struct snd_soc_dapm_widget *w, *n; |
871 | LIST_HEAD(pending); | 920 | LIST_HEAD(pending); |
872 | int cur_sort = -1; | 921 | int cur_sort = -1; |
922 | int cur_subseq = -1; | ||
873 | int cur_reg = SND_SOC_NOPM; | 923 | int cur_reg = SND_SOC_NOPM; |
874 | struct snd_soc_dapm_context *cur_dapm = NULL; | 924 | struct snd_soc_dapm_context *cur_dapm = NULL; |
875 | int ret; | 925 | int ret, i; |
926 | int *sort; | ||
927 | |||
928 | if (power_up) | ||
929 | sort = dapm_up_seq; | ||
930 | else | ||
931 | sort = dapm_down_seq; | ||
876 | 932 | ||
877 | list_for_each_entry_safe(w, n, list, power_list) { | 933 | list_for_each_entry_safe(w, n, list, power_list) { |
878 | ret = 0; | 934 | ret = 0; |
879 | 935 | ||
880 | /* Do we need to apply any queued changes? */ | 936 | /* Do we need to apply any queued changes? */ |
881 | if (sort[w->id] != cur_sort || w->reg != cur_reg || | 937 | if (sort[w->id] != cur_sort || w->reg != cur_reg || |
882 | w->dapm != cur_dapm) { | 938 | w->dapm != cur_dapm || w->subseq != cur_subseq) { |
883 | if (!list_empty(&pending)) | 939 | if (!list_empty(&pending)) |
884 | dapm_seq_run_coalesced(cur_dapm, &pending); | 940 | dapm_seq_run_coalesced(cur_dapm, &pending); |
885 | 941 | ||
942 | if (cur_dapm && cur_dapm->seq_notifier) { | ||
943 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) | ||
944 | if (sort[i] == cur_sort) | ||
945 | cur_dapm->seq_notifier(cur_dapm, | ||
946 | i, | ||
947 | cur_subseq); | ||
948 | } | ||
949 | |||
886 | INIT_LIST_HEAD(&pending); | 950 | INIT_LIST_HEAD(&pending); |
887 | cur_sort = -1; | 951 | cur_sort = -1; |
952 | cur_subseq = -1; | ||
888 | cur_reg = SND_SOC_NOPM; | 953 | cur_reg = SND_SOC_NOPM; |
889 | cur_dapm = NULL; | 954 | cur_dapm = NULL; |
890 | } | 955 | } |
@@ -929,6 +994,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
929 | default: | 994 | default: |
930 | /* Queue it up for application */ | 995 | /* Queue it up for application */ |
931 | cur_sort = sort[w->id]; | 996 | cur_sort = sort[w->id]; |
997 | cur_subseq = w->subseq; | ||
932 | cur_reg = w->reg; | 998 | cur_reg = w->reg; |
933 | cur_dapm = w->dapm; | 999 | cur_dapm = w->dapm; |
934 | list_move(&w->power_list, &pending); | 1000 | list_move(&w->power_list, &pending); |
@@ -942,6 +1008,13 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm, | |||
942 | 1008 | ||
943 | if (!list_empty(&pending)) | 1009 | if (!list_empty(&pending)) |
944 | dapm_seq_run_coalesced(cur_dapm, &pending); | 1010 | dapm_seq_run_coalesced(cur_dapm, &pending); |
1011 | |||
1012 | if (cur_dapm && cur_dapm->seq_notifier) { | ||
1013 | for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) | ||
1014 | if (sort[i] == cur_sort) | ||
1015 | cur_dapm->seq_notifier(cur_dapm, | ||
1016 | i, cur_subseq); | ||
1017 | } | ||
945 | } | 1018 | } |
946 | 1019 | ||
947 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | 1020 | static void dapm_widget_update(struct snd_soc_dapm_context *dapm) |
@@ -977,7 +1050,62 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | |||
977 | } | 1050 | } |
978 | } | 1051 | } |
979 | 1052 | ||
1053 | /* Async callback run prior to DAPM sequences - brings to _PREPARE if | ||
1054 | * they're changing state. | ||
1055 | */ | ||
1056 | static void dapm_pre_sequence_async(void *data, async_cookie_t cookie) | ||
1057 | { | ||
1058 | struct snd_soc_dapm_context *d = data; | ||
1059 | int ret; | ||
980 | 1060 | ||
1061 | if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) { | ||
1062 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); | ||
1063 | if (ret != 0) | ||
1064 | dev_err(d->dev, | ||
1065 | "Failed to turn on bias: %d\n", ret); | ||
1066 | } | ||
1067 | |||
1068 | /* If we're changing to all on or all off then prepare */ | ||
1069 | if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) || | ||
1070 | (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) { | ||
1071 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE); | ||
1072 | if (ret != 0) | ||
1073 | dev_err(d->dev, | ||
1074 | "Failed to prepare bias: %d\n", ret); | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1078 | /* Async callback run prior to DAPM sequences - brings to their final | ||
1079 | * state. | ||
1080 | */ | ||
1081 | static void dapm_post_sequence_async(void *data, async_cookie_t cookie) | ||
1082 | { | ||
1083 | struct snd_soc_dapm_context *d = data; | ||
1084 | int ret; | ||
1085 | |||
1086 | /* If we just powered the last thing off drop to standby bias */ | ||
1087 | if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) { | ||
1088 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY); | ||
1089 | if (ret != 0) | ||
1090 | dev_err(d->dev, "Failed to apply standby bias: %d\n", | ||
1091 | ret); | ||
1092 | } | ||
1093 | |||
1094 | /* If we're in standby and can support bias off then do that */ | ||
1095 | if (d->bias_level == SND_SOC_BIAS_STANDBY && d->idle_bias_off) { | ||
1096 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF); | ||
1097 | if (ret != 0) | ||
1098 | dev_err(d->dev, "Failed to turn off bias: %d\n", ret); | ||
1099 | } | ||
1100 | |||
1101 | /* If we just powered up then move to active bias */ | ||
1102 | if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) { | ||
1103 | ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON); | ||
1104 | if (ret != 0) | ||
1105 | dev_err(d->dev, "Failed to apply active bias: %d\n", | ||
1106 | ret); | ||
1107 | } | ||
1108 | } | ||
981 | 1109 | ||
982 | /* | 1110 | /* |
983 | * Scan each dapm widget for complete audio path. | 1111 | * Scan each dapm widget for complete audio path. |
@@ -990,12 +1118,12 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm) | |||
990 | */ | 1118 | */ |
991 | static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | 1119 | static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) |
992 | { | 1120 | { |
993 | struct snd_soc_card *card = dapm->codec->card; | 1121 | struct snd_soc_card *card = dapm->card; |
994 | struct snd_soc_dapm_widget *w; | 1122 | struct snd_soc_dapm_widget *w; |
995 | struct snd_soc_dapm_context *d; | 1123 | struct snd_soc_dapm_context *d; |
996 | LIST_HEAD(up_list); | 1124 | LIST_HEAD(up_list); |
997 | LIST_HEAD(down_list); | 1125 | LIST_HEAD(down_list); |
998 | int ret = 0; | 1126 | LIST_HEAD(async_domain); |
999 | int power; | 1127 | int power; |
1000 | 1128 | ||
1001 | trace_snd_soc_dapm_start(card); | 1129 | trace_snd_soc_dapm_start(card); |
@@ -1010,10 +1138,10 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1010 | list_for_each_entry(w, &card->widgets, list) { | 1138 | list_for_each_entry(w, &card->widgets, list) { |
1011 | switch (w->id) { | 1139 | switch (w->id) { |
1012 | case snd_soc_dapm_pre: | 1140 | case snd_soc_dapm_pre: |
1013 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 1141 | dapm_seq_insert(w, &down_list, false); |
1014 | break; | 1142 | break; |
1015 | case snd_soc_dapm_post: | 1143 | case snd_soc_dapm_post: |
1016 | dapm_seq_insert(w, &up_list, dapm_up_seq); | 1144 | dapm_seq_insert(w, &up_list, true); |
1017 | break; | 1145 | break; |
1018 | 1146 | ||
1019 | default: | 1147 | default: |
@@ -1033,9 +1161,9 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1033 | trace_snd_soc_dapm_widget_power(w, power); | 1161 | trace_snd_soc_dapm_widget_power(w, power); |
1034 | 1162 | ||
1035 | if (power) | 1163 | if (power) |
1036 | dapm_seq_insert(w, &up_list, dapm_up_seq); | 1164 | dapm_seq_insert(w, &up_list, true); |
1037 | else | 1165 | else |
1038 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 1166 | dapm_seq_insert(w, &down_list, false); |
1039 | 1167 | ||
1040 | w->power = power; | 1168 | w->power = power; |
1041 | break; | 1169 | break; |
@@ -1073,65 +1201,25 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) | |||
1073 | } | 1201 | } |
1074 | } | 1202 | } |
1075 | 1203 | ||
1076 | list_for_each_entry(d, &dapm->card->dapm_list, list) { | 1204 | /* Run all the bias changes in parallel */ |
1077 | if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) { | 1205 | list_for_each_entry(d, &dapm->card->dapm_list, list) |
1078 | ret = snd_soc_dapm_set_bias_level(card, d, | 1206 | async_schedule_domain(dapm_pre_sequence_async, d, |
1079 | SND_SOC_BIAS_STANDBY); | 1207 | &async_domain); |
1080 | if (ret != 0) | 1208 | async_synchronize_full_domain(&async_domain); |
1081 | dev_err(d->dev, | ||
1082 | "Failed to turn on bias: %d\n", ret); | ||
1083 | } | ||
1084 | |||
1085 | /* If we're changing to all on or all off then prepare */ | ||
1086 | if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) || | ||
1087 | (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) { | ||
1088 | ret = snd_soc_dapm_set_bias_level(card, d, | ||
1089 | SND_SOC_BIAS_PREPARE); | ||
1090 | if (ret != 0) | ||
1091 | dev_err(d->dev, | ||
1092 | "Failed to prepare bias: %d\n", ret); | ||
1093 | } | ||
1094 | } | ||
1095 | 1209 | ||
1096 | /* Power down widgets first; try to avoid amplifying pops. */ | 1210 | /* Power down widgets first; try to avoid amplifying pops. */ |
1097 | dapm_seq_run(dapm, &down_list, event, dapm_down_seq); | 1211 | dapm_seq_run(dapm, &down_list, event, false); |
1098 | 1212 | ||
1099 | dapm_widget_update(dapm); | 1213 | dapm_widget_update(dapm); |
1100 | 1214 | ||
1101 | /* Now power up. */ | 1215 | /* Now power up. */ |
1102 | dapm_seq_run(dapm, &up_list, event, dapm_up_seq); | 1216 | dapm_seq_run(dapm, &up_list, event, true); |
1103 | |||
1104 | list_for_each_entry(d, &dapm->card->dapm_list, list) { | ||
1105 | /* If we just powered the last thing off drop to standby bias */ | ||
1106 | if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) { | ||
1107 | ret = snd_soc_dapm_set_bias_level(card, d, | ||
1108 | SND_SOC_BIAS_STANDBY); | ||
1109 | if (ret != 0) | ||
1110 | dev_err(d->dev, | ||
1111 | "Failed to apply standby bias: %d\n", | ||
1112 | ret); | ||
1113 | } | ||
1114 | 1217 | ||
1115 | /* If we're in standby and can support bias off then do that */ | 1218 | /* Run all the bias changes in parallel */ |
1116 | if (d->bias_level == SND_SOC_BIAS_STANDBY && | 1219 | list_for_each_entry(d, &dapm->card->dapm_list, list) |
1117 | d->idle_bias_off) { | 1220 | async_schedule_domain(dapm_post_sequence_async, d, |
1118 | ret = snd_soc_dapm_set_bias_level(card, d, | 1221 | &async_domain); |
1119 | SND_SOC_BIAS_OFF); | 1222 | async_synchronize_full_domain(&async_domain); |
1120 | if (ret != 0) | ||
1121 | dev_err(d->dev, | ||
1122 | "Failed to turn off bias: %d\n", ret); | ||
1123 | } | ||
1124 | |||
1125 | /* If we just powered up then move to active bias */ | ||
1126 | if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) { | ||
1127 | ret = snd_soc_dapm_set_bias_level(card, d, | ||
1128 | SND_SOC_BIAS_ON); | ||
1129 | if (ret != 0) | ||
1130 | dev_err(d->dev, | ||
1131 | "Failed to apply active bias: %d\n", | ||
1132 | ret); | ||
1133 | } | ||
1134 | } | ||
1135 | 1223 | ||
1136 | pop_dbg(dapm->dev, card->pop_time, | 1224 | pop_dbg(dapm->dev, card->pop_time, |
1137 | "DAPM sequencing finished, waiting %dms\n", card->pop_time); | 1225 | "DAPM sequencing finished, waiting %dms\n", card->pop_time); |
@@ -1189,7 +1277,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1189 | 1277 | ||
1190 | if (p->connect) | 1278 | if (p->connect) |
1191 | ret += snprintf(buf + ret, PAGE_SIZE - ret, | 1279 | ret += snprintf(buf + ret, PAGE_SIZE - ret, |
1192 | " in %s %s\n", | 1280 | " in \"%s\" \"%s\"\n", |
1193 | p->name ? p->name : "static", | 1281 | p->name ? p->name : "static", |
1194 | p->source->name); | 1282 | p->source->name); |
1195 | } | 1283 | } |
@@ -1199,7 +1287,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, | |||
1199 | 1287 | ||
1200 | if (p->connect) | 1288 | if (p->connect) |
1201 | ret += snprintf(buf + ret, PAGE_SIZE - ret, | 1289 | ret += snprintf(buf + ret, PAGE_SIZE - ret, |
1202 | " out %s %s\n", | 1290 | " out \"%s\" \"%s\"\n", |
1203 | p->name ? p->name : "static", | 1291 | p->name ? p->name : "static", |
1204 | p->sink->name); | 1292 | p->sink->name); |
1205 | } | 1293 | } |
@@ -1464,7 +1552,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm, | |||
1464 | char prefixed_source[80]; | 1552 | char prefixed_source[80]; |
1465 | int ret = 0; | 1553 | int ret = 0; |
1466 | 1554 | ||
1467 | if (dapm->codec->name_prefix) { | 1555 | if (dapm->codec && dapm->codec->name_prefix) { |
1468 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", | 1556 | snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s", |
1469 | dapm->codec->name_prefix, route->sink); | 1557 | dapm->codec->name_prefix, route->sink); |
1470 | sink = prefixed_sink; | 1558 | sink = prefixed_sink; |
@@ -2114,14 +2202,14 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
2114 | return -ENOMEM; | 2202 | return -ENOMEM; |
2115 | 2203 | ||
2116 | name_len = strlen(widget->name) + 1; | 2204 | name_len = strlen(widget->name) + 1; |
2117 | if (dapm->codec->name_prefix) | 2205 | if (dapm->codec && dapm->codec->name_prefix) |
2118 | name_len += 1 + strlen(dapm->codec->name_prefix); | 2206 | name_len += 1 + strlen(dapm->codec->name_prefix); |
2119 | w->name = kmalloc(name_len, GFP_KERNEL); | 2207 | w->name = kmalloc(name_len, GFP_KERNEL); |
2120 | if (w->name == NULL) { | 2208 | if (w->name == NULL) { |
2121 | kfree(w); | 2209 | kfree(w); |
2122 | return -ENOMEM; | 2210 | return -ENOMEM; |
2123 | } | 2211 | } |
2124 | if (dapm->codec->name_prefix) | 2212 | if (dapm->codec && dapm->codec->name_prefix) |
2125 | snprintf(w->name, name_len, "%s %s", | 2213 | snprintf(w->name, name_len, "%s %s", |
2126 | dapm->codec->name_prefix, widget->name); | 2214 | dapm->codec->name_prefix, widget->name); |
2127 | else | 2215 | else |
@@ -2226,7 +2314,6 @@ int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, | |||
2226 | mutex_unlock(&codec->mutex); | 2314 | mutex_unlock(&codec->mutex); |
2227 | return 0; | 2315 | return 0; |
2228 | } | 2316 | } |
2229 | EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); | ||
2230 | 2317 | ||
2231 | /** | 2318 | /** |
2232 | * snd_soc_dapm_enable_pin - enable pin. | 2319 | * snd_soc_dapm_enable_pin - enable pin. |
@@ -2393,7 +2480,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | |||
2393 | if (w->dapm != dapm) | 2480 | if (w->dapm != dapm) |
2394 | continue; | 2481 | continue; |
2395 | if (w->power) { | 2482 | if (w->power) { |
2396 | dapm_seq_insert(w, &down_list, dapm_down_seq); | 2483 | dapm_seq_insert(w, &down_list, false); |
2397 | w->power = 0; | 2484 | w->power = 0; |
2398 | powerdown = 1; | 2485 | powerdown = 1; |
2399 | } | 2486 | } |
@@ -2403,9 +2490,9 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm) | |||
2403 | * standby. | 2490 | * standby. |
2404 | */ | 2491 | */ |
2405 | if (powerdown) { | 2492 | if (powerdown) { |
2406 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE); | 2493 | snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE); |
2407 | dapm_seq_run(dapm, &down_list, 0, dapm_down_seq); | 2494 | dapm_seq_run(dapm, &down_list, 0, false); |
2408 | snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY); | 2495 | snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY); |
2409 | } | 2496 | } |
2410 | } | 2497 | } |
2411 | 2498 | ||
@@ -2418,7 +2505,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) | |||
2418 | 2505 | ||
2419 | list_for_each_entry(codec, &card->codec_dev_list, list) { | 2506 | list_for_each_entry(codec, &card->codec_dev_list, list) { |
2420 | soc_dapm_shutdown_codec(&codec->dapm); | 2507 | soc_dapm_shutdown_codec(&codec->dapm); |
2421 | snd_soc_dapm_set_bias_level(card, &codec->dapm, SND_SOC_BIAS_OFF); | 2508 | snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF); |
2422 | } | 2509 | } |
2423 | } | 2510 | } |
2424 | 2511 | ||
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index ac5a5bc7375a..fcab80b36a37 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -37,6 +37,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type, | |||
37 | { | 37 | { |
38 | jack->codec = codec; | 38 | jack->codec = codec; |
39 | INIT_LIST_HEAD(&jack->pins); | 39 | INIT_LIST_HEAD(&jack->pins); |
40 | INIT_LIST_HEAD(&jack->jack_zones); | ||
40 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); | 41 | BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); |
41 | 42 | ||
42 | return snd_jack_new(codec->card->snd_card, id, type, &jack->jack); | 43 | return snd_jack_new(codec->card->snd_card, id, type, &jack->jack); |
@@ -100,7 +101,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
100 | } | 101 | } |
101 | 102 | ||
102 | /* Report before the DAPM sync to help users updating micbias status */ | 103 | /* Report before the DAPM sync to help users updating micbias status */ |
103 | blocking_notifier_call_chain(&jack->notifier, status, NULL); | 104 | blocking_notifier_call_chain(&jack->notifier, status, jack); |
104 | 105 | ||
105 | snd_soc_dapm_sync(dapm); | 106 | snd_soc_dapm_sync(dapm); |
106 | 107 | ||
@@ -112,6 +113,51 @@ out: | |||
112 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); | 113 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); |
113 | 114 | ||
114 | /** | 115 | /** |
116 | * snd_soc_jack_add_zones - Associate voltage zones with jack | ||
117 | * | ||
118 | * @jack: ASoC jack | ||
119 | * @count: Number of zones | ||
120 | * @zone: Array of zones | ||
121 | * | ||
122 | * After this function has been called the zones specified in the | ||
123 | * array will be associated with the jack. | ||
124 | */ | ||
125 | int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count, | ||
126 | struct snd_soc_jack_zone *zones) | ||
127 | { | ||
128 | int i; | ||
129 | |||
130 | for (i = 0; i < count; i++) { | ||
131 | INIT_LIST_HEAD(&zones[i].list); | ||
132 | list_add(&(zones[i].list), &jack->jack_zones); | ||
133 | } | ||
134 | return 0; | ||
135 | } | ||
136 | EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones); | ||
137 | |||
138 | /** | ||
139 | * snd_soc_jack_get_type - Based on the mic bias value, this function returns | ||
140 | * the type of jack from the zones delcared in the jack type | ||
141 | * | ||
142 | * @micbias_voltage: mic bias voltage at adc channel when jack is plugged in | ||
143 | * | ||
144 | * Based on the mic bias value passed, this function helps identify | ||
145 | * the type of jack from the already delcared jack zones | ||
146 | */ | ||
147 | int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage) | ||
148 | { | ||
149 | struct snd_soc_jack_zone *zone; | ||
150 | |||
151 | list_for_each_entry(zone, &jack->jack_zones, list) { | ||
152 | if (micbias_voltage >= zone->min_mv && | ||
153 | micbias_voltage < zone->max_mv) | ||
154 | return zone->jack_type; | ||
155 | } | ||
156 | return 0; | ||
157 | } | ||
158 | EXPORT_SYMBOL_GPL(snd_soc_jack_get_type); | ||
159 | |||
160 | /** | ||
115 | * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack | 161 | * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack |
116 | * | 162 | * |
117 | * @jack: ASoC jack | 163 | * @jack: ASoC jack |
@@ -194,7 +240,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) | |||
194 | int enable; | 240 | int enable; |
195 | int report; | 241 | int report; |
196 | 242 | ||
197 | enable = gpio_get_value(gpio->gpio); | 243 | enable = gpio_get_value_cansleep(gpio->gpio); |
198 | if (gpio->invert) | 244 | if (gpio->invert) |
199 | enable = !enable; | 245 | enable = !enable; |
200 | 246 | ||
@@ -284,6 +330,14 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | |||
284 | if (ret) | 330 | if (ret) |
285 | goto err; | 331 | goto err; |
286 | 332 | ||
333 | if (gpios[i].wake) { | ||
334 | ret = set_irq_wake(gpio_to_irq(gpios[i].gpio), 1); | ||
335 | if (ret != 0) | ||
336 | printk(KERN_ERR | ||
337 | "Failed to mark GPIO %d as wake source: %d\n", | ||
338 | gpios[i].gpio, ret); | ||
339 | } | ||
340 | |||
287 | #ifdef CONFIG_GPIO_SYSFS | 341 | #ifdef CONFIG_GPIO_SYSFS |
288 | /* Expose GPIO value over sysfs for diagnostic purposes */ | 342 | /* Expose GPIO value over sysfs for diagnostic purposes */ |
289 | gpio_export(gpios[i].gpio, false); | 343 | gpio_export(gpios[i].gpio, false); |
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index 1d07b931f3d8..3f45e6a439bf 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c | |||
@@ -28,26 +28,9 @@ int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params) | |||
28 | { | 28 | { |
29 | int sample_size; | 29 | int sample_size; |
30 | 30 | ||
31 | switch (params_format(params)) { | 31 | sample_size = snd_pcm_format_width(params_format(params)); |
32 | case SNDRV_PCM_FORMAT_S16_LE: | 32 | if (sample_size < 0) |
33 | case SNDRV_PCM_FORMAT_S16_BE: | 33 | return sample_size; |
34 | sample_size = 16; | ||
35 | break; | ||
36 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
37 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
38 | sample_size = 20; | ||
39 | break; | ||
40 | case SNDRV_PCM_FORMAT_S24_LE: | ||
41 | case SNDRV_PCM_FORMAT_S24_BE: | ||
42 | sample_size = 24; | ||
43 | break; | ||
44 | case SNDRV_PCM_FORMAT_S32_LE: | ||
45 | case SNDRV_PCM_FORMAT_S32_BE: | ||
46 | sample_size = 32; | ||
47 | break; | ||
48 | default: | ||
49 | return -ENOTSUPP; | ||
50 | } | ||
51 | 34 | ||
52 | return snd_soc_calc_frame_size(sample_size, params_channels(params), | 35 | return snd_soc_calc_frame_size(sample_size, params_channels(params), |
53 | 1); | 36 | 1); |
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig new file mode 100644 index 000000000000..66b504f06c23 --- /dev/null +++ b/sound/soc/tegra/Kconfig | |||
@@ -0,0 +1,26 @@ | |||
1 | config SND_TEGRA_SOC | ||
2 | tristate "SoC Audio for the Tegra System-on-Chip" | ||
3 | depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA | ||
4 | default m | ||
5 | help | ||
6 | Say Y or M here if you want support for SoC audio on Tegra. | ||
7 | |||
8 | config SND_TEGRA_SOC_I2S | ||
9 | tristate | ||
10 | depends on SND_TEGRA_SOC | ||
11 | default m | ||
12 | help | ||
13 | Say Y or M if you want to add support for codecs attached to the | ||
14 | Tegra I2S interface. You will also need to select the individual | ||
15 | machine drivers to support below. | ||
16 | |||
17 | config SND_TEGRA_SOC_HARMONY | ||
18 | tristate "SoC Audio support for Tegra Harmony reference board" | ||
19 | depends on SND_TEGRA_SOC && MACH_HARMONY && I2C | ||
20 | default m | ||
21 | select SND_TEGRA_SOC_I2S | ||
22 | select SND_SOC_WM8903 | ||
23 | help | ||
24 | Say Y or M here if you want to add support for SoC audio on the | ||
25 | Tegra Harmony reference board. | ||
26 | |||
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile new file mode 100644 index 000000000000..fd183d3ab4f1 --- /dev/null +++ b/sound/soc/tegra/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | # Tegra platform Support | ||
2 | snd-soc-tegra-das-objs := tegra_das.o | ||
3 | snd-soc-tegra-pcm-objs := tegra_pcm.o | ||
4 | snd-soc-tegra-i2s-objs := tegra_i2s.o | ||
5 | snd-soc-tegra-utils-objs += tegra_asoc_utils.o | ||
6 | |||
7 | obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-utils.o | ||
8 | obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-das.o | ||
9 | obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-pcm.o | ||
10 | obj-$(CONFIG_SND_TEGRA_SOC_I2S) += snd-soc-tegra-i2s.o | ||
11 | |||
12 | # Tegra machine Support | ||
13 | snd-soc-tegra-harmony-objs := harmony.o | ||
14 | |||
15 | obj-$(CONFIG_SND_TEGRA_SOC_HARMONY) += snd-soc-tegra-harmony.o | ||
diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c new file mode 100644 index 000000000000..8585957477eb --- /dev/null +++ b/sound/soc/tegra/harmony.c | |||
@@ -0,0 +1,393 @@ | |||
1 | /* | ||
2 | * harmony.c - Harmony machine ASoC driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010-2011 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * | ||
9 | * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd. | ||
10 | * | ||
11 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
12 | * Author: Graeme Gregory | ||
13 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | * General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
27 | * 02110-1301 USA | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <asm/mach-types.h> | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/platform_device.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/gpio.h> | ||
37 | |||
38 | #include <mach/harmony_audio.h> | ||
39 | |||
40 | #include <sound/core.h> | ||
41 | #include <sound/jack.h> | ||
42 | #include <sound/pcm.h> | ||
43 | #include <sound/pcm_params.h> | ||
44 | #include <sound/soc.h> | ||
45 | |||
46 | #include "../codecs/wm8903.h" | ||
47 | |||
48 | #include "tegra_das.h" | ||
49 | #include "tegra_i2s.h" | ||
50 | #include "tegra_pcm.h" | ||
51 | #include "tegra_asoc_utils.h" | ||
52 | |||
53 | #define DRV_NAME "tegra-snd-harmony" | ||
54 | |||
55 | #define GPIO_SPKR_EN BIT(0) | ||
56 | #define GPIO_INT_MIC_EN BIT(1) | ||
57 | #define GPIO_EXT_MIC_EN BIT(2) | ||
58 | |||
59 | struct tegra_harmony { | ||
60 | struct tegra_asoc_utils_data util_data; | ||
61 | struct harmony_audio_platform_data *pdata; | ||
62 | int gpio_requested; | ||
63 | }; | ||
64 | |||
65 | static int harmony_asoc_hw_params(struct snd_pcm_substream *substream, | ||
66 | struct snd_pcm_hw_params *params) | ||
67 | { | ||
68 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
69 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
70 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
71 | struct snd_soc_codec *codec = rtd->codec; | ||
72 | struct snd_soc_card *card = codec->card; | ||
73 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
74 | int srate, mclk, mclk_change; | ||
75 | int err; | ||
76 | |||
77 | srate = params_rate(params); | ||
78 | switch (srate) { | ||
79 | case 64000: | ||
80 | case 88200: | ||
81 | case 96000: | ||
82 | mclk = 128 * srate; | ||
83 | break; | ||
84 | default: | ||
85 | mclk = 256 * srate; | ||
86 | break; | ||
87 | } | ||
88 | /* FIXME: Codec only requires >= 3MHz if OSR==0 */ | ||
89 | while (mclk < 6000000) | ||
90 | mclk *= 2; | ||
91 | |||
92 | err = tegra_asoc_utils_set_rate(&harmony->util_data, srate, mclk, | ||
93 | &mclk_change); | ||
94 | if (err < 0) { | ||
95 | dev_err(card->dev, "Can't configure clocks\n"); | ||
96 | return err; | ||
97 | } | ||
98 | |||
99 | err = snd_soc_dai_set_fmt(codec_dai, | ||
100 | SND_SOC_DAIFMT_I2S | | ||
101 | SND_SOC_DAIFMT_NB_NF | | ||
102 | SND_SOC_DAIFMT_CBS_CFS); | ||
103 | if (err < 0) { | ||
104 | dev_err(card->dev, "codec_dai fmt not set\n"); | ||
105 | return err; | ||
106 | } | ||
107 | |||
108 | err = snd_soc_dai_set_fmt(cpu_dai, | ||
109 | SND_SOC_DAIFMT_I2S | | ||
110 | SND_SOC_DAIFMT_NB_NF | | ||
111 | SND_SOC_DAIFMT_CBS_CFS); | ||
112 | if (err < 0) { | ||
113 | dev_err(card->dev, "cpu_dai fmt not set\n"); | ||
114 | return err; | ||
115 | } | ||
116 | |||
117 | if (mclk_change) { | ||
118 | err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, | ||
119 | SND_SOC_CLOCK_IN); | ||
120 | if (err < 0) { | ||
121 | dev_err(card->dev, "codec_dai clock not set\n"); | ||
122 | return err; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static struct snd_soc_ops harmony_asoc_ops = { | ||
130 | .hw_params = harmony_asoc_hw_params, | ||
131 | }; | ||
132 | |||
133 | static struct snd_soc_jack harmony_hp_jack; | ||
134 | |||
135 | static struct snd_soc_jack_pin harmony_hp_jack_pins[] = { | ||
136 | { | ||
137 | .pin = "Headphone Jack", | ||
138 | .mask = SND_JACK_HEADPHONE, | ||
139 | }, | ||
140 | }; | ||
141 | |||
142 | static struct snd_soc_jack_gpio harmony_hp_jack_gpios[] = { | ||
143 | { | ||
144 | .name = "headphone detect", | ||
145 | .report = SND_JACK_HEADPHONE, | ||
146 | .debounce_time = 150, | ||
147 | .invert = 1, | ||
148 | } | ||
149 | }; | ||
150 | |||
151 | static struct snd_soc_jack harmony_mic_jack; | ||
152 | |||
153 | static struct snd_soc_jack_pin harmony_mic_jack_pins[] = { | ||
154 | { | ||
155 | .pin = "Mic Jack", | ||
156 | .mask = SND_JACK_MICROPHONE, | ||
157 | }, | ||
158 | }; | ||
159 | |||
160 | static int harmony_event_int_spk(struct snd_soc_dapm_widget *w, | ||
161 | struct snd_kcontrol *k, int event) | ||
162 | { | ||
163 | struct snd_soc_codec *codec = w->codec; | ||
164 | struct snd_soc_card *card = codec->card; | ||
165 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
166 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
167 | |||
168 | gpio_set_value_cansleep(pdata->gpio_spkr_en, | ||
169 | SND_SOC_DAPM_EVENT_ON(event)); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = { | ||
175 | SND_SOC_DAPM_SPK("Int Spk", harmony_event_int_spk), | ||
176 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
177 | SND_SOC_DAPM_MIC("Mic Jack", NULL), | ||
178 | }; | ||
179 | |||
180 | static const struct snd_soc_dapm_route harmony_audio_map[] = { | ||
181 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
182 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
183 | {"Int Spk", NULL, "ROP"}, | ||
184 | {"Int Spk", NULL, "RON"}, | ||
185 | {"Int Spk", NULL, "LOP"}, | ||
186 | {"Int Spk", NULL, "LON"}, | ||
187 | {"Mic Bias", NULL, "Mic Jack"}, | ||
188 | {"IN1L", NULL, "Mic Bias"}, | ||
189 | }; | ||
190 | |||
191 | static const struct snd_kcontrol_new harmony_controls[] = { | ||
192 | SOC_DAPM_PIN_SWITCH("Int Spk"), | ||
193 | }; | ||
194 | |||
195 | static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd) | ||
196 | { | ||
197 | struct snd_soc_codec *codec = rtd->codec; | ||
198 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
199 | struct snd_soc_card *card = codec->card; | ||
200 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
201 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
202 | int ret; | ||
203 | |||
204 | ret = gpio_request(pdata->gpio_spkr_en, "spkr_en"); | ||
205 | if (ret) { | ||
206 | dev_err(card->dev, "cannot get spkr_en gpio\n"); | ||
207 | return ret; | ||
208 | } | ||
209 | harmony->gpio_requested |= GPIO_SPKR_EN; | ||
210 | |||
211 | gpio_direction_output(pdata->gpio_spkr_en, 0); | ||
212 | |||
213 | ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en"); | ||
214 | if (ret) { | ||
215 | dev_err(card->dev, "cannot get int_mic_en gpio\n"); | ||
216 | return ret; | ||
217 | } | ||
218 | harmony->gpio_requested |= GPIO_INT_MIC_EN; | ||
219 | |||
220 | /* Disable int mic; enable signal is active-high */ | ||
221 | gpio_direction_output(pdata->gpio_int_mic_en, 0); | ||
222 | |||
223 | ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en"); | ||
224 | if (ret) { | ||
225 | dev_err(card->dev, "cannot get ext_mic_en gpio\n"); | ||
226 | return ret; | ||
227 | } | ||
228 | harmony->gpio_requested |= GPIO_EXT_MIC_EN; | ||
229 | |||
230 | /* Enable ext mic; enable signal is active-low */ | ||
231 | gpio_direction_output(pdata->gpio_ext_mic_en, 0); | ||
232 | |||
233 | ret = snd_soc_add_controls(codec, harmony_controls, | ||
234 | ARRAY_SIZE(harmony_controls)); | ||
235 | if (ret < 0) | ||
236 | return ret; | ||
237 | |||
238 | snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets, | ||
239 | ARRAY_SIZE(harmony_dapm_widgets)); | ||
240 | |||
241 | snd_soc_dapm_add_routes(dapm, harmony_audio_map, | ||
242 | ARRAY_SIZE(harmony_audio_map)); | ||
243 | |||
244 | harmony_hp_jack_gpios[0].gpio = pdata->gpio_hp_det; | ||
245 | snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE, | ||
246 | &harmony_hp_jack); | ||
247 | snd_soc_jack_add_pins(&harmony_hp_jack, | ||
248 | ARRAY_SIZE(harmony_hp_jack_pins), | ||
249 | harmony_hp_jack_pins); | ||
250 | snd_soc_jack_add_gpios(&harmony_hp_jack, | ||
251 | ARRAY_SIZE(harmony_hp_jack_gpios), | ||
252 | harmony_hp_jack_gpios); | ||
253 | |||
254 | snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE, | ||
255 | &harmony_mic_jack); | ||
256 | snd_soc_jack_add_pins(&harmony_mic_jack, | ||
257 | ARRAY_SIZE(harmony_mic_jack_pins), | ||
258 | harmony_mic_jack_pins); | ||
259 | wm8903_mic_detect(codec, &harmony_mic_jack, SND_JACK_MICROPHONE, 0); | ||
260 | |||
261 | snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); | ||
262 | |||
263 | snd_soc_dapm_nc_pin(dapm, "IN3L"); | ||
264 | snd_soc_dapm_nc_pin(dapm, "IN3R"); | ||
265 | snd_soc_dapm_nc_pin(dapm, "LINEOUTL"); | ||
266 | snd_soc_dapm_nc_pin(dapm, "LINEOUTR"); | ||
267 | |||
268 | snd_soc_dapm_sync(dapm); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static struct snd_soc_dai_link harmony_wm8903_dai = { | ||
274 | .name = "WM8903", | ||
275 | .stream_name = "WM8903 PCM", | ||
276 | .codec_name = "wm8903.0-001a", | ||
277 | .platform_name = "tegra-pcm-audio", | ||
278 | .cpu_dai_name = "tegra-i2s.0", | ||
279 | .codec_dai_name = "wm8903-hifi", | ||
280 | .init = harmony_asoc_init, | ||
281 | .ops = &harmony_asoc_ops, | ||
282 | }; | ||
283 | |||
284 | static struct snd_soc_card snd_soc_harmony = { | ||
285 | .name = "tegra-harmony", | ||
286 | .dai_link = &harmony_wm8903_dai, | ||
287 | .num_links = 1, | ||
288 | }; | ||
289 | |||
290 | static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev) | ||
291 | { | ||
292 | struct snd_soc_card *card = &snd_soc_harmony; | ||
293 | struct tegra_harmony *harmony; | ||
294 | struct harmony_audio_platform_data *pdata; | ||
295 | int ret; | ||
296 | |||
297 | if (!machine_is_harmony()) { | ||
298 | dev_err(&pdev->dev, "Not running on Tegra Harmony!\n"); | ||
299 | return -ENODEV; | ||
300 | } | ||
301 | |||
302 | pdata = pdev->dev.platform_data; | ||
303 | if (!pdata) { | ||
304 | dev_err(&pdev->dev, "no platform data supplied\n"); | ||
305 | return -EINVAL; | ||
306 | } | ||
307 | |||
308 | harmony = kzalloc(sizeof(struct tegra_harmony), GFP_KERNEL); | ||
309 | if (!harmony) { | ||
310 | dev_err(&pdev->dev, "Can't allocate tegra_harmony\n"); | ||
311 | return -ENOMEM; | ||
312 | } | ||
313 | |||
314 | harmony->pdata = pdata; | ||
315 | |||
316 | ret = tegra_asoc_utils_init(&harmony->util_data, &pdev->dev); | ||
317 | if (ret) | ||
318 | goto err_free_harmony; | ||
319 | |||
320 | card->dev = &pdev->dev; | ||
321 | platform_set_drvdata(pdev, card); | ||
322 | snd_soc_card_set_drvdata(card, harmony); | ||
323 | |||
324 | ret = snd_soc_register_card(card); | ||
325 | if (ret) { | ||
326 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", | ||
327 | ret); | ||
328 | goto err_clear_drvdata; | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | |||
333 | err_clear_drvdata: | ||
334 | snd_soc_card_set_drvdata(card, NULL); | ||
335 | platform_set_drvdata(pdev, NULL); | ||
336 | card->dev = NULL; | ||
337 | tegra_asoc_utils_fini(&harmony->util_data); | ||
338 | err_free_harmony: | ||
339 | kfree(harmony); | ||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | static int __devexit tegra_snd_harmony_remove(struct platform_device *pdev) | ||
344 | { | ||
345 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
346 | struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card); | ||
347 | struct harmony_audio_platform_data *pdata = harmony->pdata; | ||
348 | |||
349 | snd_soc_unregister_card(card); | ||
350 | |||
351 | snd_soc_card_set_drvdata(card, NULL); | ||
352 | platform_set_drvdata(pdev, NULL); | ||
353 | card->dev = NULL; | ||
354 | |||
355 | tegra_asoc_utils_fini(&harmony->util_data); | ||
356 | |||
357 | if (harmony->gpio_requested & GPIO_EXT_MIC_EN) | ||
358 | gpio_free(pdata->gpio_ext_mic_en); | ||
359 | if (harmony->gpio_requested & GPIO_INT_MIC_EN) | ||
360 | gpio_free(pdata->gpio_int_mic_en); | ||
361 | if (harmony->gpio_requested & GPIO_SPKR_EN) | ||
362 | gpio_free(pdata->gpio_spkr_en); | ||
363 | |||
364 | kfree(harmony); | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static struct platform_driver tegra_snd_harmony_driver = { | ||
370 | .driver = { | ||
371 | .name = DRV_NAME, | ||
372 | .owner = THIS_MODULE, | ||
373 | }, | ||
374 | .probe = tegra_snd_harmony_probe, | ||
375 | .remove = __devexit_p(tegra_snd_harmony_remove), | ||
376 | }; | ||
377 | |||
378 | static int __init snd_tegra_harmony_init(void) | ||
379 | { | ||
380 | return platform_driver_register(&tegra_snd_harmony_driver); | ||
381 | } | ||
382 | module_init(snd_tegra_harmony_init); | ||
383 | |||
384 | static void __exit snd_tegra_harmony_exit(void) | ||
385 | { | ||
386 | platform_driver_unregister(&tegra_snd_harmony_driver); | ||
387 | } | ||
388 | module_exit(snd_tegra_harmony_exit); | ||
389 | |||
390 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
391 | MODULE_DESCRIPTION("Harmony machine ASoC driver"); | ||
392 | MODULE_LICENSE("GPL"); | ||
393 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c new file mode 100644 index 000000000000..52f0a3f9ce40 --- /dev/null +++ b/sound/soc/tegra/tegra_asoc_utils.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * tegra_asoc_utils.c - Harmony machine ASoC driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * 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., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/clk.h> | ||
24 | #include <linux/device.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/kernel.h> | ||
27 | |||
28 | #include "tegra_asoc_utils.h" | ||
29 | |||
30 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | ||
31 | int mclk, int *mclk_change) | ||
32 | { | ||
33 | int new_baseclock; | ||
34 | int err; | ||
35 | |||
36 | switch (srate) { | ||
37 | case 11025: | ||
38 | case 22050: | ||
39 | case 44100: | ||
40 | case 88200: | ||
41 | new_baseclock = 56448000; | ||
42 | break; | ||
43 | case 8000: | ||
44 | case 16000: | ||
45 | case 32000: | ||
46 | case 48000: | ||
47 | case 64000: | ||
48 | case 96000: | ||
49 | new_baseclock = 73728000; | ||
50 | break; | ||
51 | default: | ||
52 | return -EINVAL; | ||
53 | } | ||
54 | |||
55 | *mclk_change = ((new_baseclock != data->set_baseclock) || | ||
56 | (mclk != data->set_mclk)); | ||
57 | if (!*mclk_change) | ||
58 | return 0; | ||
59 | |||
60 | data->set_baseclock = 0; | ||
61 | data->set_mclk = 0; | ||
62 | |||
63 | clk_disable(data->clk_cdev1); | ||
64 | clk_disable(data->clk_pll_a_out0); | ||
65 | clk_disable(data->clk_pll_a); | ||
66 | |||
67 | err = clk_set_rate(data->clk_pll_a, new_baseclock); | ||
68 | if (err) { | ||
69 | dev_err(data->dev, "Can't set pll_a rate: %d\n", err); | ||
70 | return err; | ||
71 | } | ||
72 | |||
73 | err = clk_set_rate(data->clk_pll_a_out0, mclk); | ||
74 | if (err) { | ||
75 | dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err); | ||
76 | return err; | ||
77 | } | ||
78 | |||
79 | /* Don't set cdev1 rate; its locked to pll_a_out0 */ | ||
80 | |||
81 | err = clk_enable(data->clk_pll_a); | ||
82 | if (err) { | ||
83 | dev_err(data->dev, "Can't enable pll_a: %d\n", err); | ||
84 | return err; | ||
85 | } | ||
86 | |||
87 | err = clk_enable(data->clk_pll_a_out0); | ||
88 | if (err) { | ||
89 | dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err); | ||
90 | return err; | ||
91 | } | ||
92 | |||
93 | err = clk_enable(data->clk_cdev1); | ||
94 | if (err) { | ||
95 | dev_err(data->dev, "Can't enable cdev1: %d\n", err); | ||
96 | return err; | ||
97 | } | ||
98 | |||
99 | data->set_baseclock = new_baseclock; | ||
100 | data->set_mclk = mclk; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate); | ||
105 | |||
106 | int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, | ||
107 | struct device *dev) | ||
108 | { | ||
109 | int ret; | ||
110 | |||
111 | data->dev = dev; | ||
112 | |||
113 | data->clk_pll_a = clk_get_sys(NULL, "pll_a"); | ||
114 | if (IS_ERR(data->clk_pll_a)) { | ||
115 | dev_err(data->dev, "Can't retrieve clk pll_a\n"); | ||
116 | ret = PTR_ERR(data->clk_pll_a); | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | data->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0"); | ||
121 | if (IS_ERR(data->clk_pll_a_out0)) { | ||
122 | dev_err(data->dev, "Can't retrieve clk pll_a_out0\n"); | ||
123 | ret = PTR_ERR(data->clk_pll_a_out0); | ||
124 | goto err_put_pll_a; | ||
125 | } | ||
126 | |||
127 | data->clk_cdev1 = clk_get_sys(NULL, "cdev1"); | ||
128 | if (IS_ERR(data->clk_cdev1)) { | ||
129 | dev_err(data->dev, "Can't retrieve clk cdev1\n"); | ||
130 | ret = PTR_ERR(data->clk_cdev1); | ||
131 | goto err_put_pll_a_out0; | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | |||
136 | err_put_pll_a_out0: | ||
137 | clk_put(data->clk_pll_a_out0); | ||
138 | err_put_pll_a: | ||
139 | clk_put(data->clk_pll_a); | ||
140 | err: | ||
141 | return ret; | ||
142 | } | ||
143 | EXPORT_SYMBOL_GPL(tegra_asoc_utils_init); | ||
144 | |||
145 | void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data) | ||
146 | { | ||
147 | clk_put(data->clk_cdev1); | ||
148 | clk_put(data->clk_pll_a_out0); | ||
149 | clk_put(data->clk_pll_a); | ||
150 | } | ||
151 | EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini); | ||
152 | |||
153 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
154 | MODULE_DESCRIPTION("Tegra ASoC utility code"); | ||
155 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h new file mode 100644 index 000000000000..bbba7afdfc2c --- /dev/null +++ b/sound/soc/tegra/tegra_asoc_utils.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * tegra_asoc_utils.h - Definitions for Tegra DAS driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * 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., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef __TEGRA_ASOC_UTILS_H__ | ||
24 | #define __TEGRA_ASOC_UTILS_H_ | ||
25 | |||
26 | struct clk; | ||
27 | struct device; | ||
28 | |||
29 | struct tegra_asoc_utils_data { | ||
30 | struct device *dev; | ||
31 | struct clk *clk_pll_a; | ||
32 | struct clk *clk_pll_a_out0; | ||
33 | struct clk *clk_cdev1; | ||
34 | int set_baseclock; | ||
35 | int set_mclk; | ||
36 | }; | ||
37 | |||
38 | int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate, | ||
39 | int mclk, int *mclk_change); | ||
40 | int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data, | ||
41 | struct device *dev); | ||
42 | void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data); | ||
43 | |||
44 | #endif | ||
45 | |||
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c new file mode 100644 index 000000000000..9f24ef73f2cb --- /dev/null +++ b/sound/soc/tegra/tegra_das.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | * tegra_das.c - Tegra DAS driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * 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., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/debugfs.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/io.h> | ||
30 | #include <mach/iomap.h> | ||
31 | #include <sound/soc.h> | ||
32 | #include "tegra_das.h" | ||
33 | |||
34 | #define DRV_NAME "tegra-das" | ||
35 | |||
36 | static struct tegra_das *das; | ||
37 | |||
38 | static inline void tegra_das_write(u32 reg, u32 val) | ||
39 | { | ||
40 | __raw_writel(val, das->regs + reg); | ||
41 | } | ||
42 | |||
43 | static inline u32 tegra_das_read(u32 reg) | ||
44 | { | ||
45 | return __raw_readl(das->regs + reg); | ||
46 | } | ||
47 | |||
48 | int tegra_das_connect_dap_to_dac(int dap, int dac) | ||
49 | { | ||
50 | u32 addr; | ||
51 | u32 reg; | ||
52 | |||
53 | if (!das) | ||
54 | return -ENODEV; | ||
55 | |||
56 | addr = TEGRA_DAS_DAP_CTRL_SEL + | ||
57 | (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE); | ||
58 | reg = dac << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P; | ||
59 | |||
60 | tegra_das_write(addr, reg); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dac); | ||
65 | |||
66 | int tegra_das_connect_dap_to_dap(int dap, int otherdap, int master, | ||
67 | int sdata1rx, int sdata2rx) | ||
68 | { | ||
69 | u32 addr; | ||
70 | u32 reg; | ||
71 | |||
72 | if (!das) | ||
73 | return -ENODEV; | ||
74 | |||
75 | addr = TEGRA_DAS_DAP_CTRL_SEL + | ||
76 | (dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE); | ||
77 | reg = otherdap << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P | | ||
78 | !!sdata2rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P | | ||
79 | !!sdata1rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P | | ||
80 | !!master << TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P; | ||
81 | |||
82 | tegra_das_write(addr, reg); | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dap); | ||
87 | |||
88 | int tegra_das_connect_dac_to_dap(int dac, int dap) | ||
89 | { | ||
90 | u32 addr; | ||
91 | u32 reg; | ||
92 | |||
93 | if (!das) | ||
94 | return -ENODEV; | ||
95 | |||
96 | addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL + | ||
97 | (dac * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE); | ||
98 | reg = dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P | | ||
99 | dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P | | ||
100 | dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P; | ||
101 | |||
102 | tegra_das_write(addr, reg); | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | EXPORT_SYMBOL_GPL(tegra_das_connect_dac_to_dap); | ||
107 | |||
108 | #ifdef CONFIG_DEBUG_FS | ||
109 | static int tegra_das_show(struct seq_file *s, void *unused) | ||
110 | { | ||
111 | int i; | ||
112 | u32 addr; | ||
113 | u32 reg; | ||
114 | |||
115 | for (i = 0; i < TEGRA_DAS_DAP_CTRL_SEL_COUNT; i++) { | ||
116 | addr = TEGRA_DAS_DAP_CTRL_SEL + | ||
117 | (i * TEGRA_DAS_DAP_CTRL_SEL_STRIDE); | ||
118 | reg = tegra_das_read(addr); | ||
119 | seq_printf(s, "TEGRA_DAS_DAP_CTRL_SEL[%d] = %08x\n", i, reg); | ||
120 | } | ||
121 | |||
122 | for (i = 0; i < TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT; i++) { | ||
123 | addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL + | ||
124 | (i * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE); | ||
125 | reg = tegra_das_read(addr); | ||
126 | seq_printf(s, "TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL[%d] = %08x\n", | ||
127 | i, reg); | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static int tegra_das_debug_open(struct inode *inode, struct file *file) | ||
134 | { | ||
135 | return single_open(file, tegra_das_show, inode->i_private); | ||
136 | } | ||
137 | |||
138 | static const struct file_operations tegra_das_debug_fops = { | ||
139 | .open = tegra_das_debug_open, | ||
140 | .read = seq_read, | ||
141 | .llseek = seq_lseek, | ||
142 | .release = single_release, | ||
143 | }; | ||
144 | |||
145 | static void tegra_das_debug_add(struct tegra_das *das) | ||
146 | { | ||
147 | das->debug = debugfs_create_file(DRV_NAME, S_IRUGO, | ||
148 | snd_soc_debugfs_root, das, | ||
149 | &tegra_das_debug_fops); | ||
150 | } | ||
151 | |||
152 | static void tegra_das_debug_remove(struct tegra_das *das) | ||
153 | { | ||
154 | if (das->debug) | ||
155 | debugfs_remove(das->debug); | ||
156 | } | ||
157 | #else | ||
158 | static inline void tegra_das_debug_add(struct tegra_das *das) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | static inline void tegra_das_debug_remove(struct tegra_das *das) | ||
163 | { | ||
164 | } | ||
165 | #endif | ||
166 | |||
167 | static int __devinit tegra_das_probe(struct platform_device *pdev) | ||
168 | { | ||
169 | struct resource *res, *region; | ||
170 | int ret = 0; | ||
171 | |||
172 | if (das) | ||
173 | return -ENODEV; | ||
174 | |||
175 | das = kzalloc(sizeof(struct tegra_das), GFP_KERNEL); | ||
176 | if (!das) { | ||
177 | dev_err(&pdev->dev, "Can't allocate tegra_das\n"); | ||
178 | ret = -ENOMEM; | ||
179 | goto exit; | ||
180 | } | ||
181 | das->dev = &pdev->dev; | ||
182 | |||
183 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
184 | if (!res) { | ||
185 | dev_err(&pdev->dev, "No memory resource\n"); | ||
186 | ret = -ENODEV; | ||
187 | goto err_free; | ||
188 | } | ||
189 | |||
190 | region = request_mem_region(res->start, resource_size(res), | ||
191 | pdev->name); | ||
192 | if (!region) { | ||
193 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
194 | ret = -EBUSY; | ||
195 | goto err_free; | ||
196 | } | ||
197 | |||
198 | das->regs = ioremap(res->start, resource_size(res)); | ||
199 | if (!das->regs) { | ||
200 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
201 | ret = -ENOMEM; | ||
202 | goto err_release; | ||
203 | } | ||
204 | |||
205 | tegra_das_debug_add(das); | ||
206 | |||
207 | platform_set_drvdata(pdev, das); | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | err_release: | ||
212 | release_mem_region(res->start, resource_size(res)); | ||
213 | err_free: | ||
214 | kfree(das); | ||
215 | das = 0; | ||
216 | exit: | ||
217 | return ret; | ||
218 | } | ||
219 | |||
220 | static int __devexit tegra_das_remove(struct platform_device *pdev) | ||
221 | { | ||
222 | struct resource *res; | ||
223 | |||
224 | if (!das) | ||
225 | return -ENODEV; | ||
226 | |||
227 | platform_set_drvdata(pdev, NULL); | ||
228 | |||
229 | tegra_das_debug_remove(das); | ||
230 | |||
231 | iounmap(das->regs); | ||
232 | |||
233 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
234 | release_mem_region(res->start, resource_size(res)); | ||
235 | |||
236 | kfree(das); | ||
237 | das = 0; | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static struct platform_driver tegra_das_driver = { | ||
243 | .probe = tegra_das_probe, | ||
244 | .remove = __devexit_p(tegra_das_remove), | ||
245 | .driver = { | ||
246 | .name = DRV_NAME, | ||
247 | }, | ||
248 | }; | ||
249 | |||
250 | static int __init tegra_das_modinit(void) | ||
251 | { | ||
252 | return platform_driver_register(&tegra_das_driver); | ||
253 | } | ||
254 | module_init(tegra_das_modinit); | ||
255 | |||
256 | static void __exit tegra_das_modexit(void) | ||
257 | { | ||
258 | platform_driver_unregister(&tegra_das_driver); | ||
259 | } | ||
260 | module_exit(tegra_das_modexit); | ||
261 | |||
262 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
263 | MODULE_DESCRIPTION("Tegra DAS driver"); | ||
264 | MODULE_LICENSE("GPL"); | ||
265 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/tegra/tegra_das.h b/sound/soc/tegra/tegra_das.h new file mode 100644 index 000000000000..2c96c7b3c459 --- /dev/null +++ b/sound/soc/tegra/tegra_das.h | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * tegra_das.h - Definitions for Tegra DAS driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * 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., 51 Franklin St, Fifth Floor, Boston, MA | ||
19 | * 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef __TEGRA_DAS_H__ | ||
24 | #define __TEGRA_DAS_H__ | ||
25 | |||
26 | /* Register TEGRA_DAS_DAP_CTRL_SEL */ | ||
27 | #define TEGRA_DAS_DAP_CTRL_SEL 0x00 | ||
28 | #define TEGRA_DAS_DAP_CTRL_SEL_COUNT 5 | ||
29 | #define TEGRA_DAS_DAP_CTRL_SEL_STRIDE 4 | ||
30 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P 31 | ||
31 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_S 1 | ||
32 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P 30 | ||
33 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_S 1 | ||
34 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P 29 | ||
35 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_S 1 | ||
36 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P 0 | ||
37 | #define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_S 5 | ||
38 | |||
39 | /* Values for field TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL */ | ||
40 | #define TEGRA_DAS_DAP_SEL_DAC1 0 | ||
41 | #define TEGRA_DAS_DAP_SEL_DAC2 1 | ||
42 | #define TEGRA_DAS_DAP_SEL_DAC3 2 | ||
43 | #define TEGRA_DAS_DAP_SEL_DAP1 16 | ||
44 | #define TEGRA_DAS_DAP_SEL_DAP2 17 | ||
45 | #define TEGRA_DAS_DAP_SEL_DAP3 18 | ||
46 | #define TEGRA_DAS_DAP_SEL_DAP4 19 | ||
47 | #define TEGRA_DAS_DAP_SEL_DAP5 20 | ||
48 | |||
49 | /* Register TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL */ | ||
50 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL 0x40 | ||
51 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT 3 | ||
52 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE 4 | ||
53 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P 28 | ||
54 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_S 4 | ||
55 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P 24 | ||
56 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_S 4 | ||
57 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P 0 | ||
58 | #define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_S 4 | ||
59 | |||
60 | /* | ||
61 | * Values for: | ||
62 | * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL | ||
63 | * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL | ||
64 | * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL | ||
65 | */ | ||
66 | #define TEGRA_DAS_DAC_SEL_DAP1 0 | ||
67 | #define TEGRA_DAS_DAC_SEL_DAP2 1 | ||
68 | #define TEGRA_DAS_DAC_SEL_DAP3 2 | ||
69 | #define TEGRA_DAS_DAC_SEL_DAP4 3 | ||
70 | #define TEGRA_DAS_DAC_SEL_DAP5 4 | ||
71 | |||
72 | /* | ||
73 | * Names/IDs of the DACs/DAPs. | ||
74 | */ | ||
75 | |||
76 | #define TEGRA_DAS_DAP_ID_1 0 | ||
77 | #define TEGRA_DAS_DAP_ID_2 1 | ||
78 | #define TEGRA_DAS_DAP_ID_3 2 | ||
79 | #define TEGRA_DAS_DAP_ID_4 3 | ||
80 | #define TEGRA_DAS_DAP_ID_5 4 | ||
81 | |||
82 | #define TEGRA_DAS_DAC_ID_1 0 | ||
83 | #define TEGRA_DAS_DAC_ID_2 1 | ||
84 | #define TEGRA_DAS_DAC_ID_3 2 | ||
85 | |||
86 | struct tegra_das { | ||
87 | struct device *dev; | ||
88 | void __iomem *regs; | ||
89 | struct dentry *debug; | ||
90 | }; | ||
91 | |||
92 | /* | ||
93 | * Terminology: | ||
94 | * DAS: Digital audio switch (HW module controlled by this driver) | ||
95 | * DAP: Digital audio port (port/pins on Tegra device) | ||
96 | * DAC: Digital audio controller (e.g. I2S or AC97 controller elsewhere) | ||
97 | * | ||
98 | * The Tegra DAS is a mux/cross-bar which can connect each DAP to a specific | ||
99 | * DAC, or another DAP. When DAPs are connected, one must be the master and | ||
100 | * one the slave. Each DAC allows selection of a specific DAP for input, to | ||
101 | * cater for the case where N DAPs are connected to 1 DAC for broadcast | ||
102 | * output. | ||
103 | * | ||
104 | * This driver is dumb; no attempt is made to ensure that a valid routing | ||
105 | * configuration is programmed. | ||
106 | */ | ||
107 | |||
108 | /* | ||
109 | * Connect a DAP to to a DAC | ||
110 | * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_* | ||
111 | * dac_sel: DAC to connect to: TEGRA_DAS_DAP_SEL_DAC* | ||
112 | */ | ||
113 | extern int tegra_das_connect_dap_to_dac(int dap_id, int dac_sel); | ||
114 | |||
115 | /* | ||
116 | * Connect a DAP to to another DAP | ||
117 | * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_* | ||
118 | * other_dap_sel: DAP to connect to: TEGRA_DAS_DAP_SEL_DAP* | ||
119 | * master: Is this DAP the master (1) or slave (0) | ||
120 | * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0) | ||
121 | * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0) | ||
122 | */ | ||
123 | extern int tegra_das_connect_dap_to_dap(int dap_id, int other_dap_sel, | ||
124 | int master, int sdata1rx, | ||
125 | int sdata2rx); | ||
126 | |||
127 | /* | ||
128 | * Connect a DAC's input to a DAP | ||
129 | * (DAC outputs are selected by the DAP) | ||
130 | * dac_id: DAC ID to connect: TEGRA_DAS_DAC_ID_* | ||
131 | * dap_sel: DAP to receive input from: TEGRA_DAS_DAC_SEL_DAP* | ||
132 | */ | ||
133 | extern int tegra_das_connect_dac_to_dap(int dac_id, int dap_sel); | ||
134 | |||
135 | #endif | ||
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c new file mode 100644 index 000000000000..4f5e2c90b020 --- /dev/null +++ b/sound/soc/tegra/tegra_i2s.c | |||
@@ -0,0 +1,503 @@ | |||
1 | /* | ||
2 | * tegra_i2s.c - Tegra I2S driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * | ||
9 | * Copyright (c) 2009-2010, NVIDIA Corporation. | ||
10 | * Scott Peterson <speterson@nvidia.com> | ||
11 | * | ||
12 | * Copyright (C) 2010 Google, Inc. | ||
13 | * Iliyan Malchev <malchev@google.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | * General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
27 | * 02110-1301 USA | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #include <linux/clk.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/debugfs.h> | ||
34 | #include <linux/device.h> | ||
35 | #include <linux/platform_device.h> | ||
36 | #include <linux/seq_file.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/io.h> | ||
39 | #include <mach/iomap.h> | ||
40 | #include <sound/core.h> | ||
41 | #include <sound/pcm.h> | ||
42 | #include <sound/pcm_params.h> | ||
43 | #include <sound/soc.h> | ||
44 | |||
45 | #include "tegra_das.h" | ||
46 | #include "tegra_i2s.h" | ||
47 | |||
48 | #define DRV_NAME "tegra-i2s" | ||
49 | |||
50 | static inline void tegra_i2s_write(struct tegra_i2s *i2s, u32 reg, u32 val) | ||
51 | { | ||
52 | __raw_writel(val, i2s->regs + reg); | ||
53 | } | ||
54 | |||
55 | static inline u32 tegra_i2s_read(struct tegra_i2s *i2s, u32 reg) | ||
56 | { | ||
57 | return __raw_readl(i2s->regs + reg); | ||
58 | } | ||
59 | |||
60 | #ifdef CONFIG_DEBUG_FS | ||
61 | static int tegra_i2s_show(struct seq_file *s, void *unused) | ||
62 | { | ||
63 | #define REG(r) { r, #r } | ||
64 | static const struct { | ||
65 | int offset; | ||
66 | const char *name; | ||
67 | } regs[] = { | ||
68 | REG(TEGRA_I2S_CTRL), | ||
69 | REG(TEGRA_I2S_STATUS), | ||
70 | REG(TEGRA_I2S_TIMING), | ||
71 | REG(TEGRA_I2S_FIFO_SCR), | ||
72 | REG(TEGRA_I2S_PCM_CTRL), | ||
73 | REG(TEGRA_I2S_NW_CTRL), | ||
74 | REG(TEGRA_I2S_TDM_CTRL), | ||
75 | REG(TEGRA_I2S_TDM_TX_RX_CTRL), | ||
76 | }; | ||
77 | #undef REG | ||
78 | |||
79 | struct tegra_i2s *i2s = s->private; | ||
80 | int i; | ||
81 | |||
82 | for (i = 0; i < ARRAY_SIZE(regs); i++) { | ||
83 | u32 val = tegra_i2s_read(i2s, regs[i].offset); | ||
84 | seq_printf(s, "%s = %08x\n", regs[i].name, val); | ||
85 | } | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int tegra_i2s_debug_open(struct inode *inode, struct file *file) | ||
91 | { | ||
92 | return single_open(file, tegra_i2s_show, inode->i_private); | ||
93 | } | ||
94 | |||
95 | static const struct file_operations tegra_i2s_debug_fops = { | ||
96 | .open = tegra_i2s_debug_open, | ||
97 | .read = seq_read, | ||
98 | .llseek = seq_lseek, | ||
99 | .release = single_release, | ||
100 | }; | ||
101 | |||
102 | static void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id) | ||
103 | { | ||
104 | char name[] = DRV_NAME ".0"; | ||
105 | |||
106 | snprintf(name, sizeof(name), DRV_NAME".%1d", id); | ||
107 | i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root, | ||
108 | i2s, &tegra_i2s_debug_fops); | ||
109 | } | ||
110 | |||
111 | static void tegra_i2s_debug_remove(struct tegra_i2s *i2s) | ||
112 | { | ||
113 | if (i2s->debug) | ||
114 | debugfs_remove(i2s->debug); | ||
115 | } | ||
116 | #else | ||
117 | static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s) | ||
118 | { | ||
119 | } | ||
120 | |||
121 | static inline void tegra_i2s_debug_remove(struct tegra_i2s *i2s) | ||
122 | { | ||
123 | } | ||
124 | #endif | ||
125 | |||
126 | static int tegra_i2s_set_fmt(struct snd_soc_dai *dai, | ||
127 | unsigned int fmt) | ||
128 | { | ||
129 | struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
130 | |||
131 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
132 | case SND_SOC_DAIFMT_NB_NF: | ||
133 | break; | ||
134 | default: | ||
135 | return -EINVAL; | ||
136 | } | ||
137 | |||
138 | i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_MASTER_ENABLE; | ||
139 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
140 | case SND_SOC_DAIFMT_CBS_CFS: | ||
141 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_MASTER_ENABLE; | ||
142 | break; | ||
143 | case SND_SOC_DAIFMT_CBM_CFM: | ||
144 | break; | ||
145 | default: | ||
146 | return -EINVAL; | ||
147 | } | ||
148 | |||
149 | i2s->reg_ctrl &= ~(TEGRA_I2S_CTRL_BIT_FORMAT_MASK | | ||
150 | TEGRA_I2S_CTRL_LRCK_MASK); | ||
151 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
152 | case SND_SOC_DAIFMT_DSP_A: | ||
153 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP; | ||
154 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; | ||
155 | break; | ||
156 | case SND_SOC_DAIFMT_DSP_B: | ||
157 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP; | ||
158 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_R_LOW; | ||
159 | break; | ||
160 | case SND_SOC_DAIFMT_I2S: | ||
161 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_I2S; | ||
162 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; | ||
163 | break; | ||
164 | case SND_SOC_DAIFMT_RIGHT_J: | ||
165 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_RJM; | ||
166 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; | ||
167 | break; | ||
168 | case SND_SOC_DAIFMT_LEFT_J: | ||
169 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_LJM; | ||
170 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW; | ||
171 | break; | ||
172 | default: | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int tegra_i2s_hw_params(struct snd_pcm_substream *substream, | ||
180 | struct snd_pcm_hw_params *params, | ||
181 | struct snd_soc_dai *dai) | ||
182 | { | ||
183 | struct device *dev = substream->pcm->card->dev; | ||
184 | struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
185 | u32 reg; | ||
186 | int ret, sample_size, srate, i2sclock, bitcnt; | ||
187 | |||
188 | i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_BIT_SIZE_MASK; | ||
189 | switch (params_format(params)) { | ||
190 | case SNDRV_PCM_FORMAT_S16_LE: | ||
191 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_16; | ||
192 | sample_size = 16; | ||
193 | break; | ||
194 | case SNDRV_PCM_FORMAT_S24_LE: | ||
195 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_24; | ||
196 | sample_size = 24; | ||
197 | break; | ||
198 | case SNDRV_PCM_FORMAT_S32_LE: | ||
199 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_32; | ||
200 | sample_size = 32; | ||
201 | break; | ||
202 | default: | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | srate = params_rate(params); | ||
207 | |||
208 | /* Final "* 2" required by Tegra hardware */ | ||
209 | i2sclock = srate * params_channels(params) * sample_size * 2; | ||
210 | |||
211 | ret = clk_set_rate(i2s->clk_i2s, i2sclock); | ||
212 | if (ret) { | ||
213 | dev_err(dev, "Can't set I2S clock rate: %d\n", ret); | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | bitcnt = (i2sclock / (2 * srate)) - 1; | ||
218 | if (bitcnt < 0 || bitcnt > TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) | ||
219 | return -EINVAL; | ||
220 | reg = bitcnt << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; | ||
221 | |||
222 | if (i2sclock % (2 * srate)) | ||
223 | reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; | ||
224 | |||
225 | tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); | ||
226 | |||
227 | tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR, | ||
228 | TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | | ||
229 | TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static void tegra_i2s_start_playback(struct tegra_i2s *i2s) | ||
235 | { | ||
236 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO1_ENABLE; | ||
237 | tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); | ||
238 | } | ||
239 | |||
240 | static void tegra_i2s_stop_playback(struct tegra_i2s *i2s) | ||
241 | { | ||
242 | i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO1_ENABLE; | ||
243 | tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); | ||
244 | } | ||
245 | |||
246 | static void tegra_i2s_start_capture(struct tegra_i2s *i2s) | ||
247 | { | ||
248 | i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO2_ENABLE; | ||
249 | tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); | ||
250 | } | ||
251 | |||
252 | static void tegra_i2s_stop_capture(struct tegra_i2s *i2s) | ||
253 | { | ||
254 | i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO2_ENABLE; | ||
255 | tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); | ||
256 | } | ||
257 | |||
258 | static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | ||
259 | struct snd_soc_dai *dai) | ||
260 | { | ||
261 | struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai); | ||
262 | |||
263 | switch (cmd) { | ||
264 | case SNDRV_PCM_TRIGGER_START: | ||
265 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
266 | case SNDRV_PCM_TRIGGER_RESUME: | ||
267 | if (!i2s->clk_refs) | ||
268 | clk_enable(i2s->clk_i2s); | ||
269 | i2s->clk_refs++; | ||
270 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
271 | tegra_i2s_start_playback(i2s); | ||
272 | else | ||
273 | tegra_i2s_start_capture(i2s); | ||
274 | break; | ||
275 | case SNDRV_PCM_TRIGGER_STOP: | ||
276 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
277 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
278 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
279 | tegra_i2s_stop_playback(i2s); | ||
280 | else | ||
281 | tegra_i2s_stop_capture(i2s); | ||
282 | i2s->clk_refs--; | ||
283 | if (!i2s->clk_refs) | ||
284 | clk_disable(i2s->clk_i2s); | ||
285 | break; | ||
286 | default: | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int tegra_i2s_probe(struct snd_soc_dai *dai) | ||
294 | { | ||
295 | struct tegra_i2s * i2s = snd_soc_dai_get_drvdata(dai); | ||
296 | |||
297 | dai->capture_dma_data = &i2s->capture_dma_data; | ||
298 | dai->playback_dma_data = &i2s->playback_dma_data; | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static struct snd_soc_dai_ops tegra_i2s_dai_ops = { | ||
304 | .set_fmt = tegra_i2s_set_fmt, | ||
305 | .hw_params = tegra_i2s_hw_params, | ||
306 | .trigger = tegra_i2s_trigger, | ||
307 | }; | ||
308 | |||
309 | struct snd_soc_dai_driver tegra_i2s_dai[] = { | ||
310 | { | ||
311 | .name = DRV_NAME ".0", | ||
312 | .probe = tegra_i2s_probe, | ||
313 | .playback = { | ||
314 | .channels_min = 2, | ||
315 | .channels_max = 2, | ||
316 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
317 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
318 | }, | ||
319 | .capture = { | ||
320 | .channels_min = 2, | ||
321 | .channels_max = 2, | ||
322 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
323 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
324 | }, | ||
325 | .ops = &tegra_i2s_dai_ops, | ||
326 | .symmetric_rates = 1, | ||
327 | }, | ||
328 | { | ||
329 | .name = DRV_NAME ".1", | ||
330 | .probe = tegra_i2s_probe, | ||
331 | .playback = { | ||
332 | .channels_min = 2, | ||
333 | .channels_max = 2, | ||
334 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
335 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
336 | }, | ||
337 | .capture = { | ||
338 | .channels_min = 2, | ||
339 | .channels_max = 2, | ||
340 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
341 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
342 | }, | ||
343 | .ops = &tegra_i2s_dai_ops, | ||
344 | .symmetric_rates = 1, | ||
345 | }, | ||
346 | }; | ||
347 | |||
348 | static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev) | ||
349 | { | ||
350 | struct tegra_i2s * i2s; | ||
351 | char clk_name[12]; /* tegra-i2s.0 */ | ||
352 | struct resource *mem, *memregion, *dmareq; | ||
353 | int ret; | ||
354 | |||
355 | if ((pdev->id < 0) || | ||
356 | (pdev->id >= ARRAY_SIZE(tegra_i2s_dai))) { | ||
357 | dev_err(&pdev->dev, "ID %d out of range\n", pdev->id); | ||
358 | return -EINVAL; | ||
359 | } | ||
360 | |||
361 | /* | ||
362 | * FIXME: Until a codec driver exists for the tegra DAS, hard-code a | ||
363 | * 1:1 mapping between audio controllers and audio ports. | ||
364 | */ | ||
365 | ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1 + pdev->id, | ||
366 | TEGRA_DAS_DAP_SEL_DAC1 + pdev->id); | ||
367 | if (ret) { | ||
368 | dev_err(&pdev->dev, "Can't set up DAP connection\n"); | ||
369 | return ret; | ||
370 | } | ||
371 | ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1 + pdev->id, | ||
372 | TEGRA_DAS_DAC_SEL_DAP1 + pdev->id); | ||
373 | if (ret) { | ||
374 | dev_err(&pdev->dev, "Can't set up DAC connection\n"); | ||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL); | ||
379 | if (!i2s) { | ||
380 | dev_err(&pdev->dev, "Can't allocate tegra_i2s\n"); | ||
381 | ret = -ENOMEM; | ||
382 | goto exit; | ||
383 | } | ||
384 | dev_set_drvdata(&pdev->dev, i2s); | ||
385 | |||
386 | snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id); | ||
387 | i2s->clk_i2s = clk_get_sys(clk_name, NULL); | ||
388 | if (IS_ERR(i2s->clk_i2s)) { | ||
389 | dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); | ||
390 | ret = PTR_ERR(i2s->clk_i2s); | ||
391 | goto err_free; | ||
392 | } | ||
393 | |||
394 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
395 | if (!mem) { | ||
396 | dev_err(&pdev->dev, "No memory resource\n"); | ||
397 | ret = -ENODEV; | ||
398 | goto err_clk_put; | ||
399 | } | ||
400 | |||
401 | dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
402 | if (!dmareq) { | ||
403 | dev_err(&pdev->dev, "No DMA resource\n"); | ||
404 | ret = -ENODEV; | ||
405 | goto err_clk_put; | ||
406 | } | ||
407 | |||
408 | memregion = request_mem_region(mem->start, resource_size(mem), | ||
409 | DRV_NAME); | ||
410 | if (!memregion) { | ||
411 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
412 | ret = -EBUSY; | ||
413 | goto err_clk_put; | ||
414 | } | ||
415 | |||
416 | i2s->regs = ioremap(mem->start, resource_size(mem)); | ||
417 | if (!i2s->regs) { | ||
418 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
419 | ret = -ENOMEM; | ||
420 | goto err_release; | ||
421 | } | ||
422 | |||
423 | i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2; | ||
424 | i2s->capture_dma_data.wrap = 4; | ||
425 | i2s->capture_dma_data.width = 32; | ||
426 | i2s->capture_dma_data.req_sel = dmareq->start; | ||
427 | |||
428 | i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1; | ||
429 | i2s->playback_dma_data.wrap = 4; | ||
430 | i2s->playback_dma_data.width = 32; | ||
431 | i2s->playback_dma_data.req_sel = dmareq->start; | ||
432 | |||
433 | i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED; | ||
434 | |||
435 | ret = snd_soc_register_dai(&pdev->dev, &tegra_i2s_dai[pdev->id]); | ||
436 | if (ret) { | ||
437 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
438 | ret = -ENOMEM; | ||
439 | goto err_unmap; | ||
440 | } | ||
441 | |||
442 | tegra_i2s_debug_add(i2s, pdev->id); | ||
443 | |||
444 | return 0; | ||
445 | |||
446 | err_unmap: | ||
447 | iounmap(i2s->regs); | ||
448 | err_release: | ||
449 | release_mem_region(mem->start, resource_size(mem)); | ||
450 | err_clk_put: | ||
451 | clk_put(i2s->clk_i2s); | ||
452 | err_free: | ||
453 | kfree(i2s); | ||
454 | exit: | ||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev) | ||
459 | { | ||
460 | struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev); | ||
461 | struct resource *res; | ||
462 | |||
463 | snd_soc_unregister_dai(&pdev->dev); | ||
464 | |||
465 | tegra_i2s_debug_remove(i2s); | ||
466 | |||
467 | iounmap(i2s->regs); | ||
468 | |||
469 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
470 | release_mem_region(res->start, resource_size(res)); | ||
471 | |||
472 | clk_put(i2s->clk_i2s); | ||
473 | |||
474 | kfree(i2s); | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | static struct platform_driver tegra_i2s_driver = { | ||
480 | .driver = { | ||
481 | .name = DRV_NAME, | ||
482 | .owner = THIS_MODULE, | ||
483 | }, | ||
484 | .probe = tegra_i2s_platform_probe, | ||
485 | .remove = __devexit_p(tegra_i2s_platform_remove), | ||
486 | }; | ||
487 | |||
488 | static int __init snd_tegra_i2s_init(void) | ||
489 | { | ||
490 | return platform_driver_register(&tegra_i2s_driver); | ||
491 | } | ||
492 | module_init(snd_tegra_i2s_init); | ||
493 | |||
494 | static void __exit snd_tegra_i2s_exit(void) | ||
495 | { | ||
496 | platform_driver_unregister(&tegra_i2s_driver); | ||
497 | } | ||
498 | module_exit(snd_tegra_i2s_exit); | ||
499 | |||
500 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
501 | MODULE_DESCRIPTION("Tegra I2S ASoC driver"); | ||
502 | MODULE_LICENSE("GPL"); | ||
503 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h new file mode 100644 index 000000000000..2b38a096f46c --- /dev/null +++ b/sound/soc/tegra/tegra_i2s.h | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * tegra_i2s.h - Definitions for Tegra I2S driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * | ||
9 | * Copyright (c) 2009-2010, NVIDIA Corporation. | ||
10 | * Scott Peterson <speterson@nvidia.com> | ||
11 | * | ||
12 | * Copyright (C) 2010 Google, Inc. | ||
13 | * Iliyan Malchev <malchev@google.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | * General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
27 | * 02110-1301 USA | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #ifndef __TEGRA_I2S_H__ | ||
32 | #define __TEGRA_I2S_H__ | ||
33 | |||
34 | #include "tegra_pcm.h" | ||
35 | |||
36 | /* Register offsets from TEGRA_I2S1_BASE and TEGRA_I2S2_BASE */ | ||
37 | |||
38 | #define TEGRA_I2S_CTRL 0x00 | ||
39 | #define TEGRA_I2S_STATUS 0x04 | ||
40 | #define TEGRA_I2S_TIMING 0x08 | ||
41 | #define TEGRA_I2S_FIFO_SCR 0x0c | ||
42 | #define TEGRA_I2S_PCM_CTRL 0x10 | ||
43 | #define TEGRA_I2S_NW_CTRL 0x14 | ||
44 | #define TEGRA_I2S_TDM_CTRL 0x20 | ||
45 | #define TEGRA_I2S_TDM_TX_RX_CTRL 0x24 | ||
46 | #define TEGRA_I2S_FIFO1 0x40 | ||
47 | #define TEGRA_I2S_FIFO2 0x80 | ||
48 | |||
49 | /* Fields in TEGRA_I2S_CTRL */ | ||
50 | |||
51 | #define TEGRA_I2S_CTRL_FIFO2_TX_ENABLE (1 << 30) | ||
52 | #define TEGRA_I2S_CTRL_FIFO1_ENABLE (1 << 29) | ||
53 | #define TEGRA_I2S_CTRL_FIFO2_ENABLE (1 << 28) | ||
54 | #define TEGRA_I2S_CTRL_FIFO1_RX_ENABLE (1 << 27) | ||
55 | #define TEGRA_I2S_CTRL_FIFO_LPBK_ENABLE (1 << 26) | ||
56 | #define TEGRA_I2S_CTRL_MASTER_ENABLE (1 << 25) | ||
57 | |||
58 | #define TEGRA_I2S_LRCK_LEFT_LOW 0 | ||
59 | #define TEGRA_I2S_LRCK_RIGHT_LOW 1 | ||
60 | |||
61 | #define TEGRA_I2S_CTRL_LRCK_SHIFT 24 | ||
62 | #define TEGRA_I2S_CTRL_LRCK_MASK (1 << TEGRA_I2S_CTRL_LRCK_SHIFT) | ||
63 | #define TEGRA_I2S_CTRL_LRCK_L_LOW (TEGRA_I2S_LRCK_LEFT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT) | ||
64 | #define TEGRA_I2S_CTRL_LRCK_R_LOW (TEGRA_I2S_LRCK_RIGHT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT) | ||
65 | |||
66 | #define TEGRA_I2S_BIT_FORMAT_I2S 0 | ||
67 | #define TEGRA_I2S_BIT_FORMAT_RJM 1 | ||
68 | #define TEGRA_I2S_BIT_FORMAT_LJM 2 | ||
69 | #define TEGRA_I2S_BIT_FORMAT_DSP 3 | ||
70 | |||
71 | #define TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT 10 | ||
72 | #define TEGRA_I2S_CTRL_BIT_FORMAT_MASK (3 << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT) | ||
73 | #define TEGRA_I2S_CTRL_BIT_FORMAT_I2S (TEGRA_I2S_BIT_FORMAT_I2S << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT) | ||
74 | #define TEGRA_I2S_CTRL_BIT_FORMAT_RJM (TEGRA_I2S_BIT_FORMAT_RJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT) | ||
75 | #define TEGRA_I2S_CTRL_BIT_FORMAT_LJM (TEGRA_I2S_BIT_FORMAT_LJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT) | ||
76 | #define TEGRA_I2S_CTRL_BIT_FORMAT_DSP (TEGRA_I2S_BIT_FORMAT_DSP << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT) | ||
77 | |||
78 | #define TEGRA_I2S_BIT_SIZE_16 0 | ||
79 | #define TEGRA_I2S_BIT_SIZE_20 1 | ||
80 | #define TEGRA_I2S_BIT_SIZE_24 2 | ||
81 | #define TEGRA_I2S_BIT_SIZE_32 3 | ||
82 | |||
83 | #define TEGRA_I2S_CTRL_BIT_SIZE_SHIFT 8 | ||
84 | #define TEGRA_I2S_CTRL_BIT_SIZE_MASK (3 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT) | ||
85 | #define TEGRA_I2S_CTRL_BIT_SIZE_16 (TEGRA_I2S_BIT_SIZE_16 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT) | ||
86 | #define TEGRA_I2S_CTRL_BIT_SIZE_20 (TEGRA_I2S_BIT_SIZE_20 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT) | ||
87 | #define TEGRA_I2S_CTRL_BIT_SIZE_24 (TEGRA_I2S_BIT_SIZE_24 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT) | ||
88 | #define TEGRA_I2S_CTRL_BIT_SIZE_32 (TEGRA_I2S_BIT_SIZE_32 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT) | ||
89 | |||
90 | #define TEGRA_I2S_FIFO_16_LSB 0 | ||
91 | #define TEGRA_I2S_FIFO_20_LSB 1 | ||
92 | #define TEGRA_I2S_FIFO_24_LSB 2 | ||
93 | #define TEGRA_I2S_FIFO_32 3 | ||
94 | #define TEGRA_I2S_FIFO_PACKED 7 | ||
95 | |||
96 | #define TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT 4 | ||
97 | #define TEGRA_I2S_CTRL_FIFO_FORMAT_MASK (7 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT) | ||
98 | #define TEGRA_I2S_CTRL_FIFO_FORMAT_16_LSB (TEGRA_I2S_FIFO_16_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT) | ||
99 | #define TEGRA_I2S_CTRL_FIFO_FORMAT_20_LSB (TEGRA_I2S_FIFO_20_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT) | ||
100 | #define TEGRA_I2S_CTRL_FIFO_FORMAT_24_LSB (TEGRA_I2S_FIFO_24_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT) | ||
101 | #define TEGRA_I2S_CTRL_FIFO_FORMAT_32 (TEGRA_I2S_FIFO_32 << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT) | ||
102 | #define TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED (TEGRA_I2S_FIFO_PACKED << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT) | ||
103 | |||
104 | #define TEGRA_I2S_CTRL_IE_FIFO1_ERR (1 << 3) | ||
105 | #define TEGRA_I2S_CTRL_IE_FIFO2_ERR (1 << 2) | ||
106 | #define TEGRA_I2S_CTRL_QE_FIFO1 (1 << 1) | ||
107 | #define TEGRA_I2S_CTRL_QE_FIFO2 (1 << 0) | ||
108 | |||
109 | /* Fields in TEGRA_I2S_STATUS */ | ||
110 | |||
111 | #define TEGRA_I2S_STATUS_FIFO1_RDY (1 << 31) | ||
112 | #define TEGRA_I2S_STATUS_FIFO2_RDY (1 << 30) | ||
113 | #define TEGRA_I2S_STATUS_FIFO1_BSY (1 << 29) | ||
114 | #define TEGRA_I2S_STATUS_FIFO2_BSY (1 << 28) | ||
115 | #define TEGRA_I2S_STATUS_FIFO1_ERR (1 << 3) | ||
116 | #define TEGRA_I2S_STATUS_FIFO2_ERR (1 << 2) | ||
117 | #define TEGRA_I2S_STATUS_QS_FIFO1 (1 << 1) | ||
118 | #define TEGRA_I2S_STATUS_QS_FIFO2 (1 << 0) | ||
119 | |||
120 | /* Fields in TEGRA_I2S_TIMING */ | ||
121 | |||
122 | #define TEGRA_I2S_TIMING_NON_SYM_ENABLE (1 << 12) | ||
123 | #define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT 0 | ||
124 | #define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US 0x7fff | ||
125 | #define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK (TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT) | ||
126 | |||
127 | /* Fields in TEGRA_I2S_FIFO_SCR */ | ||
128 | |||
129 | #define TEGRA_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT 24 | ||
130 | #define TEGRA_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT 16 | ||
131 | #define TEGRA_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK 0x3f | ||
132 | |||
133 | #define TEGRA_I2S_FIFO_SCR_FIFO2_CLR (1 << 12) | ||
134 | #define TEGRA_I2S_FIFO_SCR_FIFO1_CLR (1 << 8) | ||
135 | |||
136 | #define TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT 0 | ||
137 | #define TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS 1 | ||
138 | #define TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS 2 | ||
139 | #define TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS 3 | ||
140 | |||
141 | #define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT 4 | ||
142 | #define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT) | ||
143 | #define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT) | ||
144 | #define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT) | ||
145 | #define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT) | ||
146 | #define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT) | ||
147 | |||
148 | #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT 0 | ||
149 | #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK (3 << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT) | ||
150 | #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT (TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT) | ||
151 | #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT) | ||
152 | #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT) | ||
153 | #define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT) | ||
154 | |||
155 | struct tegra_i2s { | ||
156 | struct clk *clk_i2s; | ||
157 | int clk_refs; | ||
158 | struct tegra_pcm_dma_params capture_dma_data; | ||
159 | struct tegra_pcm_dma_params playback_dma_data; | ||
160 | void __iomem *regs; | ||
161 | struct dentry *debug; | ||
162 | u32 reg_ctrl; | ||
163 | }; | ||
164 | |||
165 | #endif | ||
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c new file mode 100644 index 000000000000..3c271f953582 --- /dev/null +++ b/sound/soc/tegra/tegra_pcm.c | |||
@@ -0,0 +1,404 @@ | |||
1 | /* | ||
2 | * tegra_pcm.c - Tegra PCM driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * | ||
9 | * Copyright (c) 2009-2010, NVIDIA Corporation. | ||
10 | * Scott Peterson <speterson@nvidia.com> | ||
11 | * Vijay Mali <vmali@nvidia.com> | ||
12 | * | ||
13 | * Copyright (C) 2010 Google, Inc. | ||
14 | * Iliyan Malchev <malchev@google.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License | ||
18 | * version 2 as published by the Free Software Foundation. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, but | ||
21 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
23 | * General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
28 | * 02110-1301 USA | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/module.h> | ||
33 | #include <linux/dma-mapping.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <sound/core.h> | ||
36 | #include <sound/pcm.h> | ||
37 | #include <sound/pcm_params.h> | ||
38 | #include <sound/soc.h> | ||
39 | |||
40 | #include "tegra_pcm.h" | ||
41 | |||
42 | #define DRV_NAME "tegra-pcm-audio" | ||
43 | |||
44 | static const struct snd_pcm_hardware tegra_pcm_hardware = { | ||
45 | .info = SNDRV_PCM_INFO_MMAP | | ||
46 | SNDRV_PCM_INFO_MMAP_VALID | | ||
47 | SNDRV_PCM_INFO_PAUSE | | ||
48 | SNDRV_PCM_INFO_RESUME | | ||
49 | SNDRV_PCM_INFO_INTERLEAVED, | ||
50 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
51 | .channels_min = 2, | ||
52 | .channels_max = 2, | ||
53 | .period_bytes_min = 1024, | ||
54 | .period_bytes_max = PAGE_SIZE, | ||
55 | .periods_min = 2, | ||
56 | .periods_max = 8, | ||
57 | .buffer_bytes_max = PAGE_SIZE * 8, | ||
58 | .fifo_size = 4, | ||
59 | }; | ||
60 | |||
61 | static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd) | ||
62 | { | ||
63 | struct snd_pcm_substream *substream = prtd->substream; | ||
64 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
65 | struct tegra_dma_req *dma_req; | ||
66 | unsigned long addr; | ||
67 | |||
68 | dma_req = &prtd->dma_req[prtd->dma_req_idx]; | ||
69 | prtd->dma_req_idx = 1 - prtd->dma_req_idx; | ||
70 | |||
71 | addr = buf->addr + prtd->dma_pos; | ||
72 | prtd->dma_pos += dma_req->size; | ||
73 | if (prtd->dma_pos >= prtd->dma_pos_end) | ||
74 | prtd->dma_pos = 0; | ||
75 | |||
76 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
77 | dma_req->source_addr = addr; | ||
78 | else | ||
79 | dma_req->dest_addr = addr; | ||
80 | |||
81 | tegra_dma_enqueue_req(prtd->dma_chan, dma_req); | ||
82 | } | ||
83 | |||
84 | static void dma_complete_callback(struct tegra_dma_req *req) | ||
85 | { | ||
86 | struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev; | ||
87 | struct snd_pcm_substream *substream = prtd->substream; | ||
88 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
89 | |||
90 | spin_lock(&prtd->lock); | ||
91 | |||
92 | if (!prtd->running) { | ||
93 | spin_unlock(&prtd->lock); | ||
94 | return; | ||
95 | } | ||
96 | |||
97 | if (++prtd->period_index >= runtime->periods) | ||
98 | prtd->period_index = 0; | ||
99 | |||
100 | tegra_pcm_queue_dma(prtd); | ||
101 | |||
102 | spin_unlock(&prtd->lock); | ||
103 | |||
104 | snd_pcm_period_elapsed(substream); | ||
105 | } | ||
106 | |||
107 | static void setup_dma_tx_request(struct tegra_dma_req *req, | ||
108 | struct tegra_pcm_dma_params * dmap) | ||
109 | { | ||
110 | req->complete = dma_complete_callback; | ||
111 | req->to_memory = false; | ||
112 | req->dest_addr = dmap->addr; | ||
113 | req->dest_wrap = dmap->wrap; | ||
114 | req->source_bus_width = 32; | ||
115 | req->source_wrap = 0; | ||
116 | req->dest_bus_width = dmap->width; | ||
117 | req->req_sel = dmap->req_sel; | ||
118 | } | ||
119 | |||
120 | static void setup_dma_rx_request(struct tegra_dma_req *req, | ||
121 | struct tegra_pcm_dma_params * dmap) | ||
122 | { | ||
123 | req->complete = dma_complete_callback; | ||
124 | req->to_memory = true; | ||
125 | req->source_addr = dmap->addr; | ||
126 | req->dest_wrap = 0; | ||
127 | req->source_bus_width = dmap->width; | ||
128 | req->source_wrap = dmap->wrap; | ||
129 | req->dest_bus_width = 32; | ||
130 | req->req_sel = dmap->req_sel; | ||
131 | } | ||
132 | |||
133 | static int tegra_pcm_open(struct snd_pcm_substream *substream) | ||
134 | { | ||
135 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
136 | struct tegra_runtime_data *prtd; | ||
137 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
138 | struct tegra_pcm_dma_params * dmap; | ||
139 | int ret = 0; | ||
140 | |||
141 | prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL); | ||
142 | if (prtd == NULL) | ||
143 | return -ENOMEM; | ||
144 | |||
145 | runtime->private_data = prtd; | ||
146 | prtd->substream = substream; | ||
147 | |||
148 | spin_lock_init(&prtd->lock); | ||
149 | |||
150 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
151 | dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
152 | setup_dma_tx_request(&prtd->dma_req[0], dmap); | ||
153 | setup_dma_tx_request(&prtd->dma_req[1], dmap); | ||
154 | } else { | ||
155 | dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | ||
156 | setup_dma_rx_request(&prtd->dma_req[0], dmap); | ||
157 | setup_dma_rx_request(&prtd->dma_req[1], dmap); | ||
158 | } | ||
159 | |||
160 | prtd->dma_req[0].dev = prtd; | ||
161 | prtd->dma_req[1].dev = prtd; | ||
162 | |||
163 | prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); | ||
164 | if (prtd->dma_chan == NULL) { | ||
165 | ret = -ENOMEM; | ||
166 | goto err; | ||
167 | } | ||
168 | |||
169 | /* Set HW params now that initialization is complete */ | ||
170 | snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware); | ||
171 | |||
172 | /* Ensure that buffer size is a multiple of period size */ | ||
173 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
174 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
175 | if (ret < 0) | ||
176 | goto err; | ||
177 | |||
178 | return 0; | ||
179 | |||
180 | err: | ||
181 | if (prtd->dma_chan) { | ||
182 | tegra_dma_free_channel(prtd->dma_chan); | ||
183 | } | ||
184 | |||
185 | kfree(prtd); | ||
186 | |||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | static int tegra_pcm_close(struct snd_pcm_substream *substream) | ||
191 | { | ||
192 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
193 | struct tegra_runtime_data *prtd = runtime->private_data; | ||
194 | |||
195 | tegra_dma_free_channel(prtd->dma_chan); | ||
196 | |||
197 | kfree(prtd); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int tegra_pcm_hw_params(struct snd_pcm_substream *substream, | ||
203 | struct snd_pcm_hw_params *params) | ||
204 | { | ||
205 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
206 | struct tegra_runtime_data *prtd = runtime->private_data; | ||
207 | |||
208 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
209 | |||
210 | prtd->dma_req[0].size = params_period_bytes(params); | ||
211 | prtd->dma_req[1].size = prtd->dma_req[0].size; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int tegra_pcm_hw_free(struct snd_pcm_substream *substream) | ||
217 | { | ||
218 | snd_pcm_set_runtime_buffer(substream, NULL); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
224 | { | ||
225 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
226 | struct tegra_runtime_data *prtd = runtime->private_data; | ||
227 | unsigned long flags; | ||
228 | |||
229 | switch (cmd) { | ||
230 | case SNDRV_PCM_TRIGGER_START: | ||
231 | prtd->dma_pos = 0; | ||
232 | prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size); | ||
233 | prtd->period_index = 0; | ||
234 | prtd->dma_req_idx = 0; | ||
235 | /* Fall-through */ | ||
236 | case SNDRV_PCM_TRIGGER_RESUME: | ||
237 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
238 | spin_lock_irqsave(&prtd->lock, flags); | ||
239 | prtd->running = 1; | ||
240 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
241 | tegra_pcm_queue_dma(prtd); | ||
242 | tegra_pcm_queue_dma(prtd); | ||
243 | break; | ||
244 | case SNDRV_PCM_TRIGGER_STOP: | ||
245 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
246 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
247 | spin_lock_irqsave(&prtd->lock, flags); | ||
248 | prtd->running = 0; | ||
249 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
250 | tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]); | ||
251 | tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]); | ||
252 | break; | ||
253 | default: | ||
254 | return -EINVAL; | ||
255 | } | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream) | ||
261 | { | ||
262 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
263 | struct tegra_runtime_data *prtd = runtime->private_data; | ||
264 | |||
265 | return prtd->period_index * runtime->period_size; | ||
266 | } | ||
267 | |||
268 | |||
269 | static int tegra_pcm_mmap(struct snd_pcm_substream *substream, | ||
270 | struct vm_area_struct *vma) | ||
271 | { | ||
272 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
273 | |||
274 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
275 | runtime->dma_area, | ||
276 | runtime->dma_addr, | ||
277 | runtime->dma_bytes); | ||
278 | } | ||
279 | |||
280 | static struct snd_pcm_ops tegra_pcm_ops = { | ||
281 | .open = tegra_pcm_open, | ||
282 | .close = tegra_pcm_close, | ||
283 | .ioctl = snd_pcm_lib_ioctl, | ||
284 | .hw_params = tegra_pcm_hw_params, | ||
285 | .hw_free = tegra_pcm_hw_free, | ||
286 | .trigger = tegra_pcm_trigger, | ||
287 | .pointer = tegra_pcm_pointer, | ||
288 | .mmap = tegra_pcm_mmap, | ||
289 | }; | ||
290 | |||
291 | static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
292 | { | ||
293 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
294 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
295 | size_t size = tegra_pcm_hardware.buffer_bytes_max; | ||
296 | |||
297 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
298 | &buf->addr, GFP_KERNEL); | ||
299 | if (!buf->area) | ||
300 | return -ENOMEM; | ||
301 | |||
302 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
303 | buf->dev.dev = pcm->card->dev; | ||
304 | buf->private_data = NULL; | ||
305 | buf->bytes = size; | ||
306 | |||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
311 | { | ||
312 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
313 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
314 | |||
315 | if (!buf->area) | ||
316 | return; | ||
317 | |||
318 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
319 | buf->area, buf->addr); | ||
320 | buf->area = NULL; | ||
321 | } | ||
322 | |||
323 | static u64 tegra_dma_mask = DMA_BIT_MASK(32); | ||
324 | |||
325 | static int tegra_pcm_new(struct snd_card *card, | ||
326 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
327 | { | ||
328 | int ret = 0; | ||
329 | |||
330 | if (!card->dev->dma_mask) | ||
331 | card->dev->dma_mask = &tegra_dma_mask; | ||
332 | if (!card->dev->coherent_dma_mask) | ||
333 | card->dev->coherent_dma_mask = 0xffffffff; | ||
334 | |||
335 | if (dai->driver->playback.channels_min) { | ||
336 | ret = tegra_pcm_preallocate_dma_buffer(pcm, | ||
337 | SNDRV_PCM_STREAM_PLAYBACK); | ||
338 | if (ret) | ||
339 | goto err; | ||
340 | } | ||
341 | |||
342 | if (dai->driver->capture.channels_min) { | ||
343 | ret = tegra_pcm_preallocate_dma_buffer(pcm, | ||
344 | SNDRV_PCM_STREAM_CAPTURE); | ||
345 | if (ret) | ||
346 | goto err_free_play; | ||
347 | } | ||
348 | |||
349 | return 0; | ||
350 | |||
351 | err_free_play: | ||
352 | tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); | ||
353 | err: | ||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | static void tegra_pcm_free(struct snd_pcm *pcm) | ||
358 | { | ||
359 | tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE); | ||
360 | tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK); | ||
361 | } | ||
362 | |||
363 | struct snd_soc_platform_driver tegra_pcm_platform = { | ||
364 | .ops = &tegra_pcm_ops, | ||
365 | .pcm_new = tegra_pcm_new, | ||
366 | .pcm_free = tegra_pcm_free, | ||
367 | }; | ||
368 | |||
369 | static int __devinit tegra_pcm_platform_probe(struct platform_device *pdev) | ||
370 | { | ||
371 | return snd_soc_register_platform(&pdev->dev, &tegra_pcm_platform); | ||
372 | } | ||
373 | |||
374 | static int __devexit tegra_pcm_platform_remove(struct platform_device *pdev) | ||
375 | { | ||
376 | snd_soc_unregister_platform(&pdev->dev); | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static struct platform_driver tegra_pcm_driver = { | ||
381 | .driver = { | ||
382 | .name = DRV_NAME, | ||
383 | .owner = THIS_MODULE, | ||
384 | }, | ||
385 | .probe = tegra_pcm_platform_probe, | ||
386 | .remove = __devexit_p(tegra_pcm_platform_remove), | ||
387 | }; | ||
388 | |||
389 | static int __init snd_tegra_pcm_init(void) | ||
390 | { | ||
391 | return platform_driver_register(&tegra_pcm_driver); | ||
392 | } | ||
393 | module_init(snd_tegra_pcm_init); | ||
394 | |||
395 | static void __exit snd_tegra_pcm_exit(void) | ||
396 | { | ||
397 | platform_driver_unregister(&tegra_pcm_driver); | ||
398 | } | ||
399 | module_exit(snd_tegra_pcm_exit); | ||
400 | |||
401 | MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>"); | ||
402 | MODULE_DESCRIPTION("Tegra PCM ASoC driver"); | ||
403 | MODULE_LICENSE("GPL"); | ||
404 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h new file mode 100644 index 000000000000..dbb90339fe0d --- /dev/null +++ b/sound/soc/tegra/tegra_pcm.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * tegra_pcm.h - Definitions for Tegra PCM driver | ||
3 | * | ||
4 | * Author: Stephen Warren <swarren@nvidia.com> | ||
5 | * Copyright (C) 2010 - NVIDIA, Inc. | ||
6 | * | ||
7 | * Based on code copyright/by: | ||
8 | * | ||
9 | * Copyright (c) 2009-2010, NVIDIA Corporation. | ||
10 | * Scott Peterson <speterson@nvidia.com> | ||
11 | * | ||
12 | * Copyright (C) 2010 Google, Inc. | ||
13 | * Iliyan Malchev <malchev@google.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, but | ||
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
22 | * General Public License for more details. | ||
23 | * | ||
24 | * You should have received a copy of the GNU General Public License | ||
25 | * along with this program; if not, write to the Free Software | ||
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
27 | * 02110-1301 USA | ||
28 | * | ||
29 | */ | ||
30 | |||
31 | #ifndef __TEGRA_PCM_H__ | ||
32 | #define __TEGRA_PCM_H__ | ||
33 | |||
34 | #include <mach/dma.h> | ||
35 | |||
36 | struct tegra_pcm_dma_params { | ||
37 | unsigned long addr; | ||
38 | unsigned long wrap; | ||
39 | unsigned long width; | ||
40 | unsigned long req_sel; | ||
41 | }; | ||
42 | |||
43 | struct tegra_runtime_data { | ||
44 | struct snd_pcm_substream *substream; | ||
45 | spinlock_t lock; | ||
46 | int running; | ||
47 | int dma_pos; | ||
48 | int dma_pos_end; | ||
49 | int period_index; | ||
50 | int dma_req_idx; | ||
51 | struct tegra_dma_req dma_req[2]; | ||
52 | struct tegra_dma_channel *dma_chan; | ||
53 | }; | ||
54 | |||
55 | #endif | ||
diff --git a/sound/sound_core.c b/sound/sound_core.c index 5580aced8730..6ce277860fd7 100644 --- a/sound/sound_core.c +++ b/sound/sound_core.c | |||
@@ -384,6 +384,9 @@ int register_sound_special_device(const struct file_operations *fops, int unit, | |||
384 | case 4: | 384 | case 4: |
385 | name = "audio"; | 385 | name = "audio"; |
386 | break; | 386 | break; |
387 | case 5: | ||
388 | name = "dspW"; | ||
389 | break; | ||
387 | case 8: | 390 | case 8: |
388 | name = "sequencer2"; | 391 | name = "sequencer2"; |
389 | if (unit >= SOUND_STEP) | 392 | if (unit >= SOUND_STEP) |
diff --git a/sound/usb/6fire/Makefile b/sound/usb/6fire/Makefile new file mode 100644 index 000000000000..dfce6ec53513 --- /dev/null +++ b/sound/usb/6fire/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | snd-usb-6fire-objs += chip.o comm.o midi.o control.o firmware.o pcm.o | ||
2 | obj-$(CONFIG_SND_USB_6FIRE) += snd-usb-6fire.o | ||
3 | |||
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c new file mode 100644 index 000000000000..c7dca7b0b9fe --- /dev/null +++ b/sound/usb/6fire/chip.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Main routines and module definitions. | ||
5 | * | ||
6 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
7 | * Created: Jan 01, 2011 | ||
8 | * Version: 0.3.0 | ||
9 | * Copyright: (C) Torsten Schenk | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include "chip.h" | ||
18 | #include "firmware.h" | ||
19 | #include "pcm.h" | ||
20 | #include "control.h" | ||
21 | #include "comm.h" | ||
22 | #include "midi.h" | ||
23 | |||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/gfp.h> | ||
29 | #include <sound/initval.h> | ||
30 | |||
31 | MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>"); | ||
32 | MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0"); | ||
33 | MODULE_LICENSE("GPL v2"); | ||
34 | MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}"); | ||
35 | |||
36 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ | ||
37 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */ | ||
38 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */ | ||
39 | static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
40 | static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | ||
41 | |||
42 | module_param_array(index, int, NULL, 0444); | ||
43 | MODULE_PARM_DESC(index, "Index value for the 6fire sound device"); | ||
44 | module_param_array(id, charp, NULL, 0444); | ||
45 | MODULE_PARM_DESC(id, "ID string for the 6fire sound device."); | ||
46 | module_param_array(enable, bool, NULL, 0444); | ||
47 | MODULE_PARM_DESC(enable, "Enable the 6fire sound device."); | ||
48 | |||
49 | static DEFINE_MUTEX(register_mutex); | ||
50 | |||
51 | static void usb6fire_chip_abort(struct sfire_chip *chip) | ||
52 | { | ||
53 | if (chip) { | ||
54 | if (chip->pcm) | ||
55 | usb6fire_pcm_abort(chip); | ||
56 | if (chip->midi) | ||
57 | usb6fire_midi_abort(chip); | ||
58 | if (chip->comm) | ||
59 | usb6fire_comm_abort(chip); | ||
60 | if (chip->control) | ||
61 | usb6fire_control_abort(chip); | ||
62 | if (chip->card) { | ||
63 | snd_card_disconnect(chip->card); | ||
64 | snd_card_free_when_closed(chip->card); | ||
65 | chip->card = NULL; | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | static void usb6fire_chip_destroy(struct sfire_chip *chip) | ||
71 | { | ||
72 | if (chip) { | ||
73 | if (chip->pcm) | ||
74 | usb6fire_pcm_destroy(chip); | ||
75 | if (chip->midi) | ||
76 | usb6fire_midi_destroy(chip); | ||
77 | if (chip->comm) | ||
78 | usb6fire_comm_destroy(chip); | ||
79 | if (chip->control) | ||
80 | usb6fire_control_destroy(chip); | ||
81 | if (chip->card) | ||
82 | snd_card_free(chip->card); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | static int __devinit usb6fire_chip_probe(struct usb_interface *intf, | ||
87 | const struct usb_device_id *usb_id) | ||
88 | { | ||
89 | int ret; | ||
90 | int i; | ||
91 | struct sfire_chip *chip = NULL; | ||
92 | struct usb_device *device = interface_to_usbdev(intf); | ||
93 | int regidx = -1; /* index in module parameter array */ | ||
94 | struct snd_card *card = NULL; | ||
95 | |||
96 | /* look if we already serve this card and return if so */ | ||
97 | mutex_lock(®ister_mutex); | ||
98 | for (i = 0; i < SNDRV_CARDS; i++) { | ||
99 | if (devices[i] == device) { | ||
100 | if (chips[i]) | ||
101 | chips[i]->intf_count++; | ||
102 | usb_set_intfdata(intf, chips[i]); | ||
103 | mutex_unlock(®ister_mutex); | ||
104 | return 0; | ||
105 | } else if (regidx < 0) | ||
106 | regidx = i; | ||
107 | } | ||
108 | if (regidx < 0) { | ||
109 | mutex_unlock(®ister_mutex); | ||
110 | snd_printk(KERN_ERR PREFIX "too many cards registered.\n"); | ||
111 | return -ENODEV; | ||
112 | } | ||
113 | devices[regidx] = device; | ||
114 | mutex_unlock(®ister_mutex); | ||
115 | |||
116 | /* check, if firmware is present on device, upload it if not */ | ||
117 | ret = usb6fire_fw_init(intf); | ||
118 | if (ret < 0) | ||
119 | return ret; | ||
120 | else if (ret == FW_NOT_READY) /* firmware update performed */ | ||
121 | return 0; | ||
122 | |||
123 | /* if we are here, card can be registered in alsa. */ | ||
124 | if (usb_set_interface(device, 0, 0) != 0) { | ||
125 | snd_printk(KERN_ERR PREFIX "can't set first interface.\n"); | ||
126 | return -EIO; | ||
127 | } | ||
128 | ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE, | ||
129 | sizeof(struct sfire_chip), &card); | ||
130 | if (ret < 0) { | ||
131 | snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n"); | ||
132 | return ret; | ||
133 | } | ||
134 | strcpy(card->driver, "6FireUSB"); | ||
135 | strcpy(card->shortname, "TerraTec DMX6FireUSB"); | ||
136 | sprintf(card->longname, "%s at %d:%d", card->shortname, | ||
137 | device->bus->busnum, device->devnum); | ||
138 | snd_card_set_dev(card, &intf->dev); | ||
139 | |||
140 | chip = card->private_data; | ||
141 | chips[regidx] = chip; | ||
142 | chip->dev = device; | ||
143 | chip->regidx = regidx; | ||
144 | chip->intf_count = 1; | ||
145 | chip->card = card; | ||
146 | |||
147 | ret = usb6fire_comm_init(chip); | ||
148 | if (ret < 0) { | ||
149 | usb6fire_chip_destroy(chip); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | ret = usb6fire_midi_init(chip); | ||
154 | if (ret < 0) { | ||
155 | usb6fire_chip_destroy(chip); | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | ret = usb6fire_pcm_init(chip); | ||
160 | if (ret < 0) { | ||
161 | usb6fire_chip_destroy(chip); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | ret = usb6fire_control_init(chip); | ||
166 | if (ret < 0) { | ||
167 | usb6fire_chip_destroy(chip); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | ret = snd_card_register(card); | ||
172 | if (ret < 0) { | ||
173 | snd_printk(KERN_ERR PREFIX "cannot register card."); | ||
174 | usb6fire_chip_destroy(chip); | ||
175 | return ret; | ||
176 | } | ||
177 | usb_set_intfdata(intf, chip); | ||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | static void usb6fire_chip_disconnect(struct usb_interface *intf) | ||
182 | { | ||
183 | struct sfire_chip *chip; | ||
184 | struct snd_card *card; | ||
185 | |||
186 | chip = usb_get_intfdata(intf); | ||
187 | if (chip) { /* if !chip, fw upload has been performed */ | ||
188 | card = chip->card; | ||
189 | chip->intf_count--; | ||
190 | if (!chip->intf_count) { | ||
191 | mutex_lock(®ister_mutex); | ||
192 | devices[chip->regidx] = NULL; | ||
193 | chips[chip->regidx] = NULL; | ||
194 | mutex_unlock(®ister_mutex); | ||
195 | |||
196 | chip->shutdown = true; | ||
197 | usb6fire_chip_abort(chip); | ||
198 | usb6fire_chip_destroy(chip); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | |||
203 | static struct usb_device_id device_table[] = { | ||
204 | { | ||
205 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
206 | .idVendor = 0x0ccd, | ||
207 | .idProduct = 0x0080 | ||
208 | }, | ||
209 | {} | ||
210 | }; | ||
211 | |||
212 | MODULE_DEVICE_TABLE(usb, device_table); | ||
213 | |||
214 | static struct usb_driver driver = { | ||
215 | .name = "snd-usb-6fire", | ||
216 | .probe = usb6fire_chip_probe, | ||
217 | .disconnect = usb6fire_chip_disconnect, | ||
218 | .id_table = device_table, | ||
219 | }; | ||
220 | |||
221 | static int __init usb6fire_chip_init(void) | ||
222 | { | ||
223 | return usb_register(&driver); | ||
224 | } | ||
225 | |||
226 | static void __exit usb6fire_chip_cleanup(void) | ||
227 | { | ||
228 | usb_deregister(&driver); | ||
229 | } | ||
230 | |||
231 | module_init(usb6fire_chip_init); | ||
232 | module_exit(usb6fire_chip_cleanup); | ||
diff --git a/sound/usb/6fire/chip.h b/sound/usb/6fire/chip.h new file mode 100644 index 000000000000..d11e5cb520f0 --- /dev/null +++ b/sound/usb/6fire/chip.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
5 | * Created: Jan 01, 2011 | ||
6 | * Version: 0.3.0 | ||
7 | * Copyright: (C) Torsten Schenk | ||
8 | * | ||
9 | * This program 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 | #ifndef USB6FIRE_CHIP_H | ||
15 | #define USB6FIRE_CHIP_H | ||
16 | |||
17 | #include "common.h" | ||
18 | |||
19 | struct sfire_chip { | ||
20 | struct usb_device *dev; | ||
21 | struct snd_card *card; | ||
22 | int intf_count; /* number of registered interfaces */ | ||
23 | int regidx; /* index in module parameter arrays */ | ||
24 | bool shutdown; | ||
25 | |||
26 | struct midi_runtime *midi; | ||
27 | struct pcm_runtime *pcm; | ||
28 | struct control_runtime *control; | ||
29 | struct comm_runtime *comm; | ||
30 | }; | ||
31 | #endif /* USB6FIRE_CHIP_H */ | ||
32 | |||
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c new file mode 100644 index 000000000000..c994daa57af2 --- /dev/null +++ b/sound/usb/6fire/comm.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Device communications | ||
5 | * | ||
6 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
7 | * Created: Jan 01, 2011 | ||
8 | * Version: 0.3.0 | ||
9 | * Copyright: (C) Torsten Schenk | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include "comm.h" | ||
18 | #include "chip.h" | ||
19 | #include "midi.h" | ||
20 | |||
21 | enum { | ||
22 | COMM_EP = 1, | ||
23 | COMM_FPGA_EP = 2 | ||
24 | }; | ||
25 | |||
26 | static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb, | ||
27 | u8 *buffer, void *context, void(*handler)(struct urb *urb)) | ||
28 | { | ||
29 | usb_init_urb(urb); | ||
30 | urb->transfer_buffer = buffer; | ||
31 | urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP); | ||
32 | urb->complete = handler; | ||
33 | urb->context = context; | ||
34 | urb->interval = 1; | ||
35 | urb->dev = rt->chip->dev; | ||
36 | } | ||
37 | |||
38 | static void usb6fire_comm_receiver_handler(struct urb *urb) | ||
39 | { | ||
40 | struct comm_runtime *rt = urb->context; | ||
41 | struct midi_runtime *midi_rt = rt->chip->midi; | ||
42 | |||
43 | if (!urb->status) { | ||
44 | if (rt->receiver_buffer[0] == 0x10) /* midi in event */ | ||
45 | if (midi_rt) | ||
46 | midi_rt->in_received(midi_rt, | ||
47 | rt->receiver_buffer + 2, | ||
48 | rt->receiver_buffer[1]); | ||
49 | } | ||
50 | |||
51 | if (!rt->chip->shutdown) { | ||
52 | urb->status = 0; | ||
53 | urb->actual_length = 0; | ||
54 | if (usb_submit_urb(urb, GFP_ATOMIC) < 0) | ||
55 | snd_printk(KERN_WARNING PREFIX | ||
56 | "comm data receiver aborted.\n"); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request, | ||
61 | u8 reg, u8 vl, u8 vh) | ||
62 | { | ||
63 | buffer[0] = 0x01; | ||
64 | buffer[2] = request; | ||
65 | buffer[3] = id; | ||
66 | switch (request) { | ||
67 | case 0x02: | ||
68 | buffer[1] = 0x05; /* length (starting at buffer[2]) */ | ||
69 | buffer[4] = reg; | ||
70 | buffer[5] = vl; | ||
71 | buffer[6] = vh; | ||
72 | break; | ||
73 | |||
74 | case 0x12: | ||
75 | buffer[1] = 0x0b; /* length (starting at buffer[2]) */ | ||
76 | buffer[4] = 0x00; | ||
77 | buffer[5] = 0x18; | ||
78 | buffer[6] = 0x05; | ||
79 | buffer[7] = 0x00; | ||
80 | buffer[8] = 0x01; | ||
81 | buffer[9] = 0x00; | ||
82 | buffer[10] = 0x9e; | ||
83 | buffer[11] = reg; | ||
84 | buffer[12] = vl; | ||
85 | break; | ||
86 | |||
87 | case 0x20: | ||
88 | case 0x21: | ||
89 | case 0x22: | ||
90 | buffer[1] = 0x04; | ||
91 | buffer[4] = reg; | ||
92 | buffer[5] = vl; | ||
93 | break; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev) | ||
98 | { | ||
99 | int ret; | ||
100 | int actual_len; | ||
101 | |||
102 | ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP), | ||
103 | buffer, buffer[1] + 2, &actual_len, HZ); | ||
104 | if (ret < 0) | ||
105 | return ret; | ||
106 | else if (actual_len != buffer[1] + 2) | ||
107 | return -EIO; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request, | ||
112 | u8 reg, u8 value) | ||
113 | { | ||
114 | u8 buffer[13]; /* 13: maximum length of message */ | ||
115 | |||
116 | usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00); | ||
117 | return usb6fire_comm_send_buffer(buffer, rt->chip->dev); | ||
118 | } | ||
119 | |||
120 | static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request, | ||
121 | u8 reg, u8 vl, u8 vh) | ||
122 | { | ||
123 | u8 buffer[13]; /* 13: maximum length of message */ | ||
124 | |||
125 | usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh); | ||
126 | return usb6fire_comm_send_buffer(buffer, rt->chip->dev); | ||
127 | } | ||
128 | |||
129 | int __devinit usb6fire_comm_init(struct sfire_chip *chip) | ||
130 | { | ||
131 | struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime), | ||
132 | GFP_KERNEL); | ||
133 | struct urb *urb = &rt->receiver; | ||
134 | int ret; | ||
135 | |||
136 | if (!rt) | ||
137 | return -ENOMEM; | ||
138 | |||
139 | rt->serial = 1; | ||
140 | rt->chip = chip; | ||
141 | usb_init_urb(urb); | ||
142 | rt->init_urb = usb6fire_comm_init_urb; | ||
143 | rt->write8 = usb6fire_comm_write8; | ||
144 | rt->write16 = usb6fire_comm_write16; | ||
145 | |||
146 | /* submit an urb that receives communication data from device */ | ||
147 | urb->transfer_buffer = rt->receiver_buffer; | ||
148 | urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE; | ||
149 | urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP); | ||
150 | urb->dev = chip->dev; | ||
151 | urb->complete = usb6fire_comm_receiver_handler; | ||
152 | urb->context = rt; | ||
153 | urb->interval = 1; | ||
154 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
155 | if (ret < 0) { | ||
156 | kfree(rt); | ||
157 | snd_printk(KERN_ERR PREFIX "cannot create comm data receiver."); | ||
158 | return ret; | ||
159 | } | ||
160 | chip->comm = rt; | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | void usb6fire_comm_abort(struct sfire_chip *chip) | ||
165 | { | ||
166 | struct comm_runtime *rt = chip->comm; | ||
167 | |||
168 | if (rt) | ||
169 | usb_poison_urb(&rt->receiver); | ||
170 | } | ||
171 | |||
172 | void usb6fire_comm_destroy(struct sfire_chip *chip) | ||
173 | { | ||
174 | kfree(chip->comm); | ||
175 | chip->comm = NULL; | ||
176 | } | ||
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h new file mode 100644 index 000000000000..edc5dc84b888 --- /dev/null +++ b/sound/usb/6fire/comm.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
5 | * Created: Jan 01, 2011 | ||
6 | * Version: 0.3.0 | ||
7 | * Copyright: (C) Torsten Schenk | ||
8 | * | ||
9 | * This program 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 | #ifndef USB6FIRE_COMM_H | ||
15 | #define USB6FIRE_COMM_H | ||
16 | |||
17 | #include "common.h" | ||
18 | |||
19 | enum /* settings for comm */ | ||
20 | { | ||
21 | COMM_RECEIVER_BUFSIZE = 64, | ||
22 | }; | ||
23 | |||
24 | struct comm_runtime { | ||
25 | struct sfire_chip *chip; | ||
26 | |||
27 | struct urb receiver; | ||
28 | u8 receiver_buffer[COMM_RECEIVER_BUFSIZE]; | ||
29 | |||
30 | u8 serial; /* urb serial */ | ||
31 | |||
32 | void (*init_urb)(struct comm_runtime *rt, struct urb *urb, u8 *buffer, | ||
33 | void *context, void(*handler)(struct urb *urb)); | ||
34 | /* writes control data to the device */ | ||
35 | int (*write8)(struct comm_runtime *rt, u8 request, u8 reg, u8 value); | ||
36 | int (*write16)(struct comm_runtime *rt, u8 request, u8 reg, | ||
37 | u8 vh, u8 vl); | ||
38 | }; | ||
39 | |||
40 | int __devinit usb6fire_comm_init(struct sfire_chip *chip); | ||
41 | void usb6fire_comm_abort(struct sfire_chip *chip); | ||
42 | void usb6fire_comm_destroy(struct sfire_chip *chip); | ||
43 | #endif /* USB6FIRE_COMM_H */ | ||
44 | |||
diff --git a/sound/usb/6fire/common.h b/sound/usb/6fire/common.h new file mode 100644 index 000000000000..7dbeb4a37831 --- /dev/null +++ b/sound/usb/6fire/common.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
5 | * Created: Jan 01, 2011 | ||
6 | * Version: 0.3.0 | ||
7 | * Copyright: (C) Torsten Schenk | ||
8 | * | ||
9 | * This program 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 | |||
15 | #ifndef USB6FIRE_COMMON_H | ||
16 | #define USB6FIRE_COMMON_H | ||
17 | |||
18 | #include <linux/slab.h> | ||
19 | #include <linux/usb.h> | ||
20 | #include <sound/core.h> | ||
21 | |||
22 | #define PREFIX "6fire: " | ||
23 | |||
24 | struct sfire_chip; | ||
25 | struct midi_runtime; | ||
26 | struct pcm_runtime; | ||
27 | struct control_runtime; | ||
28 | struct comm_runtime; | ||
29 | #endif /* USB6FIRE_COMMON_H */ | ||
30 | |||
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c new file mode 100644 index 000000000000..248463511186 --- /dev/null +++ b/sound/usb/6fire/control.c | |||
@@ -0,0 +1,275 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Mixer control | ||
5 | * | ||
6 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
7 | * Created: Jan 01, 2011 | ||
8 | * Version: 0.3.0 | ||
9 | * Copyright: (C) Torsten Schenk | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/interrupt.h> | ||
18 | #include <sound/control.h> | ||
19 | |||
20 | #include "control.h" | ||
21 | #include "comm.h" | ||
22 | #include "chip.h" | ||
23 | |||
24 | static char *opt_coax_texts[2] = { "Optical", "Coax" }; | ||
25 | static char *line_phono_texts[2] = { "Line", "Phono" }; | ||
26 | |||
27 | /* | ||
28 | * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$ | ||
29 | * this is done because the linear values cause rapid degredation | ||
30 | * of volume in the uppermost region. | ||
31 | */ | ||
32 | static const u8 log_volume_table[128] = { | ||
33 | 0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34, | ||
34 | 0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43, | ||
35 | 0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, | ||
36 | 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, | ||
37 | 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, | ||
38 | 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, | ||
39 | 0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68, | ||
40 | 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, | ||
41 | 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71, | ||
42 | 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, | ||
43 | 0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, | ||
44 | 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, | ||
45 | 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f }; | ||
46 | |||
47 | /* | ||
48 | * data that needs to be sent to device. sets up card internal stuff. | ||
49 | * values dumped from windows driver and filtered by trial'n'error. | ||
50 | */ | ||
51 | static const struct { | ||
52 | u8 type; | ||
53 | u8 reg; | ||
54 | u8 value; | ||
55 | } | ||
56 | init_data[] = { | ||
57 | { 0x22, 0x00, 0x00 }, { 0x20, 0x00, 0x08 }, { 0x22, 0x01, 0x01 }, | ||
58 | { 0x20, 0x01, 0x08 }, { 0x22, 0x02, 0x00 }, { 0x20, 0x02, 0x08 }, | ||
59 | { 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 }, | ||
60 | { 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 }, | ||
61 | { 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 }, | ||
62 | { 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 }, | ||
63 | { 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 }, | ||
64 | { 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 }, | ||
65 | { 0 } /* TERMINATING ENTRY */ | ||
66 | }; | ||
67 | |||
68 | static void usb6fire_control_master_vol_update(struct control_runtime *rt) | ||
69 | { | ||
70 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
71 | if (comm_rt) { | ||
72 | /* set volume */ | ||
73 | comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f - | ||
74 | log_volume_table[rt->master_vol]); | ||
75 | /* unmute */ | ||
76 | comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static void usb6fire_control_line_phono_update(struct control_runtime *rt) | ||
81 | { | ||
82 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
83 | if (comm_rt) { | ||
84 | comm_rt->write8(comm_rt, 0x22, 0x02, rt->line_phono_switch); | ||
85 | comm_rt->write8(comm_rt, 0x21, 0x02, rt->line_phono_switch); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | static void usb6fire_control_opt_coax_update(struct control_runtime *rt) | ||
90 | { | ||
91 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
92 | if (comm_rt) { | ||
93 | comm_rt->write8(comm_rt, 0x22, 0x00, rt->opt_coax_switch); | ||
94 | comm_rt->write8(comm_rt, 0x21, 0x00, rt->opt_coax_switch); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol, | ||
99 | struct snd_ctl_elem_info *uinfo) | ||
100 | { | ||
101 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
102 | uinfo->count = 1; | ||
103 | uinfo->value.integer.min = 0; | ||
104 | uinfo->value.integer.max = 127; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol, | ||
109 | struct snd_ctl_elem_value *ucontrol) | ||
110 | { | ||
111 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
112 | int changed = 0; | ||
113 | if (rt->master_vol != ucontrol->value.integer.value[0]) { | ||
114 | rt->master_vol = ucontrol->value.integer.value[0]; | ||
115 | usb6fire_control_master_vol_update(rt); | ||
116 | changed = 1; | ||
117 | } | ||
118 | return changed; | ||
119 | } | ||
120 | |||
121 | static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol, | ||
122 | struct snd_ctl_elem_value *ucontrol) | ||
123 | { | ||
124 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
125 | ucontrol->value.integer.value[0] = rt->master_vol; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol, | ||
130 | struct snd_ctl_elem_info *uinfo) | ||
131 | { | ||
132 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
133 | uinfo->count = 1; | ||
134 | uinfo->value.enumerated.items = 2; | ||
135 | if (uinfo->value.enumerated.item > 1) | ||
136 | uinfo->value.enumerated.item = 1; | ||
137 | strcpy(uinfo->value.enumerated.name, | ||
138 | line_phono_texts[uinfo->value.enumerated.item]); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol, | ||
143 | struct snd_ctl_elem_value *ucontrol) | ||
144 | { | ||
145 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
146 | int changed = 0; | ||
147 | if (rt->line_phono_switch != ucontrol->value.integer.value[0]) { | ||
148 | rt->line_phono_switch = ucontrol->value.integer.value[0]; | ||
149 | usb6fire_control_line_phono_update(rt); | ||
150 | changed = 1; | ||
151 | } | ||
152 | return changed; | ||
153 | } | ||
154 | |||
155 | static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol, | ||
156 | struct snd_ctl_elem_value *ucontrol) | ||
157 | { | ||
158 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
159 | ucontrol->value.integer.value[0] = rt->line_phono_switch; | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol, | ||
164 | struct snd_ctl_elem_info *uinfo) | ||
165 | { | ||
166 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
167 | uinfo->count = 1; | ||
168 | uinfo->value.enumerated.items = 2; | ||
169 | if (uinfo->value.enumerated.item > 1) | ||
170 | uinfo->value.enumerated.item = 1; | ||
171 | strcpy(uinfo->value.enumerated.name, | ||
172 | opt_coax_texts[uinfo->value.enumerated.item]); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol, | ||
177 | struct snd_ctl_elem_value *ucontrol) | ||
178 | { | ||
179 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
180 | int changed = 0; | ||
181 | |||
182 | if (rt->opt_coax_switch != ucontrol->value.enumerated.item[0]) { | ||
183 | rt->opt_coax_switch = ucontrol->value.enumerated.item[0]; | ||
184 | usb6fire_control_opt_coax_update(rt); | ||
185 | changed = 1; | ||
186 | } | ||
187 | return changed; | ||
188 | } | ||
189 | |||
190 | static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol, | ||
191 | struct snd_ctl_elem_value *ucontrol) | ||
192 | { | ||
193 | struct control_runtime *rt = snd_kcontrol_chip(kcontrol); | ||
194 | ucontrol->value.enumerated.item[0] = rt->opt_coax_switch; | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | static struct __devinitdata snd_kcontrol_new elements[] = { | ||
199 | { | ||
200 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
201 | .name = "Master Playback Volume", | ||
202 | .index = 0, | ||
203 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
204 | .info = usb6fire_control_master_vol_info, | ||
205 | .get = usb6fire_control_master_vol_get, | ||
206 | .put = usb6fire_control_master_vol_put | ||
207 | }, | ||
208 | { | ||
209 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
210 | .name = "Line/Phono Capture Route", | ||
211 | .index = 0, | ||
212 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
213 | .info = usb6fire_control_line_phono_info, | ||
214 | .get = usb6fire_control_line_phono_get, | ||
215 | .put = usb6fire_control_line_phono_put | ||
216 | }, | ||
217 | { | ||
218 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
219 | .name = "Opt/Coax Capture Route", | ||
220 | .index = 0, | ||
221 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
222 | .info = usb6fire_control_opt_coax_info, | ||
223 | .get = usb6fire_control_opt_coax_get, | ||
224 | .put = usb6fire_control_opt_coax_put | ||
225 | }, | ||
226 | {} | ||
227 | }; | ||
228 | |||
229 | int __devinit usb6fire_control_init(struct sfire_chip *chip) | ||
230 | { | ||
231 | int i; | ||
232 | int ret; | ||
233 | struct control_runtime *rt = kzalloc(sizeof(struct control_runtime), | ||
234 | GFP_KERNEL); | ||
235 | struct comm_runtime *comm_rt = chip->comm; | ||
236 | |||
237 | if (!rt) | ||
238 | return -ENOMEM; | ||
239 | |||
240 | rt->chip = chip; | ||
241 | |||
242 | i = 0; | ||
243 | while (init_data[i].type) { | ||
244 | comm_rt->write8(comm_rt, init_data[i].type, init_data[i].reg, | ||
245 | init_data[i].value); | ||
246 | i++; | ||
247 | } | ||
248 | |||
249 | usb6fire_control_opt_coax_update(rt); | ||
250 | usb6fire_control_line_phono_update(rt); | ||
251 | usb6fire_control_master_vol_update(rt); | ||
252 | |||
253 | i = 0; | ||
254 | while (elements[i].name) { | ||
255 | ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt)); | ||
256 | if (ret < 0) { | ||
257 | kfree(rt); | ||
258 | snd_printk(KERN_ERR PREFIX "cannot add control.\n"); | ||
259 | return ret; | ||
260 | } | ||
261 | i++; | ||
262 | } | ||
263 | |||
264 | chip->control = rt; | ||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | void usb6fire_control_abort(struct sfire_chip *chip) | ||
269 | {} | ||
270 | |||
271 | void usb6fire_control_destroy(struct sfire_chip *chip) | ||
272 | { | ||
273 | kfree(chip->control); | ||
274 | chip->control = NULL; | ||
275 | } | ||
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h new file mode 100644 index 000000000000..b534c777ab02 --- /dev/null +++ b/sound/usb/6fire/control.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
5 | * Created: Jan 01, 2011 | ||
6 | * Version: 0.3.0 | ||
7 | * Copyright: (C) Torsten Schenk | ||
8 | * | ||
9 | * This program 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 | |||
15 | #ifndef USB6FIRE_CONTROL_H | ||
16 | #define USB6FIRE_CONTROL_H | ||
17 | |||
18 | #include "common.h" | ||
19 | |||
20 | enum { | ||
21 | CONTROL_MAX_ELEMENTS = 32 | ||
22 | }; | ||
23 | |||
24 | struct control_runtime { | ||
25 | struct sfire_chip *chip; | ||
26 | |||
27 | struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS]; | ||
28 | bool opt_coax_switch; | ||
29 | bool line_phono_switch; | ||
30 | u8 master_vol; | ||
31 | }; | ||
32 | |||
33 | int __devinit usb6fire_control_init(struct sfire_chip *chip); | ||
34 | void usb6fire_control_abort(struct sfire_chip *chip); | ||
35 | void usb6fire_control_destroy(struct sfire_chip *chip); | ||
36 | #endif /* USB6FIRE_CONTROL_H */ | ||
37 | |||
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c new file mode 100644 index 000000000000..9081a54a9c6c --- /dev/null +++ b/sound/usb/6fire/firmware.c | |||
@@ -0,0 +1,426 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Firmware loader | ||
5 | * | ||
6 | * Currently not working for all devices. To be able to use the device | ||
7 | * in linux, it is also possible to let the windows driver upload the firmware. | ||
8 | * For that, start the computer in windows and reboot. | ||
9 | * As long as the device is connected to the power supply, no firmware reload | ||
10 | * needs to be performed. | ||
11 | * | ||
12 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
13 | * Created: Jan 01, 2011 | ||
14 | * Version: 0.3.0 | ||
15 | * Copyright: (C) Torsten Schenk | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License as published by | ||
19 | * the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | */ | ||
22 | |||
23 | #include <linux/firmware.h> | ||
24 | |||
25 | #include "firmware.h" | ||
26 | #include "chip.h" | ||
27 | |||
28 | MODULE_FIRMWARE("6fire/dmx6firel2.ihx"); | ||
29 | MODULE_FIRMWARE("6fire/dmx6fireap.ihx"); | ||
30 | MODULE_FIRMWARE("6fire/dmx6firecf.bin"); | ||
31 | |||
32 | enum { | ||
33 | FPGA_BUFSIZE = 512, FPGA_EP = 2 | ||
34 | }; | ||
35 | |||
36 | static const u8 BIT_REVERSE_TABLE[256] = { | ||
37 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, | ||
38 | 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, | ||
39 | 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, | ||
40 | 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, | ||
41 | 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, | ||
42 | 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, | ||
43 | 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, | ||
44 | 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, | ||
45 | 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, | ||
46 | 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, | ||
47 | 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, | ||
48 | 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, | ||
49 | 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, | ||
50 | 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, | ||
51 | 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, | ||
52 | 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, | ||
53 | 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, | ||
54 | 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, | ||
55 | 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, | ||
56 | 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, | ||
57 | 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, | ||
58 | 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, | ||
59 | 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, | ||
60 | 0xbf, 0x7f, 0xff }; | ||
61 | |||
62 | /* | ||
63 | * wMaxPacketSize of pcm endpoints. | ||
64 | * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c | ||
65 | * fpp: frames per isopacket | ||
66 | * | ||
67 | * CAUTION: keep sizeof <= buffer[] in usb6fire_fw_init | ||
68 | */ | ||
69 | static const u8 ep_w_max_packet_size[] = { | ||
70 | 0xe4, 0x00, 0xe4, 0x00, /* alt 1: 228 EP2 and EP6 (7 fpp) */ | ||
71 | 0xa4, 0x01, 0xa4, 0x01, /* alt 2: 420 EP2 and EP6 (13 fpp)*/ | ||
72 | 0x94, 0x01, 0x5c, 0x02 /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */ | ||
73 | }; | ||
74 | |||
75 | struct ihex_record { | ||
76 | u16 address; | ||
77 | u8 len; | ||
78 | u8 data[256]; | ||
79 | char error; /* true if an error occured parsing this record */ | ||
80 | |||
81 | u8 max_len; /* maximum record length in whole ihex */ | ||
82 | |||
83 | /* private */ | ||
84 | const char *txt_data; | ||
85 | unsigned int txt_length; | ||
86 | unsigned int txt_offset; /* current position in txt_data */ | ||
87 | }; | ||
88 | |||
89 | static u8 usb6fire_fw_ihex_nibble(const u8 n) | ||
90 | { | ||
91 | if (n >= '0' && n <= '9') | ||
92 | return n - '0'; | ||
93 | else if (n >= 'A' && n <= 'F') | ||
94 | return n - ('A' - 10); | ||
95 | else if (n >= 'a' && n <= 'f') | ||
96 | return n - ('a' - 10); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc) | ||
101 | { | ||
102 | u8 val = (usb6fire_fw_ihex_nibble(data[0]) << 4) | | ||
103 | usb6fire_fw_ihex_nibble(data[1]); | ||
104 | *crc += val; | ||
105 | return val; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * returns true if record is available, false otherwise. | ||
110 | * iff an error occured, false will be returned and record->error will be true. | ||
111 | */ | ||
112 | static bool usb6fire_fw_ihex_next_record(struct ihex_record *record) | ||
113 | { | ||
114 | u8 crc = 0; | ||
115 | u8 type; | ||
116 | int i; | ||
117 | |||
118 | record->error = false; | ||
119 | |||
120 | /* find begin of record (marked by a colon) */ | ||
121 | while (record->txt_offset < record->txt_length | ||
122 | && record->txt_data[record->txt_offset] != ':') | ||
123 | record->txt_offset++; | ||
124 | if (record->txt_offset == record->txt_length) | ||
125 | return false; | ||
126 | |||
127 | /* number of characters needed for len, addr and type entries */ | ||
128 | record->txt_offset++; | ||
129 | if (record->txt_offset + 8 > record->txt_length) { | ||
130 | record->error = true; | ||
131 | return false; | ||
132 | } | ||
133 | |||
134 | record->len = usb6fire_fw_ihex_hex(record->txt_data + | ||
135 | record->txt_offset, &crc); | ||
136 | record->txt_offset += 2; | ||
137 | record->address = usb6fire_fw_ihex_hex(record->txt_data + | ||
138 | record->txt_offset, &crc) << 8; | ||
139 | record->txt_offset += 2; | ||
140 | record->address |= usb6fire_fw_ihex_hex(record->txt_data + | ||
141 | record->txt_offset, &crc); | ||
142 | record->txt_offset += 2; | ||
143 | type = usb6fire_fw_ihex_hex(record->txt_data + | ||
144 | record->txt_offset, &crc); | ||
145 | record->txt_offset += 2; | ||
146 | |||
147 | /* number of characters needed for data and crc entries */ | ||
148 | if (record->txt_offset + 2 * (record->len + 1) > record->txt_length) { | ||
149 | record->error = true; | ||
150 | return false; | ||
151 | } | ||
152 | for (i = 0; i < record->len; i++) { | ||
153 | record->data[i] = usb6fire_fw_ihex_hex(record->txt_data | ||
154 | + record->txt_offset, &crc); | ||
155 | record->txt_offset += 2; | ||
156 | } | ||
157 | usb6fire_fw_ihex_hex(record->txt_data + record->txt_offset, &crc); | ||
158 | if (crc) { | ||
159 | record->error = true; | ||
160 | return false; | ||
161 | } | ||
162 | |||
163 | if (type == 1 || !record->len) /* eof */ | ||
164 | return false; | ||
165 | else if (type == 0) | ||
166 | return true; | ||
167 | else { | ||
168 | record->error = true; | ||
169 | return false; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static int usb6fire_fw_ihex_init(const struct firmware *fw, | ||
174 | struct ihex_record *record) | ||
175 | { | ||
176 | record->txt_data = fw->data; | ||
177 | record->txt_length = fw->size; | ||
178 | record->txt_offset = 0; | ||
179 | record->max_len = 0; | ||
180 | /* read all records, if loop ends, record->error indicates, | ||
181 | * whether ihex is valid. */ | ||
182 | while (usb6fire_fw_ihex_next_record(record)) | ||
183 | record->max_len = max(record->len, record->max_len); | ||
184 | if (record->error) | ||
185 | return -EINVAL; | ||
186 | record->txt_offset = 0; | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int usb6fire_fw_ezusb_write(struct usb_device *device, | ||
191 | int type, int value, char *data, int len) | ||
192 | { | ||
193 | int ret; | ||
194 | |||
195 | ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), type, | ||
196 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
197 | value, 0, data, len, HZ); | ||
198 | if (ret < 0) | ||
199 | return ret; | ||
200 | else if (ret != len) | ||
201 | return -EIO; | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static int usb6fire_fw_ezusb_read(struct usb_device *device, | ||
206 | int type, int value, char *data, int len) | ||
207 | { | ||
208 | int ret = usb_control_msg(device, usb_rcvctrlpipe(device, 0), type, | ||
209 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value, | ||
210 | 0, data, len, HZ); | ||
211 | if (ret < 0) | ||
212 | return ret; | ||
213 | else if (ret != len) | ||
214 | return -EIO; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int usb6fire_fw_fpga_write(struct usb_device *device, | ||
219 | char *data, int len) | ||
220 | { | ||
221 | int actual_len; | ||
222 | int ret; | ||
223 | |||
224 | ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len, | ||
225 | &actual_len, HZ); | ||
226 | if (ret < 0) | ||
227 | return ret; | ||
228 | else if (actual_len != len) | ||
229 | return -EIO; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int usb6fire_fw_ezusb_upload( | ||
234 | struct usb_interface *intf, const char *fwname, | ||
235 | unsigned int postaddr, u8 *postdata, unsigned int postlen) | ||
236 | { | ||
237 | int ret; | ||
238 | u8 data; | ||
239 | struct usb_device *device = interface_to_usbdev(intf); | ||
240 | const struct firmware *fw = 0; | ||
241 | struct ihex_record *rec = kmalloc(sizeof(struct ihex_record), | ||
242 | GFP_KERNEL); | ||
243 | |||
244 | if (!rec) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | ret = request_firmware(&fw, fwname, &device->dev); | ||
248 | if (ret < 0) { | ||
249 | kfree(rec); | ||
250 | snd_printk(KERN_ERR PREFIX "error requesting ezusb " | ||
251 | "firmware %s.\n", fwname); | ||
252 | return ret; | ||
253 | } | ||
254 | ret = usb6fire_fw_ihex_init(fw, rec); | ||
255 | if (ret < 0) { | ||
256 | kfree(rec); | ||
257 | snd_printk(KERN_ERR PREFIX "error validating ezusb " | ||
258 | "firmware %s.\n", fwname); | ||
259 | return ret; | ||
260 | } | ||
261 | /* upload firmware image */ | ||
262 | data = 0x01; /* stop ezusb cpu */ | ||
263 | ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); | ||
264 | if (ret < 0) { | ||
265 | kfree(rec); | ||
266 | release_firmware(fw); | ||
267 | snd_printk(KERN_ERR PREFIX "unable to upload ezusb " | ||
268 | "firmware %s: begin message.\n", fwname); | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | while (usb6fire_fw_ihex_next_record(rec)) { /* write firmware */ | ||
273 | ret = usb6fire_fw_ezusb_write(device, 0xa0, rec->address, | ||
274 | rec->data, rec->len); | ||
275 | if (ret < 0) { | ||
276 | kfree(rec); | ||
277 | release_firmware(fw); | ||
278 | snd_printk(KERN_ERR PREFIX "unable to upload ezusb " | ||
279 | "firmware %s: data urb.\n", fwname); | ||
280 | return ret; | ||
281 | } | ||
282 | } | ||
283 | |||
284 | release_firmware(fw); | ||
285 | kfree(rec); | ||
286 | if (postdata) { /* write data after firmware has been uploaded */ | ||
287 | ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr, | ||
288 | postdata, postlen); | ||
289 | if (ret < 0) { | ||
290 | snd_printk(KERN_ERR PREFIX "unable to upload ezusb " | ||
291 | "firmware %s: post urb.\n", fwname); | ||
292 | return ret; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | data = 0x00; /* resume ezusb cpu */ | ||
297 | ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1); | ||
298 | if (ret < 0) { | ||
299 | release_firmware(fw); | ||
300 | snd_printk(KERN_ERR PREFIX "unable to upload ezusb " | ||
301 | "firmware %s: end message.\n", fwname); | ||
302 | return ret; | ||
303 | } | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int usb6fire_fw_fpga_upload( | ||
308 | struct usb_interface *intf, const char *fwname) | ||
309 | { | ||
310 | int ret; | ||
311 | int i; | ||
312 | struct usb_device *device = interface_to_usbdev(intf); | ||
313 | u8 *buffer = kmalloc(FPGA_BUFSIZE, GFP_KERNEL); | ||
314 | const char *c; | ||
315 | const char *end; | ||
316 | const struct firmware *fw; | ||
317 | |||
318 | if (!buffer) | ||
319 | return -ENOMEM; | ||
320 | |||
321 | ret = request_firmware(&fw, fwname, &device->dev); | ||
322 | if (ret < 0) { | ||
323 | snd_printk(KERN_ERR PREFIX "unable to get fpga firmware %s.\n", | ||
324 | fwname); | ||
325 | kfree(buffer); | ||
326 | return -EIO; | ||
327 | } | ||
328 | |||
329 | c = fw->data; | ||
330 | end = fw->data + fw->size; | ||
331 | |||
332 | ret = usb6fire_fw_ezusb_write(device, 8, 0, NULL, 0); | ||
333 | if (ret < 0) { | ||
334 | kfree(buffer); | ||
335 | release_firmware(fw); | ||
336 | snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: " | ||
337 | "begin urb.\n"); | ||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | while (c != end) { | ||
342 | for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++) | ||
343 | buffer[i] = BIT_REVERSE_TABLE[(u8) *c]; | ||
344 | |||
345 | ret = usb6fire_fw_fpga_write(device, buffer, i); | ||
346 | if (ret < 0) { | ||
347 | release_firmware(fw); | ||
348 | kfree(buffer); | ||
349 | snd_printk(KERN_ERR PREFIX "unable to upload fpga " | ||
350 | "firmware: fw urb.\n"); | ||
351 | return ret; | ||
352 | } | ||
353 | } | ||
354 | release_firmware(fw); | ||
355 | kfree(buffer); | ||
356 | |||
357 | ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0); | ||
358 | if (ret < 0) { | ||
359 | snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: " | ||
360 | "end urb.\n"); | ||
361 | return ret; | ||
362 | } | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | int usb6fire_fw_init(struct usb_interface *intf) | ||
367 | { | ||
368 | int i; | ||
369 | int ret; | ||
370 | struct usb_device *device = interface_to_usbdev(intf); | ||
371 | /* buffer: 8 receiving bytes from device and | ||
372 | * sizeof(EP_W_MAX_PACKET_SIZE) bytes for non-const copy */ | ||
373 | u8 buffer[12]; | ||
374 | |||
375 | ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8); | ||
376 | if (ret < 0) { | ||
377 | snd_printk(KERN_ERR PREFIX "unable to receive device " | ||
378 | "firmware state.\n"); | ||
379 | return ret; | ||
380 | } | ||
381 | if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55 | ||
382 | || buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7] | ||
383 | != 0x00) { | ||
384 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " | ||
385 | "received from device: "); | ||
386 | for (i = 0; i < 8; i++) | ||
387 | snd_printk("%02x ", buffer[i]); | ||
388 | snd_printk("\n"); | ||
389 | return -EIO; | ||
390 | } | ||
391 | /* do we need fpga loader ezusb firmware? */ | ||
392 | if (buffer[3] == 0x01 && buffer[6] == 0x19) { | ||
393 | ret = usb6fire_fw_ezusb_upload(intf, | ||
394 | "6fire/dmx6firel2.ihx", 0, NULL, 0); | ||
395 | if (ret < 0) | ||
396 | return ret; | ||
397 | return FW_NOT_READY; | ||
398 | } | ||
399 | /* do we need fpga firmware and application ezusb firmware? */ | ||
400 | else if (buffer[3] == 0x02 && buffer[6] == 0x0b) { | ||
401 | ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin"); | ||
402 | if (ret < 0) | ||
403 | return ret; | ||
404 | memcpy(buffer, ep_w_max_packet_size, | ||
405 | sizeof(ep_w_max_packet_size)); | ||
406 | ret = usb6fire_fw_ezusb_upload(intf, "6fire/dmx6fireap.ihx", | ||
407 | 0x0003, buffer, sizeof(ep_w_max_packet_size)); | ||
408 | if (ret < 0) | ||
409 | return ret; | ||
410 | return FW_NOT_READY; | ||
411 | } | ||
412 | /* all fw loaded? */ | ||
413 | else if (buffer[3] == 0x03 && buffer[6] == 0x0b) | ||
414 | return 0; | ||
415 | /* unknown data? */ | ||
416 | else { | ||
417 | snd_printk(KERN_ERR PREFIX "unknown device firmware state " | ||
418 | "received from device: "); | ||
419 | for (i = 0; i < 8; i++) | ||
420 | snd_printk("%02x ", buffer[i]); | ||
421 | snd_printk("\n"); | ||
422 | return -EIO; | ||
423 | } | ||
424 | return 0; | ||
425 | } | ||
426 | |||
diff --git a/sound/usb/6fire/firmware.h b/sound/usb/6fire/firmware.h new file mode 100644 index 000000000000..008569895381 --- /dev/null +++ b/sound/usb/6fire/firmware.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Author: Torsten Schenk | ||
5 | * Created: Jan 01, 2011 | ||
6 | * Copyright: (C) Torsten Schenk | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef USB6FIRE_FIRMWARE_H | ||
15 | #define USB6FIRE_FIRMWARE_H | ||
16 | |||
17 | #include "common.h" | ||
18 | |||
19 | enum /* firmware state of device */ | ||
20 | { | ||
21 | FW_READY = 0, | ||
22 | FW_NOT_READY = 1 | ||
23 | }; | ||
24 | |||
25 | int __devinit usb6fire_fw_init(struct usb_interface *intf); | ||
26 | #endif /* USB6FIRE_FIRMWARE_H */ | ||
27 | |||
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c new file mode 100644 index 000000000000..13f4509dce2b --- /dev/null +++ b/sound/usb/6fire/midi.c | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Rawmidi driver | ||
5 | * | ||
6 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
7 | * Created: Jan 01, 2011 | ||
8 | * Version: 0.3.0 | ||
9 | * Copyright: (C) Torsten Schenk | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <sound/rawmidi.h> | ||
18 | |||
19 | #include "midi.h" | ||
20 | #include "chip.h" | ||
21 | #include "comm.h" | ||
22 | |||
23 | static void usb6fire_midi_out_handler(struct urb *urb) | ||
24 | { | ||
25 | struct midi_runtime *rt = urb->context; | ||
26 | int ret; | ||
27 | unsigned long flags; | ||
28 | |||
29 | spin_lock_irqsave(&rt->out_lock, flags); | ||
30 | |||
31 | if (rt->out) { | ||
32 | ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4, | ||
33 | MIDI_BUFSIZE - 4); | ||
34 | if (ret > 0) { /* more data available, send next packet */ | ||
35 | rt->out_buffer[1] = ret + 2; | ||
36 | rt->out_buffer[3] = rt->out_serial++; | ||
37 | urb->transfer_buffer_length = ret + 4; | ||
38 | |||
39 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
40 | if (ret < 0) | ||
41 | snd_printk(KERN_ERR PREFIX "midi out urb " | ||
42 | "submit failed: %d\n", ret); | ||
43 | } else /* no more data to transmit */ | ||
44 | rt->out = NULL; | ||
45 | } | ||
46 | spin_unlock_irqrestore(&rt->out_lock, flags); | ||
47 | } | ||
48 | |||
49 | static void usb6fire_midi_in_received( | ||
50 | struct midi_runtime *rt, u8 *data, int length) | ||
51 | { | ||
52 | unsigned long flags; | ||
53 | |||
54 | spin_lock_irqsave(&rt->in_lock, flags); | ||
55 | if (rt->in) | ||
56 | snd_rawmidi_receive(rt->in, data, length); | ||
57 | spin_unlock_irqrestore(&rt->in_lock, flags); | ||
58 | } | ||
59 | |||
60 | static int usb6fire_midi_out_open(struct snd_rawmidi_substream *alsa_sub) | ||
61 | { | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int usb6fire_midi_out_close(struct snd_rawmidi_substream *alsa_sub) | ||
66 | { | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static void usb6fire_midi_out_trigger( | ||
71 | struct snd_rawmidi_substream *alsa_sub, int up) | ||
72 | { | ||
73 | struct midi_runtime *rt = alsa_sub->rmidi->private_data; | ||
74 | struct urb *urb = &rt->out_urb; | ||
75 | __s8 ret; | ||
76 | unsigned long flags; | ||
77 | |||
78 | spin_lock_irqsave(&rt->out_lock, flags); | ||
79 | if (up) { /* start transfer */ | ||
80 | if (rt->out) { /* we are already transmitting so just return */ | ||
81 | spin_unlock_irqrestore(&rt->out_lock, flags); | ||
82 | return; | ||
83 | } | ||
84 | |||
85 | ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4, | ||
86 | MIDI_BUFSIZE - 4); | ||
87 | if (ret > 0) { | ||
88 | rt->out_buffer[1] = ret + 2; | ||
89 | rt->out_buffer[3] = rt->out_serial++; | ||
90 | urb->transfer_buffer_length = ret + 4; | ||
91 | |||
92 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
93 | if (ret < 0) | ||
94 | snd_printk(KERN_ERR PREFIX "midi out urb " | ||
95 | "submit failed: %d\n", ret); | ||
96 | else | ||
97 | rt->out = alsa_sub; | ||
98 | } | ||
99 | } else if (rt->out == alsa_sub) | ||
100 | rt->out = NULL; | ||
101 | spin_unlock_irqrestore(&rt->out_lock, flags); | ||
102 | } | ||
103 | |||
104 | static void usb6fire_midi_out_drain(struct snd_rawmidi_substream *alsa_sub) | ||
105 | { | ||
106 | struct midi_runtime *rt = alsa_sub->rmidi->private_data; | ||
107 | int retry = 0; | ||
108 | |||
109 | while (rt->out && retry++ < 100) | ||
110 | msleep(10); | ||
111 | } | ||
112 | |||
113 | static int usb6fire_midi_in_open(struct snd_rawmidi_substream *alsa_sub) | ||
114 | { | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int usb6fire_midi_in_close(struct snd_rawmidi_substream *alsa_sub) | ||
119 | { | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static void usb6fire_midi_in_trigger( | ||
124 | struct snd_rawmidi_substream *alsa_sub, int up) | ||
125 | { | ||
126 | struct midi_runtime *rt = alsa_sub->rmidi->private_data; | ||
127 | unsigned long flags; | ||
128 | |||
129 | spin_lock_irqsave(&rt->in_lock, flags); | ||
130 | if (up) | ||
131 | rt->in = alsa_sub; | ||
132 | else | ||
133 | rt->in = NULL; | ||
134 | spin_unlock_irqrestore(&rt->in_lock, flags); | ||
135 | } | ||
136 | |||
137 | static struct snd_rawmidi_ops out_ops = { | ||
138 | .open = usb6fire_midi_out_open, | ||
139 | .close = usb6fire_midi_out_close, | ||
140 | .trigger = usb6fire_midi_out_trigger, | ||
141 | .drain = usb6fire_midi_out_drain | ||
142 | }; | ||
143 | |||
144 | static struct snd_rawmidi_ops in_ops = { | ||
145 | .open = usb6fire_midi_in_open, | ||
146 | .close = usb6fire_midi_in_close, | ||
147 | .trigger = usb6fire_midi_in_trigger | ||
148 | }; | ||
149 | |||
150 | int __devinit usb6fire_midi_init(struct sfire_chip *chip) | ||
151 | { | ||
152 | int ret; | ||
153 | struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime), | ||
154 | GFP_KERNEL); | ||
155 | struct comm_runtime *comm_rt = chip->comm; | ||
156 | |||
157 | if (!rt) | ||
158 | return -ENOMEM; | ||
159 | |||
160 | rt->chip = chip; | ||
161 | rt->in_received = usb6fire_midi_in_received; | ||
162 | rt->out_buffer[0] = 0x80; /* 'send midi' command */ | ||
163 | rt->out_buffer[1] = 0x00; /* size of data */ | ||
164 | rt->out_buffer[2] = 0x00; /* always 0 */ | ||
165 | spin_lock_init(&rt->in_lock); | ||
166 | spin_lock_init(&rt->out_lock); | ||
167 | |||
168 | comm_rt->init_urb(comm_rt, &rt->out_urb, rt->out_buffer, rt, | ||
169 | usb6fire_midi_out_handler); | ||
170 | |||
171 | ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance); | ||
172 | if (ret < 0) { | ||
173 | kfree(rt); | ||
174 | snd_printk(KERN_ERR PREFIX "unable to create midi.\n"); | ||
175 | return ret; | ||
176 | } | ||
177 | rt->instance->private_data = rt; | ||
178 | strcpy(rt->instance->name, "DMX6FireUSB MIDI"); | ||
179 | rt->instance->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | | ||
180 | SNDRV_RAWMIDI_INFO_INPUT | | ||
181 | SNDRV_RAWMIDI_INFO_DUPLEX; | ||
182 | snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_OUTPUT, | ||
183 | &out_ops); | ||
184 | snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_INPUT, | ||
185 | &in_ops); | ||
186 | |||
187 | chip->midi = rt; | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | void usb6fire_midi_abort(struct sfire_chip *chip) | ||
192 | { | ||
193 | struct midi_runtime *rt = chip->midi; | ||
194 | |||
195 | if (rt) | ||
196 | usb_poison_urb(&rt->out_urb); | ||
197 | } | ||
198 | |||
199 | void usb6fire_midi_destroy(struct sfire_chip *chip) | ||
200 | { | ||
201 | kfree(chip->midi); | ||
202 | chip->midi = NULL; | ||
203 | } | ||
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h new file mode 100644 index 000000000000..97a7bf669135 --- /dev/null +++ b/sound/usb/6fire/midi.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
5 | * Created: Jan 01, 2011 | ||
6 | * Version: 0.3.0 | ||
7 | * Copyright: (C) Torsten Schenk | ||
8 | * | ||
9 | * This program 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 | |||
15 | #ifndef USB6FIRE_MIDI_H | ||
16 | #define USB6FIRE_MIDI_H | ||
17 | |||
18 | #include "common.h" | ||
19 | |||
20 | enum { | ||
21 | MIDI_BUFSIZE = 64 | ||
22 | }; | ||
23 | |||
24 | struct midi_runtime { | ||
25 | struct sfire_chip *chip; | ||
26 | struct snd_rawmidi *instance; | ||
27 | |||
28 | struct snd_rawmidi_substream *in; | ||
29 | char in_active; | ||
30 | |||
31 | spinlock_t in_lock; | ||
32 | spinlock_t out_lock; | ||
33 | struct snd_rawmidi_substream *out; | ||
34 | struct urb out_urb; | ||
35 | u8 out_serial; /* serial number of out packet */ | ||
36 | u8 out_buffer[MIDI_BUFSIZE]; | ||
37 | int buffer_offset; | ||
38 | |||
39 | void (*in_received)(struct midi_runtime *rt, u8 *data, int length); | ||
40 | }; | ||
41 | |||
42 | int __devinit usb6fire_midi_init(struct sfire_chip *chip); | ||
43 | void usb6fire_midi_abort(struct sfire_chip *chip); | ||
44 | void usb6fire_midi_destroy(struct sfire_chip *chip); | ||
45 | #endif /* USB6FIRE_MIDI_H */ | ||
46 | |||
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c new file mode 100644 index 000000000000..ba62c7468ba8 --- /dev/null +++ b/sound/usb/6fire/pcm.c | |||
@@ -0,0 +1,688 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * PCM driver | ||
5 | * | ||
6 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
7 | * Created: Jan 01, 2011 | ||
8 | * Version: 0.3.0 | ||
9 | * Copyright: (C) Torsten Schenk | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include "pcm.h" | ||
18 | #include "chip.h" | ||
19 | #include "comm.h" | ||
20 | |||
21 | enum { | ||
22 | OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4 | ||
23 | }; | ||
24 | |||
25 | /* keep next two synced with | ||
26 | * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */ | ||
27 | static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 }; | ||
28 | static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 }; | ||
29 | static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; | ||
30 | static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 }; | ||
31 | static const int rates_alsaid[] = { | ||
32 | SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000, | ||
33 | SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000, | ||
34 | SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 }; | ||
35 | |||
36 | /* values to write to soundcard register for all samplerates */ | ||
37 | static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01}; | ||
38 | static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00}; | ||
39 | |||
40 | enum { /* settings for pcm */ | ||
41 | OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024 | ||
42 | }; | ||
43 | |||
44 | enum { /* pcm streaming states */ | ||
45 | STREAM_DISABLED, /* no pcm streaming */ | ||
46 | STREAM_STARTING, /* pcm streaming requested, waiting to become ready */ | ||
47 | STREAM_RUNNING, /* pcm streaming running */ | ||
48 | STREAM_STOPPING | ||
49 | }; | ||
50 | |||
51 | enum { /* pcm sample rates (also index into RATES_XXX[]) */ | ||
52 | RATE_44KHZ, | ||
53 | RATE_48KHZ, | ||
54 | RATE_88KHZ, | ||
55 | RATE_96KHZ, | ||
56 | RATE_176KHZ, | ||
57 | RATE_192KHZ | ||
58 | }; | ||
59 | |||
60 | static const struct snd_pcm_hardware pcm_hw = { | ||
61 | .info = SNDRV_PCM_INFO_MMAP | | ||
62 | SNDRV_PCM_INFO_INTERLEAVED | | ||
63 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
64 | SNDRV_PCM_INFO_MMAP_VALID | | ||
65 | SNDRV_PCM_INFO_BATCH, | ||
66 | |||
67 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | ||
68 | |||
69 | .rates = SNDRV_PCM_RATE_44100 | | ||
70 | SNDRV_PCM_RATE_48000 | | ||
71 | SNDRV_PCM_RATE_88200 | | ||
72 | SNDRV_PCM_RATE_96000 | | ||
73 | SNDRV_PCM_RATE_176400 | | ||
74 | SNDRV_PCM_RATE_192000, | ||
75 | |||
76 | .rate_min = 44100, | ||
77 | .rate_max = 192000, | ||
78 | .channels_min = 1, | ||
79 | .channels_max = 0, /* set in pcm_open, depending on capture/playback */ | ||
80 | .buffer_bytes_max = MAX_BUFSIZE, | ||
81 | .period_bytes_min = PCM_N_PACKETS_PER_URB * (PCM_MAX_PACKET_SIZE - 4), | ||
82 | .period_bytes_max = MAX_BUFSIZE, | ||
83 | .periods_min = 2, | ||
84 | .periods_max = 1024 | ||
85 | }; | ||
86 | |||
87 | static int usb6fire_pcm_set_rate(struct pcm_runtime *rt) | ||
88 | { | ||
89 | int ret; | ||
90 | struct usb_device *device = rt->chip->dev; | ||
91 | struct comm_runtime *comm_rt = rt->chip->comm; | ||
92 | |||
93 | if (rt->rate >= ARRAY_SIZE(rates)) | ||
94 | return -EINVAL; | ||
95 | /* disable streaming */ | ||
96 | ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00); | ||
97 | if (ret < 0) { | ||
98 | snd_printk(KERN_ERR PREFIX "error stopping streaming while " | ||
99 | "setting samplerate %d.\n", rates[rt->rate]); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]); | ||
104 | if (ret < 0) { | ||
105 | snd_printk(KERN_ERR PREFIX "error setting interface " | ||
106 | "altsetting %d for samplerate %d.\n", | ||
107 | rates_altsetting[rt->rate], rates[rt->rate]); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | /* set soundcard clock */ | ||
112 | ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rt->rate], | ||
113 | rates_6fire_vh[rt->rate]); | ||
114 | if (ret < 0) { | ||
115 | snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n", | ||
116 | rates[rt->rate]); | ||
117 | return ret; | ||
118 | } | ||
119 | |||
120 | /* enable analog inputs and outputs | ||
121 | * (one bit per stereo-channel) */ | ||
122 | ret = comm_rt->write16(comm_rt, 0x02, 0x02, | ||
123 | (1 << (OUT_N_CHANNELS / 2)) - 1, | ||
124 | (1 << (IN_N_CHANNELS / 2)) - 1); | ||
125 | if (ret < 0) { | ||
126 | snd_printk(KERN_ERR PREFIX "error initializing analog channels " | ||
127 | "while setting samplerate %d.\n", | ||
128 | rates[rt->rate]); | ||
129 | return ret; | ||
130 | } | ||
131 | /* disable digital inputs and outputs */ | ||
132 | ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00); | ||
133 | if (ret < 0) { | ||
134 | snd_printk(KERN_ERR PREFIX "error initializing digital " | ||
135 | "channels while setting samplerate %d.\n", | ||
136 | rates[rt->rate]); | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01); | ||
141 | if (ret < 0) { | ||
142 | snd_printk(KERN_ERR PREFIX "error starting streaming while " | ||
143 | "setting samplerate %d.\n", rates[rt->rate]); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | rt->in_n_analog = IN_N_CHANNELS; | ||
148 | rt->out_n_analog = OUT_N_CHANNELS; | ||
149 | rt->in_packet_size = rates_in_packet_size[rt->rate]; | ||
150 | rt->out_packet_size = rates_out_packet_size[rt->rate]; | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static struct pcm_substream *usb6fire_pcm_get_substream( | ||
155 | struct snd_pcm_substream *alsa_sub) | ||
156 | { | ||
157 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
158 | |||
159 | if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
160 | return &rt->playback; | ||
161 | else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
162 | return &rt->capture; | ||
163 | snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n"); | ||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | /* call with stream_mutex locked */ | ||
168 | static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt) | ||
169 | { | ||
170 | int i; | ||
171 | |||
172 | if (rt->stream_state != STREAM_DISABLED) { | ||
173 | for (i = 0; i < PCM_N_URBS; i++) { | ||
174 | usb_kill_urb(&rt->in_urbs[i].instance); | ||
175 | usb_kill_urb(&rt->out_urbs[i].instance); | ||
176 | } | ||
177 | rt->stream_state = STREAM_DISABLED; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | /* call with stream_mutex locked */ | ||
182 | static int usb6fire_pcm_stream_start(struct pcm_runtime *rt) | ||
183 | { | ||
184 | int ret; | ||
185 | int i; | ||
186 | int k; | ||
187 | struct usb_iso_packet_descriptor *packet; | ||
188 | |||
189 | if (rt->stream_state == STREAM_DISABLED) { | ||
190 | /* submit our in urbs */ | ||
191 | rt->stream_wait_cond = false; | ||
192 | rt->stream_state = STREAM_STARTING; | ||
193 | for (i = 0; i < PCM_N_URBS; i++) { | ||
194 | for (k = 0; k < PCM_N_PACKETS_PER_URB; k++) { | ||
195 | packet = &rt->in_urbs[i].packets[k]; | ||
196 | packet->offset = k * rt->in_packet_size; | ||
197 | packet->length = rt->in_packet_size; | ||
198 | packet->actual_length = 0; | ||
199 | packet->status = 0; | ||
200 | } | ||
201 | ret = usb_submit_urb(&rt->in_urbs[i].instance, | ||
202 | GFP_ATOMIC); | ||
203 | if (ret) { | ||
204 | usb6fire_pcm_stream_stop(rt); | ||
205 | return ret; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /* wait for first out urb to return (sent in in urb handler) */ | ||
210 | wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond, | ||
211 | HZ); | ||
212 | if (rt->stream_wait_cond) | ||
213 | rt->stream_state = STREAM_RUNNING; | ||
214 | else { | ||
215 | usb6fire_pcm_stream_stop(rt); | ||
216 | return -EIO; | ||
217 | } | ||
218 | } | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* call with substream locked */ | ||
223 | static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb) | ||
224 | { | ||
225 | int i; | ||
226 | int frame; | ||
227 | int frame_count; | ||
228 | unsigned int total_length = 0; | ||
229 | struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); | ||
230 | struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; | ||
231 | u32 *src = (u32 *) urb->buffer; | ||
232 | u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off | ||
233 | * (alsa_rt->frame_bits >> 3)); | ||
234 | u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size | ||
235 | * (alsa_rt->frame_bits >> 3)); | ||
236 | int bytes_per_frame = alsa_rt->channels << 2; | ||
237 | |||
238 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { | ||
239 | /* at least 4 header bytes for valid packet. | ||
240 | * after that: 32 bits per sample for analog channels */ | ||
241 | if (urb->packets[i].actual_length > 4) | ||
242 | frame_count = (urb->packets[i].actual_length - 4) | ||
243 | / (rt->in_n_analog << 2); | ||
244 | else | ||
245 | frame_count = 0; | ||
246 | |||
247 | src = (u32 *) (urb->buffer + total_length); | ||
248 | src++; /* skip leading 4 bytes of every packet */ | ||
249 | total_length += urb->packets[i].length; | ||
250 | for (frame = 0; frame < frame_count; frame++) { | ||
251 | memcpy(dest, src, bytes_per_frame); | ||
252 | dest += alsa_rt->channels; | ||
253 | src += rt->in_n_analog; | ||
254 | sub->dma_off++; | ||
255 | sub->period_off++; | ||
256 | if (dest == dest_end) { | ||
257 | sub->dma_off = 0; | ||
258 | dest = (u32 *) alsa_rt->dma_area; | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | /* call with substream locked */ | ||
265 | static void usb6fire_pcm_playback(struct pcm_substream *sub, | ||
266 | struct pcm_urb *urb) | ||
267 | { | ||
268 | int i; | ||
269 | int frame; | ||
270 | int frame_count; | ||
271 | struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance); | ||
272 | struct snd_pcm_runtime *alsa_rt = sub->instance->runtime; | ||
273 | u32 *src = (u32 *) (alsa_rt->dma_area + sub->dma_off | ||
274 | * (alsa_rt->frame_bits >> 3)); | ||
275 | u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size | ||
276 | * (alsa_rt->frame_bits >> 3)); | ||
277 | u32 *dest = (u32 *) urb->buffer; | ||
278 | int bytes_per_frame = alsa_rt->channels << 2; | ||
279 | |||
280 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { | ||
281 | /* at least 4 header bytes for valid packet. | ||
282 | * after that: 32 bits per sample for analog channels */ | ||
283 | if (urb->packets[i].length > 4) | ||
284 | frame_count = (urb->packets[i].length - 4) | ||
285 | / (rt->out_n_analog << 2); | ||
286 | else | ||
287 | frame_count = 0; | ||
288 | dest++; /* skip leading 4 bytes of every frame */ | ||
289 | for (frame = 0; frame < frame_count; frame++) { | ||
290 | memcpy(dest, src, bytes_per_frame); | ||
291 | src += alsa_rt->channels; | ||
292 | dest += rt->out_n_analog; | ||
293 | sub->dma_off++; | ||
294 | sub->period_off++; | ||
295 | if (src == src_end) { | ||
296 | src = (u32 *) alsa_rt->dma_area; | ||
297 | sub->dma_off = 0; | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | } | ||
302 | |||
303 | static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb) | ||
304 | { | ||
305 | struct pcm_urb *in_urb = usb_urb->context; | ||
306 | struct pcm_urb *out_urb = in_urb->peer; | ||
307 | struct pcm_runtime *rt = in_urb->chip->pcm; | ||
308 | struct pcm_substream *sub; | ||
309 | unsigned long flags; | ||
310 | int total_length = 0; | ||
311 | int frame_count; | ||
312 | int frame; | ||
313 | int channel; | ||
314 | int i; | ||
315 | u8 *dest; | ||
316 | |||
317 | if (usb_urb->status || rt->panic || rt->stream_state == STREAM_STOPPING) | ||
318 | return; | ||
319 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) | ||
320 | if (in_urb->packets[i].status) { | ||
321 | rt->panic = true; | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | if (rt->stream_state == STREAM_DISABLED) { | ||
326 | snd_printk(KERN_ERR PREFIX "internal error: " | ||
327 | "stream disabled in in-urb handler.\n"); | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | /* receive our capture data */ | ||
332 | sub = &rt->capture; | ||
333 | spin_lock_irqsave(&sub->lock, flags); | ||
334 | if (sub->active) { | ||
335 | usb6fire_pcm_capture(sub, in_urb); | ||
336 | if (sub->period_off >= sub->instance->runtime->period_size) { | ||
337 | sub->period_off %= sub->instance->runtime->period_size; | ||
338 | spin_unlock_irqrestore(&sub->lock, flags); | ||
339 | snd_pcm_period_elapsed(sub->instance); | ||
340 | } else | ||
341 | spin_unlock_irqrestore(&sub->lock, flags); | ||
342 | } else | ||
343 | spin_unlock_irqrestore(&sub->lock, flags); | ||
344 | |||
345 | /* setup out urb structure */ | ||
346 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) { | ||
347 | out_urb->packets[i].offset = total_length; | ||
348 | out_urb->packets[i].length = (in_urb->packets[i].actual_length | ||
349 | - 4) / (rt->in_n_analog << 2) | ||
350 | * (rt->out_n_analog << 2) + 4; | ||
351 | out_urb->packets[i].status = 0; | ||
352 | total_length += out_urb->packets[i].length; | ||
353 | } | ||
354 | memset(out_urb->buffer, 0, total_length); | ||
355 | |||
356 | /* now send our playback data (if a free out urb was found) */ | ||
357 | sub = &rt->playback; | ||
358 | spin_lock_irqsave(&sub->lock, flags); | ||
359 | if (sub->active) { | ||
360 | usb6fire_pcm_playback(sub, out_urb); | ||
361 | if (sub->period_off >= sub->instance->runtime->period_size) { | ||
362 | sub->period_off %= sub->instance->runtime->period_size; | ||
363 | spin_unlock_irqrestore(&sub->lock, flags); | ||
364 | snd_pcm_period_elapsed(sub->instance); | ||
365 | } else | ||
366 | spin_unlock_irqrestore(&sub->lock, flags); | ||
367 | } else | ||
368 | spin_unlock_irqrestore(&sub->lock, flags); | ||
369 | |||
370 | /* setup the 4th byte of each sample (0x40 for analog channels) */ | ||
371 | dest = out_urb->buffer; | ||
372 | for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) | ||
373 | if (out_urb->packets[i].length >= 4) { | ||
374 | frame_count = (out_urb->packets[i].length - 4) | ||
375 | / (rt->out_n_analog << 2); | ||
376 | *(dest++) = 0xaa; | ||
377 | *(dest++) = 0xaa; | ||
378 | *(dest++) = frame_count; | ||
379 | *(dest++) = 0x00; | ||
380 | for (frame = 0; frame < frame_count; frame++) | ||
381 | for (channel = 0; | ||
382 | channel < rt->out_n_analog; | ||
383 | channel++) { | ||
384 | dest += 3; /* skip sample data */ | ||
385 | *(dest++) = 0x40; | ||
386 | } | ||
387 | } | ||
388 | usb_submit_urb(&out_urb->instance, GFP_ATOMIC); | ||
389 | usb_submit_urb(&in_urb->instance, GFP_ATOMIC); | ||
390 | } | ||
391 | |||
392 | static void usb6fire_pcm_out_urb_handler(struct urb *usb_urb) | ||
393 | { | ||
394 | struct pcm_urb *urb = usb_urb->context; | ||
395 | struct pcm_runtime *rt = urb->chip->pcm; | ||
396 | |||
397 | if (rt->stream_state == STREAM_STARTING) { | ||
398 | rt->stream_wait_cond = true; | ||
399 | wake_up(&rt->stream_wait_queue); | ||
400 | } | ||
401 | } | ||
402 | |||
403 | static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub) | ||
404 | { | ||
405 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
406 | struct pcm_substream *sub = NULL; | ||
407 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; | ||
408 | |||
409 | if (rt->panic) | ||
410 | return -EPIPE; | ||
411 | |||
412 | mutex_lock(&rt->stream_mutex); | ||
413 | alsa_rt->hw = pcm_hw; | ||
414 | |||
415 | if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
416 | if (rt->rate >= 0) | ||
417 | alsa_rt->hw.rates = rates_alsaid[rt->rate]; | ||
418 | alsa_rt->hw.channels_max = OUT_N_CHANNELS; | ||
419 | sub = &rt->playback; | ||
420 | } else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
421 | if (rt->rate >= 0) | ||
422 | alsa_rt->hw.rates = rates_alsaid[rt->rate]; | ||
423 | alsa_rt->hw.channels_max = IN_N_CHANNELS; | ||
424 | sub = &rt->capture; | ||
425 | } | ||
426 | |||
427 | if (!sub) { | ||
428 | mutex_unlock(&rt->stream_mutex); | ||
429 | snd_printk(KERN_ERR PREFIX "invalid stream type.\n"); | ||
430 | return -EINVAL; | ||
431 | } | ||
432 | |||
433 | sub->instance = alsa_sub; | ||
434 | sub->active = false; | ||
435 | mutex_unlock(&rt->stream_mutex); | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub) | ||
440 | { | ||
441 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
442 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); | ||
443 | unsigned long flags; | ||
444 | |||
445 | if (rt->panic) | ||
446 | return 0; | ||
447 | |||
448 | mutex_lock(&rt->stream_mutex); | ||
449 | if (sub) { | ||
450 | /* deactivate substream */ | ||
451 | spin_lock_irqsave(&sub->lock, flags); | ||
452 | sub->instance = NULL; | ||
453 | sub->active = false; | ||
454 | spin_unlock_irqrestore(&sub->lock, flags); | ||
455 | |||
456 | /* all substreams closed? if so, stop streaming */ | ||
457 | if (!rt->playback.instance && !rt->capture.instance) { | ||
458 | usb6fire_pcm_stream_stop(rt); | ||
459 | rt->rate = -1; | ||
460 | } | ||
461 | } | ||
462 | mutex_unlock(&rt->stream_mutex); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub, | ||
467 | struct snd_pcm_hw_params *hw_params) | ||
468 | { | ||
469 | return snd_pcm_lib_malloc_pages(alsa_sub, | ||
470 | params_buffer_bytes(hw_params)); | ||
471 | } | ||
472 | |||
473 | static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub) | ||
474 | { | ||
475 | return snd_pcm_lib_free_pages(alsa_sub); | ||
476 | } | ||
477 | |||
478 | static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub) | ||
479 | { | ||
480 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
481 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); | ||
482 | struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime; | ||
483 | int i; | ||
484 | int ret; | ||
485 | |||
486 | if (rt->panic) | ||
487 | return -EPIPE; | ||
488 | if (!sub) | ||
489 | return -ENODEV; | ||
490 | |||
491 | mutex_lock(&rt->stream_mutex); | ||
492 | sub->dma_off = 0; | ||
493 | sub->period_off = 0; | ||
494 | |||
495 | if (rt->stream_state == STREAM_DISABLED) { | ||
496 | for (i = 0; i < ARRAY_SIZE(rates); i++) | ||
497 | if (alsa_rt->rate == rates[i]) { | ||
498 | rt->rate = i; | ||
499 | break; | ||
500 | } | ||
501 | if (i == ARRAY_SIZE(rates)) { | ||
502 | mutex_unlock(&rt->stream_mutex); | ||
503 | snd_printk("invalid rate %d in prepare.\n", | ||
504 | alsa_rt->rate); | ||
505 | return -EINVAL; | ||
506 | } | ||
507 | |||
508 | ret = usb6fire_pcm_set_rate(rt); | ||
509 | if (ret) { | ||
510 | mutex_unlock(&rt->stream_mutex); | ||
511 | return ret; | ||
512 | } | ||
513 | ret = usb6fire_pcm_stream_start(rt); | ||
514 | if (ret) { | ||
515 | mutex_unlock(&rt->stream_mutex); | ||
516 | snd_printk(KERN_ERR PREFIX | ||
517 | "could not start pcm stream.\n"); | ||
518 | return ret; | ||
519 | } | ||
520 | } | ||
521 | mutex_unlock(&rt->stream_mutex); | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int usb6fire_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd) | ||
526 | { | ||
527 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); | ||
528 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
529 | unsigned long flags; | ||
530 | |||
531 | if (rt->panic) | ||
532 | return -EPIPE; | ||
533 | if (!sub) | ||
534 | return -ENODEV; | ||
535 | |||
536 | switch (cmd) { | ||
537 | case SNDRV_PCM_TRIGGER_START: | ||
538 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
539 | spin_lock_irqsave(&sub->lock, flags); | ||
540 | sub->active = true; | ||
541 | spin_unlock_irqrestore(&sub->lock, flags); | ||
542 | return 0; | ||
543 | |||
544 | case SNDRV_PCM_TRIGGER_STOP: | ||
545 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
546 | spin_lock_irqsave(&sub->lock, flags); | ||
547 | sub->active = false; | ||
548 | spin_unlock_irqrestore(&sub->lock, flags); | ||
549 | return 0; | ||
550 | |||
551 | default: | ||
552 | return -EINVAL; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | static snd_pcm_uframes_t usb6fire_pcm_pointer( | ||
557 | struct snd_pcm_substream *alsa_sub) | ||
558 | { | ||
559 | struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub); | ||
560 | struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub); | ||
561 | unsigned long flags; | ||
562 | snd_pcm_uframes_t ret; | ||
563 | |||
564 | if (rt->panic || !sub) | ||
565 | return SNDRV_PCM_STATE_XRUN; | ||
566 | |||
567 | spin_lock_irqsave(&sub->lock, flags); | ||
568 | ret = sub->dma_off; | ||
569 | spin_unlock_irqrestore(&sub->lock, flags); | ||
570 | return ret; | ||
571 | } | ||
572 | |||
573 | static struct snd_pcm_ops pcm_ops = { | ||
574 | .open = usb6fire_pcm_open, | ||
575 | .close = usb6fire_pcm_close, | ||
576 | .ioctl = snd_pcm_lib_ioctl, | ||
577 | .hw_params = usb6fire_pcm_hw_params, | ||
578 | .hw_free = usb6fire_pcm_hw_free, | ||
579 | .prepare = usb6fire_pcm_prepare, | ||
580 | .trigger = usb6fire_pcm_trigger, | ||
581 | .pointer = usb6fire_pcm_pointer, | ||
582 | }; | ||
583 | |||
584 | static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb, | ||
585 | struct sfire_chip *chip, bool in, int ep, | ||
586 | void (*handler)(struct urb *)) | ||
587 | { | ||
588 | urb->chip = chip; | ||
589 | usb_init_urb(&urb->instance); | ||
590 | urb->instance.transfer_buffer = urb->buffer; | ||
591 | urb->instance.transfer_buffer_length = | ||
592 | PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE; | ||
593 | urb->instance.dev = chip->dev; | ||
594 | urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep) | ||
595 | : usb_sndisocpipe(chip->dev, ep); | ||
596 | urb->instance.interval = 1; | ||
597 | urb->instance.transfer_flags = URB_ISO_ASAP; | ||
598 | urb->instance.complete = handler; | ||
599 | urb->instance.context = urb; | ||
600 | urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB; | ||
601 | } | ||
602 | |||
603 | int __devinit usb6fire_pcm_init(struct sfire_chip *chip) | ||
604 | { | ||
605 | int i; | ||
606 | int ret; | ||
607 | struct snd_pcm *pcm; | ||
608 | struct pcm_runtime *rt = | ||
609 | kzalloc(sizeof(struct pcm_runtime), GFP_KERNEL); | ||
610 | |||
611 | if (!rt) | ||
612 | return -ENOMEM; | ||
613 | |||
614 | rt->chip = chip; | ||
615 | rt->stream_state = STREAM_DISABLED; | ||
616 | rt->rate = -1; | ||
617 | init_waitqueue_head(&rt->stream_wait_queue); | ||
618 | mutex_init(&rt->stream_mutex); | ||
619 | |||
620 | spin_lock_init(&rt->playback.lock); | ||
621 | spin_lock_init(&rt->capture.lock); | ||
622 | |||
623 | for (i = 0; i < PCM_N_URBS; i++) { | ||
624 | usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP, | ||
625 | usb6fire_pcm_in_urb_handler); | ||
626 | usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP, | ||
627 | usb6fire_pcm_out_urb_handler); | ||
628 | |||
629 | rt->in_urbs[i].peer = &rt->out_urbs[i]; | ||
630 | rt->out_urbs[i].peer = &rt->in_urbs[i]; | ||
631 | } | ||
632 | |||
633 | ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm); | ||
634 | if (ret < 0) { | ||
635 | kfree(rt); | ||
636 | snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n"); | ||
637 | return ret; | ||
638 | } | ||
639 | |||
640 | pcm->private_data = rt; | ||
641 | strcpy(pcm->name, "DMX 6Fire USB"); | ||
642 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops); | ||
643 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops); | ||
644 | |||
645 | ret = snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
646 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
647 | snd_dma_continuous_data(GFP_KERNEL), | ||
648 | MAX_BUFSIZE, MAX_BUFSIZE); | ||
649 | if (ret) { | ||
650 | kfree(rt); | ||
651 | snd_printk(KERN_ERR PREFIX | ||
652 | "error preallocating pcm buffers.\n"); | ||
653 | return ret; | ||
654 | } | ||
655 | rt->instance = pcm; | ||
656 | |||
657 | chip->pcm = rt; | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | void usb6fire_pcm_abort(struct sfire_chip *chip) | ||
662 | { | ||
663 | struct pcm_runtime *rt = chip->pcm; | ||
664 | int i; | ||
665 | |||
666 | if (rt) { | ||
667 | rt->panic = true; | ||
668 | |||
669 | if (rt->playback.instance) | ||
670 | snd_pcm_stop(rt->playback.instance, | ||
671 | SNDRV_PCM_STATE_XRUN); | ||
672 | if (rt->capture.instance) | ||
673 | snd_pcm_stop(rt->capture.instance, | ||
674 | SNDRV_PCM_STATE_XRUN); | ||
675 | |||
676 | for (i = 0; i < PCM_N_URBS; i++) { | ||
677 | usb_poison_urb(&rt->in_urbs[i].instance); | ||
678 | usb_poison_urb(&rt->out_urbs[i].instance); | ||
679 | } | ||
680 | |||
681 | } | ||
682 | } | ||
683 | |||
684 | void usb6fire_pcm_destroy(struct sfire_chip *chip) | ||
685 | { | ||
686 | kfree(chip->pcm); | ||
687 | chip->pcm = NULL; | ||
688 | } | ||
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h new file mode 100644 index 000000000000..2bee81374002 --- /dev/null +++ b/sound/usb/6fire/pcm.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Linux driver for TerraTec DMX 6Fire USB | ||
3 | * | ||
4 | * Author: Torsten Schenk <torsten.schenk@zoho.com> | ||
5 | * Created: Jan 01, 2011 | ||
6 | * Version: 0.3.0 | ||
7 | * Copyright: (C) Torsten Schenk | ||
8 | * | ||
9 | * This program 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 | |||
15 | #ifndef USB6FIRE_PCM_H | ||
16 | #define USB6FIRE_PCM_H | ||
17 | |||
18 | #include <sound/pcm.h> | ||
19 | #include <linux/mutex.h> | ||
20 | |||
21 | #include "common.h" | ||
22 | |||
23 | enum /* settings for pcm */ | ||
24 | { | ||
25 | /* maximum of EP_W_MAX_PACKET_SIZE[] (see firmware.c) */ | ||
26 | PCM_N_URBS = 16, PCM_N_PACKETS_PER_URB = 8, PCM_MAX_PACKET_SIZE = 604 | ||
27 | }; | ||
28 | |||
29 | struct pcm_urb { | ||
30 | struct sfire_chip *chip; | ||
31 | |||
32 | /* BEGIN DO NOT SEPARATE */ | ||
33 | struct urb instance; | ||
34 | struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB]; | ||
35 | /* END DO NOT SEPARATE */ | ||
36 | u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE]; | ||
37 | |||
38 | struct pcm_urb *peer; | ||
39 | }; | ||
40 | |||
41 | struct pcm_substream { | ||
42 | spinlock_t lock; | ||
43 | struct snd_pcm_substream *instance; | ||
44 | |||
45 | bool active; | ||
46 | |||
47 | snd_pcm_uframes_t dma_off; /* current position in alsa dma_area */ | ||
48 | snd_pcm_uframes_t period_off; /* current position in current period */ | ||
49 | }; | ||
50 | |||
51 | struct pcm_runtime { | ||
52 | struct sfire_chip *chip; | ||
53 | struct snd_pcm *instance; | ||
54 | |||
55 | struct pcm_substream playback; | ||
56 | struct pcm_substream capture; | ||
57 | bool panic; /* if set driver won't do anymore pcm on device */ | ||
58 | |||
59 | struct pcm_urb in_urbs[PCM_N_URBS]; | ||
60 | struct pcm_urb out_urbs[PCM_N_URBS]; | ||
61 | int in_packet_size; | ||
62 | int out_packet_size; | ||
63 | int in_n_analog; /* number of analog channels soundcard sends */ | ||
64 | int out_n_analog; /* number of analog channels soundcard receives */ | ||
65 | |||
66 | struct mutex stream_mutex; | ||
67 | u8 stream_state; /* one of STREAM_XXX (pcm.c) */ | ||
68 | u8 rate; /* one of PCM_RATE_XXX */ | ||
69 | wait_queue_head_t stream_wait_queue; | ||
70 | bool stream_wait_cond; | ||
71 | }; | ||
72 | |||
73 | int __devinit usb6fire_pcm_init(struct sfire_chip *chip); | ||
74 | void usb6fire_pcm_abort(struct sfire_chip *chip); | ||
75 | void usb6fire_pcm_destroy(struct sfire_chip *chip); | ||
76 | #endif /* USB6FIRE_PCM_H */ | ||
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig index 112984f4080f..97724d8fa9f6 100644 --- a/sound/usb/Kconfig +++ b/sound/usb/Kconfig | |||
@@ -62,6 +62,7 @@ config SND_USB_CAIAQ | |||
62 | * Native Instruments Audio 2 DJ | 62 | * Native Instruments Audio 2 DJ |
63 | * Native Instruments Audio 4 DJ | 63 | * Native Instruments Audio 4 DJ |
64 | * Native Instruments Audio 8 DJ | 64 | * Native Instruments Audio 8 DJ |
65 | * Native Instruments Traktor Audio 2 | ||
65 | * Native Instruments Guitar Rig Session I/O | 66 | * Native Instruments Guitar Rig Session I/O |
66 | * Native Instruments Guitar Rig mobile | 67 | * Native Instruments Guitar Rig mobile |
67 | * Native Instruments Traktor Kontrol X1 | 68 | * Native Instruments Traktor Kontrol X1 |
@@ -97,5 +98,21 @@ config SND_USB_US122L | |||
97 | To compile this driver as a module, choose M here: the module | 98 | To compile this driver as a module, choose M here: the module |
98 | will be called snd-usb-us122l. | 99 | will be called snd-usb-us122l. |
99 | 100 | ||
101 | config SND_USB_6FIRE | ||
102 | tristate "TerraTec DMX 6Fire USB" | ||
103 | depends on EXPERIMENTAL | ||
104 | select FW_LOADER | ||
105 | select SND_RAWMIDI | ||
106 | select SND_PCM | ||
107 | help | ||
108 | Say Y here to include support for TerraTec 6fire DMX USB interface. | ||
109 | |||
110 | You will need firmware files in order to be able to use the device | ||
111 | after it has been coldstarted. This driver currently does not support | ||
112 | firmware loading for all devices. If you own such a device, | ||
113 | you could start windows and let the windows driver upload | ||
114 | the firmware. As long as you do not unplug your device from power, | ||
115 | it should be usable. | ||
116 | |||
100 | endif # SND_USB | 117 | endif # SND_USB |
101 | 118 | ||
diff --git a/sound/usb/Makefile b/sound/usb/Makefile index 1e362bf8834f..cf9ed66445fa 100644 --- a/sound/usb/Makefile +++ b/sound/usb/Makefile | |||
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o | |||
23 | obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o | 23 | obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o |
24 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o | 24 | obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o |
25 | 25 | ||
26 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ | 26 | obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/ |
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c index 66eabafb1c24..d0d493ca28ae 100644 --- a/sound/usb/caiaq/audio.c +++ b/sound/usb/caiaq/audio.c | |||
@@ -805,6 +805,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev) | |||
805 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): | 805 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ): |
806 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): | 806 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): |
807 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): | 807 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): |
808 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2): | ||
808 | dev->samplerates |= SNDRV_PCM_RATE_88200; | 809 | dev->samplerates |= SNDRV_PCM_RATE_88200; |
809 | break; | 810 | break; |
810 | } | 811 | } |
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 6480c3283c05..45bc4a2dc6f0 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c | |||
@@ -46,6 +46,7 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," | |||
46 | "{Native Instruments, Audio 2 DJ}," | 46 | "{Native Instruments, Audio 2 DJ}," |
47 | "{Native Instruments, Audio 4 DJ}," | 47 | "{Native Instruments, Audio 4 DJ}," |
48 | "{Native Instruments, Audio 8 DJ}," | 48 | "{Native Instruments, Audio 8 DJ}," |
49 | "{Native Instruments, Traktor Audio 2}," | ||
49 | "{Native Instruments, Session I/O}," | 50 | "{Native Instruments, Session I/O}," |
50 | "{Native Instruments, GuitarRig mobile}" | 51 | "{Native Instruments, GuitarRig mobile}" |
51 | "{Native Instruments, Traktor Kontrol X1}" | 52 | "{Native Instruments, Traktor Kontrol X1}" |
@@ -140,6 +141,11 @@ static struct usb_device_id snd_usb_id_table[] = { | |||
140 | .idVendor = USB_VID_NATIVEINSTRUMENTS, | 141 | .idVendor = USB_VID_NATIVEINSTRUMENTS, |
141 | .idProduct = USB_PID_TRAKTORKONTROLS4 | 142 | .idProduct = USB_PID_TRAKTORKONTROLS4 |
142 | }, | 143 | }, |
144 | { | ||
145 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
146 | .idVendor = USB_VID_NATIVEINSTRUMENTS, | ||
147 | .idProduct = USB_PID_TRAKTORAUDIO2 | ||
148 | }, | ||
143 | { /* terminator */ } | 149 | { /* terminator */ } |
144 | }; | 150 | }; |
145 | 151 | ||
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h index e3d8a3efb35b..b2b310194ffa 100644 --- a/sound/usb/caiaq/device.h +++ b/sound/usb/caiaq/device.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #define USB_PID_GUITARRIGMOBILE 0x0d8d | 17 | #define USB_PID_GUITARRIGMOBILE 0x0d8d |
18 | #define USB_PID_TRAKTORKONTROLX1 0x2305 | 18 | #define USB_PID_TRAKTORKONTROLX1 0x2305 |
19 | #define USB_PID_TRAKTORKONTROLS4 0xbaff | 19 | #define USB_PID_TRAKTORKONTROLS4 0xbaff |
20 | #define USB_PID_TRAKTORAUDIO2 0x041d | ||
20 | 21 | ||
21 | #define EP1_BUFSIZE 64 | 22 | #define EP1_BUFSIZE 64 |
22 | #define EP4_BUFSIZE 512 | 23 | #define EP4_BUFSIZE 512 |
diff --git a/sound/usb/card.c b/sound/usb/card.c index c0f8270bc199..40722f8711ad 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
@@ -65,6 +65,7 @@ | |||
65 | #include "pcm.h" | 65 | #include "pcm.h" |
66 | #include "urb.h" | 66 | #include "urb.h" |
67 | #include "format.h" | 67 | #include "format.h" |
68 | #include "power.h" | ||
68 | 69 | ||
69 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); | 70 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); |
70 | MODULE_DESCRIPTION("USB Audio"); | 71 | MODULE_DESCRIPTION("USB Audio"); |
@@ -330,6 +331,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, | |||
330 | chip->setup = device_setup[idx]; | 331 | chip->setup = device_setup[idx]; |
331 | chip->nrpacks = nrpacks; | 332 | chip->nrpacks = nrpacks; |
332 | chip->async_unlink = async_unlink; | 333 | chip->async_unlink = async_unlink; |
334 | chip->probing = 1; | ||
333 | 335 | ||
334 | chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | 336 | chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), |
335 | le16_to_cpu(dev->descriptor.idProduct)); | 337 | le16_to_cpu(dev->descriptor.idProduct)); |
@@ -451,6 +453,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
451 | goto __error; | 453 | goto __error; |
452 | } | 454 | } |
453 | chip = usb_chip[i]; | 455 | chip = usb_chip[i]; |
456 | chip->probing = 1; | ||
454 | break; | 457 | break; |
455 | } | 458 | } |
456 | } | 459 | } |
@@ -466,6 +469,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
466 | goto __error; | 469 | goto __error; |
467 | } | 470 | } |
468 | snd_card_set_dev(chip->card, &intf->dev); | 471 | snd_card_set_dev(chip->card, &intf->dev); |
472 | chip->pm_intf = intf; | ||
469 | break; | 473 | break; |
470 | } | 474 | } |
471 | if (!chip) { | 475 | if (!chip) { |
@@ -505,6 +509,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev, | |||
505 | 509 | ||
506 | usb_chip[chip->index] = chip; | 510 | usb_chip[chip->index] = chip; |
507 | chip->num_interfaces++; | 511 | chip->num_interfaces++; |
512 | chip->probing = 0; | ||
508 | mutex_unlock(®ister_mutex); | 513 | mutex_unlock(®ister_mutex); |
509 | return chip; | 514 | return chip; |
510 | 515 | ||
@@ -581,29 +586,61 @@ static void usb_audio_disconnect(struct usb_interface *intf) | |||
581 | } | 586 | } |
582 | 587 | ||
583 | #ifdef CONFIG_PM | 588 | #ifdef CONFIG_PM |
589 | |||
590 | int snd_usb_autoresume(struct snd_usb_audio *chip) | ||
591 | { | ||
592 | int err = -ENODEV; | ||
593 | |||
594 | if (!chip->shutdown && !chip->probing) | ||
595 | err = usb_autopm_get_interface(chip->pm_intf); | ||
596 | |||
597 | return err; | ||
598 | } | ||
599 | |||
600 | void snd_usb_autosuspend(struct snd_usb_audio *chip) | ||
601 | { | ||
602 | if (!chip->shutdown && !chip->probing) | ||
603 | usb_autopm_put_interface(chip->pm_intf); | ||
604 | } | ||
605 | |||
584 | static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) | 606 | static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) |
585 | { | 607 | { |
586 | struct snd_usb_audio *chip = usb_get_intfdata(intf); | 608 | struct snd_usb_audio *chip = usb_get_intfdata(intf); |
587 | struct list_head *p; | 609 | struct list_head *p; |
588 | struct snd_usb_stream *as; | 610 | struct snd_usb_stream *as; |
611 | struct usb_mixer_interface *mixer; | ||
589 | 612 | ||
590 | if (chip == (void *)-1L) | 613 | if (chip == (void *)-1L) |
591 | return 0; | 614 | return 0; |
592 | 615 | ||
593 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); | 616 | if (!(message.event & PM_EVENT_AUTO)) { |
594 | if (!chip->num_suspended_intf++) { | 617 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot); |
595 | list_for_each(p, &chip->pcm_list) { | 618 | if (!chip->num_suspended_intf++) { |
596 | as = list_entry(p, struct snd_usb_stream, list); | 619 | list_for_each(p, &chip->pcm_list) { |
597 | snd_pcm_suspend_all(as->pcm); | 620 | as = list_entry(p, struct snd_usb_stream, list); |
598 | } | 621 | snd_pcm_suspend_all(as->pcm); |
622 | } | ||
623 | } | ||
624 | } else { | ||
625 | /* | ||
626 | * otherwise we keep the rest of the system in the dark | ||
627 | * to keep this transparent | ||
628 | */ | ||
629 | if (!chip->num_suspended_intf++) | ||
630 | chip->autosuspended = 1; | ||
599 | } | 631 | } |
600 | 632 | ||
633 | list_for_each_entry(mixer, &chip->mixer_list, list) | ||
634 | snd_usb_mixer_inactivate(mixer); | ||
635 | |||
601 | return 0; | 636 | return 0; |
602 | } | 637 | } |
603 | 638 | ||
604 | static int usb_audio_resume(struct usb_interface *intf) | 639 | static int usb_audio_resume(struct usb_interface *intf) |
605 | { | 640 | { |
606 | struct snd_usb_audio *chip = usb_get_intfdata(intf); | 641 | struct snd_usb_audio *chip = usb_get_intfdata(intf); |
642 | struct usb_mixer_interface *mixer; | ||
643 | int err = 0; | ||
607 | 644 | ||
608 | if (chip == (void *)-1L) | 645 | if (chip == (void *)-1L) |
609 | return 0; | 646 | return 0; |
@@ -611,12 +648,20 @@ static int usb_audio_resume(struct usb_interface *intf) | |||
611 | return 0; | 648 | return 0; |
612 | /* | 649 | /* |
613 | * ALSA leaves material resumption to user space | 650 | * ALSA leaves material resumption to user space |
614 | * we just notify | 651 | * we just notify and restart the mixers |
615 | */ | 652 | */ |
653 | list_for_each_entry(mixer, &chip->mixer_list, list) { | ||
654 | err = snd_usb_mixer_activate(mixer); | ||
655 | if (err < 0) | ||
656 | goto err_out; | ||
657 | } | ||
616 | 658 | ||
617 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); | 659 | if (!chip->autosuspended) |
660 | snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0); | ||
661 | chip->autosuspended = 0; | ||
618 | 662 | ||
619 | return 0; | 663 | err_out: |
664 | return err; | ||
620 | } | 665 | } |
621 | #else | 666 | #else |
622 | #define usb_audio_suspend NULL | 667 | #define usb_audio_suspend NULL |
@@ -644,6 +689,7 @@ static struct usb_driver usb_audio_driver = { | |||
644 | .suspend = usb_audio_suspend, | 689 | .suspend = usb_audio_suspend, |
645 | .resume = usb_audio_resume, | 690 | .resume = usb_audio_resume, |
646 | .id_table = usb_audio_ids, | 691 | .id_table = usb_audio_ids, |
692 | .supports_autosuspend = 1, | ||
647 | }; | 693 | }; |
648 | 694 | ||
649 | static int __init snd_usb_audio_init(void) | 695 | static int __init snd_usb_audio_init(void) |
diff --git a/sound/usb/midi.c b/sound/usb/midi.c index db2dc5ffe6dd..b4b39c0b6c9e 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <sound/asequencer.h> | 54 | #include <sound/asequencer.h> |
55 | #include "usbaudio.h" | 55 | #include "usbaudio.h" |
56 | #include "midi.h" | 56 | #include "midi.h" |
57 | #include "power.h" | ||
57 | #include "helper.h" | 58 | #include "helper.h" |
58 | 59 | ||
59 | /* | 60 | /* |
@@ -1044,6 +1045,7 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) | |||
1044 | struct snd_usb_midi* umidi = substream->rmidi->private_data; | 1045 | struct snd_usb_midi* umidi = substream->rmidi->private_data; |
1045 | struct usbmidi_out_port* port = NULL; | 1046 | struct usbmidi_out_port* port = NULL; |
1046 | int i, j; | 1047 | int i, j; |
1048 | int err; | ||
1047 | 1049 | ||
1048 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) | 1050 | for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) |
1049 | if (umidi->endpoints[i].out) | 1051 | if (umidi->endpoints[i].out) |
@@ -1056,6 +1058,9 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) | |||
1056 | snd_BUG(); | 1058 | snd_BUG(); |
1057 | return -ENXIO; | 1059 | return -ENXIO; |
1058 | } | 1060 | } |
1061 | err = usb_autopm_get_interface(umidi->iface); | ||
1062 | if (err < 0) | ||
1063 | return -EIO; | ||
1059 | substream->runtime->private_data = port; | 1064 | substream->runtime->private_data = port; |
1060 | port->state = STATE_UNKNOWN; | 1065 | port->state = STATE_UNKNOWN; |
1061 | substream_open(substream, 1); | 1066 | substream_open(substream, 1); |
@@ -1064,7 +1069,10 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) | |||
1064 | 1069 | ||
1065 | static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) | 1070 | static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) |
1066 | { | 1071 | { |
1072 | struct snd_usb_midi* umidi = substream->rmidi->private_data; | ||
1073 | |||
1067 | substream_open(substream, 0); | 1074 | substream_open(substream, 0); |
1075 | usb_autopm_put_interface(umidi->iface); | ||
1068 | return 0; | 1076 | return 0; |
1069 | } | 1077 | } |
1070 | 1078 | ||
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 85af6051b52d..5e4775716607 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #include "mixer.h" | 61 | #include "mixer.h" |
62 | #include "helper.h" | 62 | #include "helper.h" |
63 | #include "mixer_quirks.h" | 63 | #include "mixer_quirks.h" |
64 | #include "power.h" | ||
64 | 65 | ||
65 | #define MAX_ID_ELEMS 256 | 66 | #define MAX_ID_ELEMS 256 |
66 | 67 | ||
@@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v | |||
295 | unsigned char buf[2]; | 296 | unsigned char buf[2]; |
296 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 297 | int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
297 | int timeout = 10; | 298 | int timeout = 10; |
299 | int err; | ||
298 | 300 | ||
301 | err = snd_usb_autoresume(cval->mixer->chip); | ||
302 | if (err < 0) | ||
303 | return -EIO; | ||
299 | while (timeout-- > 0) { | 304 | while (timeout-- > 0) { |
300 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, | 305 | if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, |
301 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 306 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
302 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 307 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
303 | buf, val_len, 100) >= val_len) { | 308 | buf, val_len, 100) >= val_len) { |
304 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); | 309 | *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); |
310 | snd_usb_autosuspend(cval->mixer->chip); | ||
305 | return 0; | 311 | return 0; |
306 | } | 312 | } |
307 | } | 313 | } |
314 | snd_usb_autosuspend(cval->mixer->chip); | ||
308 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 315 | snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
309 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 316 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
310 | return -EINVAL; | 317 | return -EINVAL; |
@@ -328,12 +335,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v | |||
328 | 335 | ||
329 | memset(buf, 0, sizeof(buf)); | 336 | memset(buf, 0, sizeof(buf)); |
330 | 337 | ||
338 | ret = snd_usb_autoresume(chip) ? -EIO : 0; | ||
339 | if (ret) | ||
340 | goto error; | ||
341 | |||
331 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, | 342 | ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, |
332 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, | 343 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, |
333 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 344 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
334 | buf, size, 1000); | 345 | buf, size, 1000); |
346 | snd_usb_autosuspend(chip); | ||
335 | 347 | ||
336 | if (ret < 0) { | 348 | if (ret < 0) { |
349 | error: | ||
337 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", | 350 | snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", |
338 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); | 351 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); |
339 | return ret; | 352 | return ret; |
@@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
413 | { | 426 | { |
414 | struct snd_usb_audio *chip = cval->mixer->chip; | 427 | struct snd_usb_audio *chip = cval->mixer->chip; |
415 | unsigned char buf[2]; | 428 | unsigned char buf[2]; |
416 | int val_len, timeout = 10; | 429 | int val_len, err, timeout = 10; |
417 | 430 | ||
418 | if (cval->mixer->protocol == UAC_VERSION_1) { | 431 | if (cval->mixer->protocol == UAC_VERSION_1) { |
419 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; | 432 | val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; |
@@ -433,13 +446,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | |||
433 | value_set = convert_bytes_value(cval, value_set); | 446 | value_set = convert_bytes_value(cval, value_set); |
434 | buf[0] = value_set & 0xff; | 447 | buf[0] = value_set & 0xff; |
435 | buf[1] = (value_set >> 8) & 0xff; | 448 | buf[1] = (value_set >> 8) & 0xff; |
449 | err = snd_usb_autoresume(chip); | ||
450 | if (err < 0) | ||
451 | return -EIO; | ||
436 | while (timeout-- > 0) | 452 | while (timeout-- > 0) |
437 | if (snd_usb_ctl_msg(chip->dev, | 453 | if (snd_usb_ctl_msg(chip->dev, |
438 | usb_sndctrlpipe(chip->dev, 0), request, | 454 | usb_sndctrlpipe(chip->dev, 0), request, |
439 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, | 455 | USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, |
440 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), | 456 | validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), |
441 | buf, val_len, 100) >= 0) | 457 | buf, val_len, 100) >= 0) { |
458 | snd_usb_autosuspend(chip); | ||
442 | return 0; | 459 | return 0; |
460 | } | ||
461 | snd_usb_autosuspend(chip); | ||
443 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", | 462 | snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", |
444 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); | 463 | request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); |
445 | return -EINVAL; | 464 | return -EINVAL; |
@@ -987,6 +1006,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
987 | struct snd_kcontrol *kctl; | 1006 | struct snd_kcontrol *kctl; |
988 | struct usb_mixer_elem_info *cval; | 1007 | struct usb_mixer_elem_info *cval; |
989 | const struct usbmix_name_map *map; | 1008 | const struct usbmix_name_map *map; |
1009 | unsigned int range; | ||
990 | 1010 | ||
991 | control++; /* change from zero-based to 1-based value */ | 1011 | control++; /* change from zero-based to 1-based value */ |
992 | 1012 | ||
@@ -1121,6 +1141,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1121 | } | 1141 | } |
1122 | break; | 1142 | break; |
1123 | 1143 | ||
1144 | case USB_ID(0x046d, 0x0808): | ||
1124 | case USB_ID(0x046d, 0x0809): | 1145 | case USB_ID(0x046d, 0x0809): |
1125 | case USB_ID(0x046d, 0x0991): | 1146 | case USB_ID(0x046d, 0x0991): |
1126 | /* Most audio usb devices lie about volume resolution. | 1147 | /* Most audio usb devices lie about volume resolution. |
@@ -1136,6 +1157,21 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, | |||
1136 | 1157 | ||
1137 | } | 1158 | } |
1138 | 1159 | ||
1160 | range = (cval->max - cval->min) / cval->res; | ||
1161 | /* Are there devices with volume range more than 255? I use a bit more | ||
1162 | * to be sure. 384 is a resolution magic number found on Logitech | ||
1163 | * devices. It will definitively catch all buggy Logitech devices. | ||
1164 | */ | ||
1165 | if (range > 384) { | ||
1166 | snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big " | ||
1167 | "volume range (=%u), cval->res is probably wrong.", | ||
1168 | range); | ||
1169 | snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, " | ||
1170 | "val = %d/%d/%d", cval->id, | ||
1171 | kctl->id.name, cval->channels, | ||
1172 | cval->min, cval->max, cval->res); | ||
1173 | } | ||
1174 | |||
1139 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", | 1175 | snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", |
1140 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); | 1176 | cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); |
1141 | add_control_to_empty(state, kctl); | 1177 | add_control_to_empty(state, kctl); |
@@ -2058,8 +2094,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb) | |||
2058 | { | 2094 | { |
2059 | struct usb_mixer_interface *mixer = urb->context; | 2095 | struct usb_mixer_interface *mixer = urb->context; |
2060 | int len = urb->actual_length; | 2096 | int len = urb->actual_length; |
2097 | int ustatus = urb->status; | ||
2061 | 2098 | ||
2062 | if (urb->status != 0) | 2099 | if (ustatus != 0) |
2063 | goto requeue; | 2100 | goto requeue; |
2064 | 2101 | ||
2065 | if (mixer->protocol == UAC_VERSION_1) { | 2102 | if (mixer->protocol == UAC_VERSION_1) { |
@@ -2100,12 +2137,32 @@ static void snd_usb_mixer_interrupt(struct urb *urb) | |||
2100 | } | 2137 | } |
2101 | 2138 | ||
2102 | requeue: | 2139 | requeue: |
2103 | if (urb->status != -ENOENT && urb->status != -ECONNRESET) { | 2140 | if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) { |
2104 | urb->dev = mixer->chip->dev; | 2141 | urb->dev = mixer->chip->dev; |
2105 | usb_submit_urb(urb, GFP_ATOMIC); | 2142 | usb_submit_urb(urb, GFP_ATOMIC); |
2106 | } | 2143 | } |
2107 | } | 2144 | } |
2108 | 2145 | ||
2146 | /* stop any bus activity of a mixer */ | ||
2147 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer) | ||
2148 | { | ||
2149 | usb_kill_urb(mixer->urb); | ||
2150 | usb_kill_urb(mixer->rc_urb); | ||
2151 | } | ||
2152 | |||
2153 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer) | ||
2154 | { | ||
2155 | int err; | ||
2156 | |||
2157 | if (mixer->urb) { | ||
2158 | err = usb_submit_urb(mixer->urb, GFP_NOIO); | ||
2159 | if (err < 0) | ||
2160 | return err; | ||
2161 | } | ||
2162 | |||
2163 | return 0; | ||
2164 | } | ||
2165 | |||
2109 | /* create the handler for the optional status interrupt endpoint */ | 2166 | /* create the handler for the optional status interrupt endpoint */ |
2110 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) | 2167 | static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer) |
2111 | { | 2168 | { |
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 26c636c5c93a..b4a2c8165e4b 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h | |||
@@ -52,5 +52,7 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid); | |||
52 | 52 | ||
53 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, | 53 | int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, |
54 | int request, int validx, int value_set); | 54 | int request, int validx, int value_set); |
55 | void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); | ||
56 | int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); | ||
55 | 57 | ||
56 | #endif /* __USBMIXER_H */ | 58 | #endif /* __USBMIXER_H */ |
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 782f741cd00a..73dcc8256bc0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -346,6 +346,141 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) | |||
346 | return 0; | 346 | return 0; |
347 | } | 347 | } |
348 | 348 | ||
349 | /* Native Instruments device quirks */ | ||
350 | |||
351 | #define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) | ||
352 | |||
353 | static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, | ||
354 | struct snd_ctl_elem_value *ucontrol) | ||
355 | { | ||
356 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
357 | struct usb_device *dev = mixer->chip->dev; | ||
358 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | ||
359 | u16 wIndex = kcontrol->private_value & 0xffff; | ||
360 | u8 tmp; | ||
361 | |||
362 | int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | ||
363 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
364 | 0, cpu_to_le16(wIndex), | ||
365 | &tmp, sizeof(tmp), 1000); | ||
366 | |||
367 | if (ret < 0) { | ||
368 | snd_printk(KERN_ERR | ||
369 | "unable to issue vendor read request (ret = %d)", ret); | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | ucontrol->value.integer.value[0] = tmp; | ||
374 | |||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, | ||
379 | struct snd_ctl_elem_value *ucontrol) | ||
380 | { | ||
381 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
382 | struct usb_device *dev = mixer->chip->dev; | ||
383 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | ||
384 | u16 wIndex = kcontrol->private_value & 0xffff; | ||
385 | u16 wValue = ucontrol->value.integer.value[0]; | ||
386 | |||
387 | int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | ||
388 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
389 | cpu_to_le16(wValue), cpu_to_le16(wIndex), | ||
390 | NULL, 0, 1000); | ||
391 | |||
392 | if (ret < 0) { | ||
393 | snd_printk(KERN_ERR | ||
394 | "unable to issue vendor write request (ret = %d)", ret); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { | ||
402 | { | ||
403 | .name = "Direct Thru Channel A", | ||
404 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), | ||
405 | }, | ||
406 | { | ||
407 | .name = "Direct Thru Channel B", | ||
408 | .private_value = _MAKE_NI_CONTROL(0x01, 0x05), | ||
409 | }, | ||
410 | { | ||
411 | .name = "Phono Input Channel A", | ||
412 | .private_value = _MAKE_NI_CONTROL(0x02, 0x03), | ||
413 | }, | ||
414 | { | ||
415 | .name = "Phono Input Channel B", | ||
416 | .private_value = _MAKE_NI_CONTROL(0x02, 0x05), | ||
417 | }, | ||
418 | }; | ||
419 | |||
420 | static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = { | ||
421 | { | ||
422 | .name = "Direct Thru Channel A", | ||
423 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), | ||
424 | }, | ||
425 | { | ||
426 | .name = "Direct Thru Channel B", | ||
427 | .private_value = _MAKE_NI_CONTROL(0x01, 0x05), | ||
428 | }, | ||
429 | { | ||
430 | .name = "Direct Thru Channel C", | ||
431 | .private_value = _MAKE_NI_CONTROL(0x01, 0x07), | ||
432 | }, | ||
433 | { | ||
434 | .name = "Direct Thru Channel D", | ||
435 | .private_value = _MAKE_NI_CONTROL(0x01, 0x09), | ||
436 | }, | ||
437 | { | ||
438 | .name = "Phono Input Channel A", | ||
439 | .private_value = _MAKE_NI_CONTROL(0x02, 0x03), | ||
440 | }, | ||
441 | { | ||
442 | .name = "Phono Input Channel B", | ||
443 | .private_value = _MAKE_NI_CONTROL(0x02, 0x05), | ||
444 | }, | ||
445 | { | ||
446 | .name = "Phono Input Channel C", | ||
447 | .private_value = _MAKE_NI_CONTROL(0x02, 0x07), | ||
448 | }, | ||
449 | { | ||
450 | .name = "Phono Input Channel D", | ||
451 | .private_value = _MAKE_NI_CONTROL(0x02, 0x09), | ||
452 | }, | ||
453 | }; | ||
454 | |||
455 | static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, | ||
456 | const struct snd_kcontrol_new *kc, | ||
457 | unsigned int count) | ||
458 | { | ||
459 | int i, err = 0; | ||
460 | struct snd_kcontrol_new template = { | ||
461 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
462 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
463 | .get = snd_nativeinstruments_control_get, | ||
464 | .put = snd_nativeinstruments_control_put, | ||
465 | .info = snd_ctl_boolean_mono_info, | ||
466 | }; | ||
467 | |||
468 | for (i = 0; i < count; i++) { | ||
469 | struct snd_kcontrol *c; | ||
470 | |||
471 | template.name = kc[i].name; | ||
472 | template.private_value = kc[i].private_value; | ||
473 | |||
474 | c = snd_ctl_new1(&template, mixer); | ||
475 | err = snd_ctl_add(mixer->chip->card, c); | ||
476 | |||
477 | if (err < 0) | ||
478 | break; | ||
479 | } | ||
480 | |||
481 | return err; | ||
482 | } | ||
483 | |||
349 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | 484 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, |
350 | unsigned char samplerate_id) | 485 | unsigned char samplerate_id) |
351 | { | 486 | { |
@@ -367,31 +502,44 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | |||
367 | 502 | ||
368 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 503 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
369 | { | 504 | { |
370 | int err; | 505 | int err = 0; |
371 | struct snd_info_entry *entry; | 506 | struct snd_info_entry *entry; |
372 | 507 | ||
373 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) | 508 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) |
374 | return err; | 509 | return err; |
375 | 510 | ||
376 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || | 511 | switch (mixer->chip->usb_id) { |
377 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || | 512 | case USB_ID(0x041e, 0x3020): |
378 | mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || | 513 | case USB_ID(0x041e, 0x3040): |
379 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { | 514 | case USB_ID(0x041e, 0x3042): |
380 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 515 | case USB_ID(0x041e, 0x3048): |
381 | return err; | 516 | err = snd_audigy2nx_controls_create(mixer); |
517 | if (err < 0) | ||
518 | break; | ||
382 | if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) | 519 | if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) |
383 | snd_info_set_text_ops(entry, mixer, | 520 | snd_info_set_text_ops(entry, mixer, |
384 | snd_audigy2nx_proc_read); | 521 | snd_audigy2nx_proc_read); |
385 | } | 522 | break; |
386 | 523 | ||
387 | if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) || | 524 | case USB_ID(0x0b05, 0x1739): |
388 | mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) { | 525 | case USB_ID(0x0b05, 0x1743): |
389 | err = snd_xonar_u1_controls_create(mixer); | 526 | err = snd_xonar_u1_controls_create(mixer); |
390 | if (err < 0) | 527 | break; |
391 | return err; | 528 | |
529 | case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ | ||
530 | err = snd_nativeinstruments_create_mixer(mixer, | ||
531 | snd_nativeinstruments_ta6_mixers, | ||
532 | ARRAY_SIZE(snd_nativeinstruments_ta6_mixers)); | ||
533 | break; | ||
534 | |||
535 | case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */ | ||
536 | err = snd_nativeinstruments_create_mixer(mixer, | ||
537 | snd_nativeinstruments_ta10_mixers, | ||
538 | ARRAY_SIZE(snd_nativeinstruments_ta10_mixers)); | ||
539 | break; | ||
392 | } | 540 | } |
393 | 541 | ||
394 | return 0; | 542 | return err; |
395 | } | 543 | } |
396 | 544 | ||
397 | void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, | 545 | void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e3f680526cb5..b8dcbf407bbb 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "helper.h" | 32 | #include "helper.h" |
33 | #include "pcm.h" | 33 | #include "pcm.h" |
34 | #include "clock.h" | 34 | #include "clock.h" |
35 | #include "power.h" | ||
35 | 36 | ||
36 | /* | 37 | /* |
37 | * return the current pcm pointer. just based on the hwptr_done value. | 38 | * return the current pcm pointer. just based on the hwptr_done value. |
@@ -739,6 +740,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
739 | pt = 125 * (1 << fp->datainterval); | 740 | pt = 125 * (1 << fp->datainterval); |
740 | ptmin = min(ptmin, pt); | 741 | ptmin = min(ptmin, pt); |
741 | } | 742 | } |
743 | err = snd_usb_autoresume(subs->stream->chip); | ||
744 | if (err < 0) | ||
745 | return err; | ||
742 | 746 | ||
743 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; | 747 | param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; |
744 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) | 748 | if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) |
@@ -756,21 +760,21 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
756 | SNDRV_PCM_HW_PARAM_CHANNELS, | 760 | SNDRV_PCM_HW_PARAM_CHANNELS, |
757 | param_period_time_if_needed, | 761 | param_period_time_if_needed, |
758 | -1)) < 0) | 762 | -1)) < 0) |
759 | return err; | 763 | goto rep_err; |
760 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, | 764 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, |
761 | hw_rule_channels, subs, | 765 | hw_rule_channels, subs, |
762 | SNDRV_PCM_HW_PARAM_FORMAT, | 766 | SNDRV_PCM_HW_PARAM_FORMAT, |
763 | SNDRV_PCM_HW_PARAM_RATE, | 767 | SNDRV_PCM_HW_PARAM_RATE, |
764 | param_period_time_if_needed, | 768 | param_period_time_if_needed, |
765 | -1)) < 0) | 769 | -1)) < 0) |
766 | return err; | 770 | goto rep_err; |
767 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, | 771 | if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, |
768 | hw_rule_format, subs, | 772 | hw_rule_format, subs, |
769 | SNDRV_PCM_HW_PARAM_RATE, | 773 | SNDRV_PCM_HW_PARAM_RATE, |
770 | SNDRV_PCM_HW_PARAM_CHANNELS, | 774 | SNDRV_PCM_HW_PARAM_CHANNELS, |
771 | param_period_time_if_needed, | 775 | param_period_time_if_needed, |
772 | -1)) < 0) | 776 | -1)) < 0) |
773 | return err; | 777 | goto rep_err; |
774 | if (param_period_time_if_needed >= 0) { | 778 | if (param_period_time_if_needed >= 0) { |
775 | err = snd_pcm_hw_rule_add(runtime, 0, | 779 | err = snd_pcm_hw_rule_add(runtime, 0, |
776 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, | 780 | SNDRV_PCM_HW_PARAM_PERIOD_TIME, |
@@ -780,11 +784,15 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre | |||
780 | SNDRV_PCM_HW_PARAM_RATE, | 784 | SNDRV_PCM_HW_PARAM_RATE, |
781 | -1); | 785 | -1); |
782 | if (err < 0) | 786 | if (err < 0) |
783 | return err; | 787 | goto rep_err; |
784 | } | 788 | } |
785 | if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) | 789 | if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) |
786 | return err; | 790 | goto rep_err; |
787 | return 0; | 791 | return 0; |
792 | |||
793 | rep_err: | ||
794 | snd_usb_autosuspend(subs->stream->chip); | ||
795 | return err; | ||
788 | } | 796 | } |
789 | 797 | ||
790 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | 798 | static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) |
@@ -798,6 +806,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction) | |||
798 | runtime->hw = snd_usb_hardware; | 806 | runtime->hw = snd_usb_hardware; |
799 | runtime->private_data = subs; | 807 | runtime->private_data = subs; |
800 | subs->pcm_substream = substream; | 808 | subs->pcm_substream = substream; |
809 | /* runtime PM is also done there */ | ||
801 | return setup_hw_info(runtime, subs); | 810 | return setup_hw_info(runtime, subs); |
802 | } | 811 | } |
803 | 812 | ||
@@ -811,6 +820,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction) | |||
811 | subs->interface = -1; | 820 | subs->interface = -1; |
812 | } | 821 | } |
813 | subs->pcm_substream = NULL; | 822 | subs->pcm_substream = NULL; |
823 | snd_usb_autosuspend(subs->stream->chip); | ||
814 | return 0; | 824 | return 0; |
815 | } | 825 | } |
816 | 826 | ||
diff --git a/sound/usb/power.h b/sound/usb/power.h new file mode 100644 index 000000000000..48ee51dcb71e --- /dev/null +++ b/sound/usb/power.h | |||
@@ -0,0 +1,17 @@ | |||
1 | #ifndef __USBAUDIO_POWER_H | ||
2 | #define __USBAUDIO_POWER_H | ||
3 | |||
4 | #ifdef CONFIG_PM | ||
5 | int snd_usb_autoresume(struct snd_usb_audio *chip); | ||
6 | void snd_usb_autosuspend(struct snd_usb_audio *chip); | ||
7 | #else | ||
8 | static inline int snd_usb_autoresume(struct snd_usb_audio *chip) | ||
9 | { | ||
10 | return 0; | ||
11 | } | ||
12 | static inline void snd_usb_autosuspend(struct snd_usb_audio *chip) | ||
13 | { | ||
14 | } | ||
15 | #endif | ||
16 | |||
17 | #endif /* __USBAUDIO_POWER_H */ | ||
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 921a86fd9884..c0dcfca9b5b5 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -2290,6 +2290,20 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
2290 | } | 2290 | } |
2291 | }, | 2291 | }, |
2292 | 2292 | ||
2293 | /* Native Instruments MK2 series */ | ||
2294 | { | ||
2295 | /* Traktor Audio 6 */ | ||
2296 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
2297 | .idVendor = 0x17cc, | ||
2298 | .idProduct = 0x1010, | ||
2299 | }, | ||
2300 | { | ||
2301 | /* Traktor Audio 10 */ | ||
2302 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE, | ||
2303 | .idVendor = 0x17cc, | ||
2304 | .idProduct = 0x1020, | ||
2305 | }, | ||
2306 | |||
2293 | /* Miditech devices */ | 2307 | /* Miditech devices */ |
2294 | { | 2308 | { |
2295 | USB_DEVICE(0x4752, 0x0011), | 2309 | USB_DEVICE(0x4752, 0x0011), |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index e314cdb85003..355759bad581 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -425,6 +425,34 @@ static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev) | |||
425 | } | 425 | } |
426 | 426 | ||
427 | /* | 427 | /* |
428 | * Some sound cards from Native Instruments are in fact compliant to the USB | ||
429 | * audio standard of version 2 and other approved USB standards, even though | ||
430 | * they come up as vendor-specific device when first connected. | ||
431 | * | ||
432 | * However, they can be told to come up with a new set of descriptors | ||
433 | * upon their next enumeration, and the interfaces announced by the new | ||
434 | * descriptors will then be handled by the kernel's class drivers. As the | ||
435 | * product ID will also change, no further checks are required. | ||
436 | */ | ||
437 | |||
438 | static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev) | ||
439 | { | ||
440 | int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
441 | 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
442 | cpu_to_le16(1), 0, NULL, 0, 1000); | ||
443 | |||
444 | if (ret < 0) | ||
445 | return ret; | ||
446 | |||
447 | usb_reset_device(dev); | ||
448 | |||
449 | /* return -EAGAIN, so the creation of an audio interface for this | ||
450 | * temporary device is aborted. The device will reconnect with a | ||
451 | * new product ID */ | ||
452 | return -EAGAIN; | ||
453 | } | ||
454 | |||
455 | /* | ||
428 | * Setup quirks | 456 | * Setup quirks |
429 | */ | 457 | */ |
430 | #define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */ | 458 | #define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */ |
@@ -489,27 +517,33 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, | |||
489 | u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), | 517 | u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor), |
490 | le16_to_cpu(dev->descriptor.idProduct)); | 518 | le16_to_cpu(dev->descriptor.idProduct)); |
491 | 519 | ||
492 | /* SB Extigy needs special boot-up sequence */ | 520 | switch (id) { |
493 | /* if more models come, this will go to the quirk list. */ | 521 | case USB_ID(0x041e, 0x3000): |
494 | if (id == USB_ID(0x041e, 0x3000)) | 522 | /* SB Extigy needs special boot-up sequence */ |
523 | /* if more models come, this will go to the quirk list. */ | ||
495 | return snd_usb_extigy_boot_quirk(dev, intf); | 524 | return snd_usb_extigy_boot_quirk(dev, intf); |
496 | 525 | ||
497 | /* SB Audigy 2 NX needs its own boot-up magic, too */ | 526 | case USB_ID(0x041e, 0x3020): |
498 | if (id == USB_ID(0x041e, 0x3020)) | 527 | /* SB Audigy 2 NX needs its own boot-up magic, too */ |
499 | return snd_usb_audigy2nx_boot_quirk(dev); | 528 | return snd_usb_audigy2nx_boot_quirk(dev); |
500 | 529 | ||
501 | /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */ | 530 | case USB_ID(0x10f5, 0x0200): |
502 | if (id == USB_ID(0x10f5, 0x0200)) | 531 | /* C-Media CM106 / Turtle Beach Audio Advantage Roadie */ |
503 | return snd_usb_cm106_boot_quirk(dev); | 532 | return snd_usb_cm106_boot_quirk(dev); |
504 | 533 | ||
505 | /* C-Media CM6206 / CM106-Like Sound Device */ | 534 | case USB_ID(0x0d8c, 0x0102): |
506 | if (id == USB_ID(0x0d8c, 0x0102)) | 535 | /* C-Media CM6206 / CM106-Like Sound Device */ |
507 | return snd_usb_cm6206_boot_quirk(dev); | 536 | return snd_usb_cm6206_boot_quirk(dev); |
508 | 537 | ||
509 | /* Access Music VirusTI Desktop */ | 538 | case USB_ID(0x133e, 0x0815): |
510 | if (id == USB_ID(0x133e, 0x0815)) | 539 | /* Access Music VirusTI Desktop */ |
511 | return snd_usb_accessmusic_boot_quirk(dev); | 540 | return snd_usb_accessmusic_boot_quirk(dev); |
512 | 541 | ||
542 | case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ | ||
543 | case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ | ||
544 | return snd_usb_nativeinstruments_boot_quirk(dev); | ||
545 | } | ||
546 | |||
513 | return 0; | 547 | return 0; |
514 | } | 548 | } |
515 | 549 | ||
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 6e66fffe87f5..32f2a97f2f14 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h | |||
@@ -34,10 +34,14 @@ struct snd_usb_audio { | |||
34 | int index; | 34 | int index; |
35 | struct usb_device *dev; | 35 | struct usb_device *dev; |
36 | struct snd_card *card; | 36 | struct snd_card *card; |
37 | struct usb_interface *pm_intf; | ||
37 | u32 usb_id; | 38 | u32 usb_id; |
38 | int shutdown; | ||
39 | struct mutex shutdown_mutex; | 39 | struct mutex shutdown_mutex; |
40 | unsigned int shutdown:1; | ||
41 | unsigned int probing:1; | ||
42 | unsigned int autosuspended:1; | ||
40 | unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ | 43 | unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */ |
44 | |||
41 | int num_interfaces; | 45 | int num_interfaces; |
42 | int num_suspended_intf; | 46 | int num_suspended_intf; |
43 | 47 | ||