diff options
-rw-r--r-- | arch/ppc/platforms/pmac_feature.c | 4 | ||||
-rw-r--r-- | arch/ppc64/kernel/pmac_feature.c | 29 | ||||
-rw-r--r-- | include/asm-ppc/dbdma.h | 2 | ||||
-rw-r--r-- | include/asm-ppc/keylargo.h | 5 | ||||
-rw-r--r-- | sound/ppc/beep.c | 15 | ||||
-rw-r--r-- | sound/ppc/pmac.c | 177 | ||||
-rw-r--r-- | sound/ppc/pmac.h | 6 | ||||
-rw-r--r-- | sound/ppc/tumbler.c | 259 |
8 files changed, 360 insertions, 137 deletions
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c index 24b42fd9e014..46cbf36722db 100644 --- a/arch/ppc/platforms/pmac_feature.c +++ b/arch/ppc/platforms/pmac_feature.c | |||
@@ -74,8 +74,7 @@ static DEFINE_SPINLOCK(feature_lock __pmacdata); | |||
74 | */ | 74 | */ |
75 | struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; | 75 | struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; |
76 | 76 | ||
77 | struct macio_chip* __pmac | 77 | struct macio_chip* __pmac macio_find(struct device_node* child, int type) |
78 | macio_find(struct device_node* child, int type) | ||
79 | { | 78 | { |
80 | while(child) { | 79 | while(child) { |
81 | int i; | 80 | int i; |
@@ -88,6 +87,7 @@ macio_find(struct device_node* child, int type) | |||
88 | } | 87 | } |
89 | return NULL; | 88 | return NULL; |
90 | } | 89 | } |
90 | EXPORT_SYMBOL_GPL(macio_find); | ||
91 | 91 | ||
92 | static const char* macio_names[] __pmacdata = | 92 | static const char* macio_names[] __pmacdata = |
93 | { | 93 | { |
diff --git a/arch/ppc64/kernel/pmac_feature.c b/arch/ppc64/kernel/pmac_feature.c index 086abc1bcca1..98ed2bccab1a 100644 --- a/arch/ppc64/kernel/pmac_feature.c +++ b/arch/ppc64/kernel/pmac_feature.c | |||
@@ -64,8 +64,7 @@ static DEFINE_SPINLOCK(feature_lock __pmacdata); | |||
64 | */ | 64 | */ |
65 | struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; | 65 | struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; |
66 | 66 | ||
67 | struct macio_chip* __pmac | 67 | struct macio_chip* __pmac macio_find(struct device_node* child, int type) |
68 | macio_find(struct device_node* child, int type) | ||
69 | { | 68 | { |
70 | while(child) { | 69 | while(child) { |
71 | int i; | 70 | int i; |
@@ -78,6 +77,7 @@ macio_find(struct device_node* child, int type) | |||
78 | } | 77 | } |
79 | return NULL; | 78 | return NULL; |
80 | } | 79 | } |
80 | EXPORT_SYMBOL_GPL(macio_find); | ||
81 | 81 | ||
82 | static const char* macio_names[] __pmacdata = | 82 | static const char* macio_names[] __pmacdata = |
83 | { | 83 | { |
@@ -250,6 +250,30 @@ static long __pmac g5_eth_phy_reset(struct device_node* node, long param, long v | |||
250 | return 0; | 250 | return 0; |
251 | } | 251 | } |
252 | 252 | ||
253 | static long __pmac g5_i2s_enable(struct device_node *node, long param, long value) | ||
254 | { | ||
255 | /* Very crude implementation for now */ | ||
256 | struct macio_chip* macio = &macio_chips[0]; | ||
257 | unsigned long flags; | ||
258 | |||
259 | if (value == 0) | ||
260 | return 0; /* don't disable yet */ | ||
261 | |||
262 | LOCK(flags); | ||
263 | MACIO_BIS(KEYLARGO_FCR3, KL3_CLK45_ENABLE | KL3_CLK49_ENABLE | | ||
264 | KL3_I2S0_CLK18_ENABLE); | ||
265 | udelay(10); | ||
266 | MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_I2S0_CELL_ENABLE | | ||
267 | K2_FCR1_I2S0_CLK_ENABLE_BIT | K2_FCR1_I2S0_ENABLE); | ||
268 | udelay(10); | ||
269 | MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_I2S0_RESET); | ||
270 | UNLOCK(flags); | ||
271 | udelay(10); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | |||
253 | #ifdef CONFIG_SMP | 277 | #ifdef CONFIG_SMP |
254 | static long __pmac g5_reset_cpu(struct device_node* node, long param, long value) | 278 | static long __pmac g5_reset_cpu(struct device_node* node, long param, long value) |
255 | { | 279 | { |
@@ -337,6 +361,7 @@ static struct feature_table_entry g5_features[] __pmacdata = { | |||
337 | { PMAC_FTR_READ_GPIO, g5_read_gpio }, | 361 | { PMAC_FTR_READ_GPIO, g5_read_gpio }, |
338 | { PMAC_FTR_WRITE_GPIO, g5_write_gpio }, | 362 | { PMAC_FTR_WRITE_GPIO, g5_write_gpio }, |
339 | { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset }, | 363 | { PMAC_FTR_GMAC_PHY_RESET, g5_eth_phy_reset }, |
364 | { PMAC_FTR_SOUND_CHIP_ENABLE, g5_i2s_enable }, | ||
340 | #ifdef CONFIG_SMP | 365 | #ifdef CONFIG_SMP |
341 | { PMAC_FTR_RESET_CPU, g5_reset_cpu }, | 366 | { PMAC_FTR_RESET_CPU, g5_reset_cpu }, |
342 | #endif /* CONFIG_SMP */ | 367 | #endif /* CONFIG_SMP */ |
diff --git a/include/asm-ppc/dbdma.h b/include/asm-ppc/dbdma.h index 6047f288c70b..8973565f95d3 100644 --- a/include/asm-ppc/dbdma.h +++ b/include/asm-ppc/dbdma.h | |||
@@ -88,7 +88,7 @@ struct dbdma_cmd { | |||
88 | #define WAIT_ALWAYS 3 /* always wait */ | 88 | #define WAIT_ALWAYS 3 /* always wait */ |
89 | 89 | ||
90 | /* Align an address for a DBDMA command structure */ | 90 | /* Align an address for a DBDMA command structure */ |
91 | #define DBDMA_ALIGN(x) (((unsigned)(x) + sizeof(struct dbdma_cmd) - 1) \ | 91 | #define DBDMA_ALIGN(x) (((unsigned long)(x) + sizeof(struct dbdma_cmd) - 1) \ |
92 | & -sizeof(struct dbdma_cmd)) | 92 | & -sizeof(struct dbdma_cmd)) |
93 | 93 | ||
94 | /* Useful macros */ | 94 | /* Useful macros */ |
diff --git a/include/asm-ppc/keylargo.h b/include/asm-ppc/keylargo.h index 457c75a4622f..a669a3f0f5a2 100644 --- a/include/asm-ppc/keylargo.h +++ b/include/asm-ppc/keylargo.h | |||
@@ -228,6 +228,11 @@ | |||
228 | 228 | ||
229 | #define K2_FCR1_PCI1_BUS_RESET_N 0x00000010 | 229 | #define K2_FCR1_PCI1_BUS_RESET_N 0x00000010 |
230 | #define K2_FCR1_PCI1_SLEEP_RESET_EN 0x00000020 | 230 | #define K2_FCR1_PCI1_SLEEP_RESET_EN 0x00000020 |
231 | #define K2_FCR1_I2S0_CELL_ENABLE 0x00000400 | ||
232 | #define K2_FCR1_I2S0_RESET 0x00000800 | ||
233 | #define K2_FCR1_I2S0_CLK_ENABLE_BIT 0x00001000 | ||
234 | #define K2_FCR1_I2S0_ENABLE 0x00002000 | ||
235 | |||
231 | #define K2_FCR1_PCI1_CLK_ENABLE 0x00004000 | 236 | #define K2_FCR1_PCI1_CLK_ENABLE 0x00004000 |
232 | #define K2_FCR1_FW_CLK_ENABLE 0x00008000 | 237 | #define K2_FCR1_FW_CLK_ENABLE 0x00008000 |
233 | #define K2_FCR1_FW_RESET_N 0x00010000 | 238 | #define K2_FCR1_FW_RESET_N 0x00010000 |
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c index c23f601a37f9..31ea7a4c069f 100644 --- a/sound/ppc/beep.c +++ b/sound/ppc/beep.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/input.h> | 26 | #include <linux/input.h> |
27 | #include <linux/pci.h> | ||
28 | #include <linux/dma-mapping.h> | ||
27 | #include <sound/core.h> | 29 | #include <sound/core.h> |
28 | #include <sound/control.h> | 30 | #include <sound/control.h> |
29 | #include "pmac.h" | 31 | #include "pmac.h" |
@@ -35,7 +37,7 @@ struct snd_pmac_beep { | |||
35 | int hz; | 37 | int hz; |
36 | int nsamples; | 38 | int nsamples; |
37 | short *buf; /* allocated wave buffer */ | 39 | short *buf; /* allocated wave buffer */ |
38 | unsigned long addr; /* physical address of buffer */ | 40 | dma_addr_t addr; /* physical address of buffer */ |
39 | struct input_dev dev; | 41 | struct input_dev dev; |
40 | }; | 42 | }; |
41 | 43 | ||
@@ -217,12 +219,8 @@ int __init snd_pmac_attach_beep(pmac_t *chip) | |||
217 | return -ENOMEM; | 219 | return -ENOMEM; |
218 | 220 | ||
219 | memset(beep, 0, sizeof(*beep)); | 221 | memset(beep, 0, sizeof(*beep)); |
220 | beep->buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); | 222 | beep->buf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, |
221 | if (! beep->buf) { | 223 | &beep->addr, GFP_KERNEL); |
222 | kfree(beep); | ||
223 | return -ENOMEM; | ||
224 | } | ||
225 | beep->addr = virt_to_bus(beep->buf); | ||
226 | 224 | ||
227 | beep->dev.evbit[0] = BIT(EV_SND); | 225 | beep->dev.evbit[0] = BIT(EV_SND); |
228 | beep->dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); | 226 | beep->dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); |
@@ -255,7 +253,8 @@ void snd_pmac_detach_beep(pmac_t *chip) | |||
255 | { | 253 | { |
256 | if (chip->beep) { | 254 | if (chip->beep) { |
257 | input_unregister_device(&chip->beep->dev); | 255 | input_unregister_device(&chip->beep->dev); |
258 | kfree(chip->beep->buf); | 256 | dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, |
257 | chip->beep->buf, chip->beep->addr); | ||
259 | kfree(chip->beep); | 258 | kfree(chip->beep); |
260 | chip->beep = NULL; | 259 | chip->beep = NULL; |
261 | } | 260 | } |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index f9a9601769aa..3bf5f069a03d 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c | |||
@@ -27,14 +27,13 @@ | |||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/pci.h> | ||
31 | #include <linux/dma-mapping.h> | ||
30 | #include <sound/core.h> | 32 | #include <sound/core.h> |
31 | #include "pmac.h" | 33 | #include "pmac.h" |
32 | #include <sound/pcm_params.h> | 34 | #include <sound/pcm_params.h> |
33 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
34 | #include <asm/pmac_feature.h> | 35 | #include <asm/pmac_feature.h> |
35 | #else | 36 | #include <asm/pci-bridge.h> |
36 | #include <asm/feature.h> | ||
37 | #endif | ||
38 | 37 | ||
39 | 38 | ||
40 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | 39 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) |
@@ -57,22 +56,29 @@ static int tumbler_freqs[1] = { | |||
57 | /* | 56 | /* |
58 | * allocate DBDMA command arrays | 57 | * allocate DBDMA command arrays |
59 | */ | 58 | */ |
60 | static int snd_pmac_dbdma_alloc(pmac_dbdma_t *rec, int size) | 59 | static int snd_pmac_dbdma_alloc(pmac_t *chip, pmac_dbdma_t *rec, int size) |
61 | { | 60 | { |
62 | rec->space = kmalloc(sizeof(struct dbdma_cmd) * (size + 1), GFP_KERNEL); | 61 | unsigned int rsize = sizeof(struct dbdma_cmd) * (size + 1); |
62 | |||
63 | rec->space = dma_alloc_coherent(&chip->pdev->dev, rsize, | ||
64 | &rec->dma_base, GFP_KERNEL); | ||
63 | if (rec->space == NULL) | 65 | if (rec->space == NULL) |
64 | return -ENOMEM; | 66 | return -ENOMEM; |
65 | rec->size = size; | 67 | rec->size = size; |
66 | memset(rec->space, 0, sizeof(struct dbdma_cmd) * (size + 1)); | 68 | memset(rec->space, 0, rsize); |
67 | rec->cmds = (void __iomem *)DBDMA_ALIGN(rec->space); | 69 | rec->cmds = (void __iomem *)DBDMA_ALIGN(rec->space); |
68 | rec->addr = virt_to_bus(rec->cmds); | 70 | rec->addr = rec->dma_base + (unsigned long)((char *)rec->cmds - (char *)rec->space); |
71 | |||
69 | return 0; | 72 | return 0; |
70 | } | 73 | } |
71 | 74 | ||
72 | static void snd_pmac_dbdma_free(pmac_dbdma_t *rec) | 75 | static void snd_pmac_dbdma_free(pmac_t *chip, pmac_dbdma_t *rec) |
73 | { | 76 | { |
74 | if (rec) | 77 | if (rec) { |
75 | kfree(rec->space); | 78 | unsigned int rsize = sizeof(struct dbdma_cmd) * (rec->size + 1); |
79 | |||
80 | dma_free_coherent(&chip->pdev->dev, rsize, rec->space, rec->dma_base); | ||
81 | } | ||
76 | } | 82 | } |
77 | 83 | ||
78 | 84 | ||
@@ -237,7 +243,7 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr | |||
237 | /* continuous DMA memory type doesn't provide the physical address, | 243 | /* continuous DMA memory type doesn't provide the physical address, |
238 | * so we need to resolve the address here... | 244 | * so we need to resolve the address here... |
239 | */ | 245 | */ |
240 | offset = virt_to_bus(runtime->dma_area); | 246 | offset = runtime->dma_addr; |
241 | for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { | 247 | for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) { |
242 | st_le32(&cp->phy_addr, offset); | 248 | st_le32(&cp->phy_addr, offset); |
243 | st_le16(&cp->req_count, rec->period_size); | 249 | st_le16(&cp->req_count, rec->period_size); |
@@ -664,8 +670,8 @@ int __init snd_pmac_pcm_new(pmac_t *chip) | |||
664 | chip->capture.cur_freqs = chip->freqs_ok; | 670 | chip->capture.cur_freqs = chip->freqs_ok; |
665 | 671 | ||
666 | /* preallocate 64k buffer */ | 672 | /* preallocate 64k buffer */ |
667 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, | 673 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
668 | snd_dma_continuous_data(GFP_KERNEL), | 674 | &chip->pdev->dev, |
669 | 64 * 1024, 64 * 1024); | 675 | 64 * 1024, 64 * 1024); |
670 | 676 | ||
671 | return 0; | 677 | return 0; |
@@ -757,28 +763,10 @@ snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs) | |||
757 | /* | 763 | /* |
758 | * a wrapper to feature call for compatibility | 764 | * a wrapper to feature call for compatibility |
759 | */ | 765 | */ |
760 | #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) | ||
761 | static void snd_pmac_sound_feature(pmac_t *chip, int enable) | 766 | static void snd_pmac_sound_feature(pmac_t *chip, int enable) |
762 | { | 767 | { |
763 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
764 | ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable); | 768 | ppc_md.feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, chip->node, 0, enable); |
765 | #else | ||
766 | if (chip->is_pbook_G3) { | ||
767 | pmu_suspend(); | ||
768 | feature_clear(chip->node, FEATURE_Sound_power); | ||
769 | feature_clear(chip->node, FEATURE_Sound_CLK_enable); | ||
770 | big_mdelay(1000); /* XXX */ | ||
771 | pmu_resume(); | ||
772 | } | ||
773 | if (chip->is_pbook_3400) { | ||
774 | feature_set(chip->node, FEATURE_IOBUS_enable); | ||
775 | udelay(10); | ||
776 | } | ||
777 | #endif | ||
778 | } | 769 | } |
779 | #else /* CONFIG_PM && CONFIG_PMAC_PBOOK */ | ||
780 | #define snd_pmac_sound_feature(chip,enable) /**/ | ||
781 | #endif /* CONFIG_PM && CONFIG_PMAC_PBOOK */ | ||
782 | 770 | ||
783 | /* | 771 | /* |
784 | * release resources | 772 | * release resources |
@@ -786,8 +774,6 @@ static void snd_pmac_sound_feature(pmac_t *chip, int enable) | |||
786 | 774 | ||
787 | static int snd_pmac_free(pmac_t *chip) | 775 | static int snd_pmac_free(pmac_t *chip) |
788 | { | 776 | { |
789 | int i; | ||
790 | |||
791 | /* stop sounds */ | 777 | /* stop sounds */ |
792 | if (chip->initialized) { | 778 | if (chip->initialized) { |
793 | snd_pmac_dbdma_reset(chip); | 779 | snd_pmac_dbdma_reset(chip); |
@@ -813,9 +799,9 @@ static int snd_pmac_free(pmac_t *chip) | |||
813 | free_irq(chip->tx_irq, (void*)chip); | 799 | free_irq(chip->tx_irq, (void*)chip); |
814 | if (chip->rx_irq >= 0) | 800 | if (chip->rx_irq >= 0) |
815 | free_irq(chip->rx_irq, (void*)chip); | 801 | free_irq(chip->rx_irq, (void*)chip); |
816 | snd_pmac_dbdma_free(&chip->playback.cmd); | 802 | snd_pmac_dbdma_free(chip, &chip->playback.cmd); |
817 | snd_pmac_dbdma_free(&chip->capture.cmd); | 803 | snd_pmac_dbdma_free(chip, &chip->capture.cmd); |
818 | snd_pmac_dbdma_free(&chip->extra_dma); | 804 | snd_pmac_dbdma_free(chip, &chip->extra_dma); |
819 | if (chip->macio_base) | 805 | if (chip->macio_base) |
820 | iounmap(chip->macio_base); | 806 | iounmap(chip->macio_base); |
821 | if (chip->latch_base) | 807 | if (chip->latch_base) |
@@ -826,12 +812,23 @@ static int snd_pmac_free(pmac_t *chip) | |||
826 | iounmap(chip->playback.dma); | 812 | iounmap(chip->playback.dma); |
827 | if (chip->capture.dma) | 813 | if (chip->capture.dma) |
828 | iounmap(chip->capture.dma); | 814 | iounmap(chip->capture.dma); |
815 | #ifndef CONFIG_PPC64 | ||
829 | if (chip->node) { | 816 | if (chip->node) { |
817 | int i; | ||
818 | |||
830 | for (i = 0; i < 3; i++) { | 819 | for (i = 0; i < 3; i++) { |
831 | if (chip->of_requested & (1 << i)) | 820 | if (chip->of_requested & (1 << i)) { |
832 | release_OF_resource(chip->node, i); | 821 | if (chip->is_k2) |
822 | release_OF_resource(chip->node->parent, | ||
823 | i); | ||
824 | else | ||
825 | release_OF_resource(chip->node, i); | ||
826 | } | ||
833 | } | 827 | } |
834 | } | 828 | } |
829 | #endif /* CONFIG_PPC64 */ | ||
830 | if (chip->pdev) | ||
831 | pci_dev_put(chip->pdev); | ||
835 | kfree(chip); | 832 | kfree(chip); |
836 | return 0; | 833 | return 0; |
837 | } | 834 | } |
@@ -881,6 +878,8 @@ static int __init snd_pmac_detect(pmac_t *chip) | |||
881 | { | 878 | { |
882 | struct device_node *sound; | 879 | struct device_node *sound; |
883 | unsigned int *prop, l; | 880 | unsigned int *prop, l; |
881 | struct macio_chip* macio; | ||
882 | |||
884 | u32 layout_id = 0; | 883 | u32 layout_id = 0; |
885 | 884 | ||
886 | if (_machine != _MACH_Pmac) | 885 | if (_machine != _MACH_Pmac) |
@@ -918,10 +917,17 @@ static int __init snd_pmac_detect(pmac_t *chip) | |||
918 | * if we didn't find a davbus device, try 'i2s-a' since | 917 | * if we didn't find a davbus device, try 'i2s-a' since |
919 | * this seems to be what iBooks have | 918 | * this seems to be what iBooks have |
920 | */ | 919 | */ |
921 | if (! chip->node) | 920 | if (! chip->node) { |
922 | chip->node = find_devices("i2s-a"); | 921 | chip->node = find_devices("i2s-a"); |
922 | if (chip->node && chip->node->parent && chip->node->parent->parent) { | ||
923 | if (device_is_compatible(chip->node->parent->parent, | ||
924 | "K2-Keylargo")) | ||
925 | chip->is_k2 = 1; | ||
926 | } | ||
927 | } | ||
923 | if (! chip->node) | 928 | if (! chip->node) |
924 | return -ENODEV; | 929 | return -ENODEV; |
930 | |||
925 | sound = find_devices("sound"); | 931 | sound = find_devices("sound"); |
926 | while (sound && sound->parent != chip->node) | 932 | while (sound && sound->parent != chip->node) |
927 | sound = sound->next; | 933 | sound = sound->next; |
@@ -966,7 +972,8 @@ static int __init snd_pmac_detect(pmac_t *chip) | |||
966 | chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ | 972 | chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ |
967 | } | 973 | } |
968 | if (device_is_compatible(sound, "AOAKeylargo") || | 974 | if (device_is_compatible(sound, "AOAKeylargo") || |
969 | device_is_compatible(sound, "AOAbase")) { | 975 | device_is_compatible(sound, "AOAbase") || |
976 | device_is_compatible(sound, "AOAK2")) { | ||
970 | /* For now, only support very basic TAS3004 based machines with | 977 | /* For now, only support very basic TAS3004 based machines with |
971 | * single frequency until proper i2s control is implemented | 978 | * single frequency until proper i2s control is implemented |
972 | */ | 979 | */ |
@@ -975,6 +982,7 @@ static int __init snd_pmac_detect(pmac_t *chip) | |||
975 | case 0x46: | 982 | case 0x46: |
976 | case 0x33: | 983 | case 0x33: |
977 | case 0x29: | 984 | case 0x29: |
985 | case 0x24: | ||
978 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); | 986 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); |
979 | chip->model = PMAC_SNAPPER; | 987 | chip->model = PMAC_SNAPPER; |
980 | chip->can_byte_swap = 0; /* FIXME: check this */ | 988 | chip->can_byte_swap = 0; /* FIXME: check this */ |
@@ -987,6 +995,26 @@ static int __init snd_pmac_detect(pmac_t *chip) | |||
987 | chip->device_id = *prop; | 995 | chip->device_id = *prop; |
988 | chip->has_iic = (find_devices("perch") != NULL); | 996 | chip->has_iic = (find_devices("perch") != NULL); |
989 | 997 | ||
998 | /* We need the PCI device for DMA allocations, let's use a crude method | ||
999 | * for now ... | ||
1000 | */ | ||
1001 | macio = macio_find(chip->node, macio_unknown); | ||
1002 | if (macio == NULL) | ||
1003 | printk(KERN_WARNING "snd-powermac: can't locate macio !\n"); | ||
1004 | else { | ||
1005 | struct pci_dev *pdev = NULL; | ||
1006 | |||
1007 | for_each_pci_dev(pdev) { | ||
1008 | struct device_node *np = pci_device_to_OF_node(pdev); | ||
1009 | if (np && np == macio->of_node) { | ||
1010 | chip->pdev = pdev; | ||
1011 | break; | ||
1012 | } | ||
1013 | } | ||
1014 | } | ||
1015 | if (chip->pdev == NULL) | ||
1016 | printk(KERN_WARNING "snd-powermac: can't locate macio PCI device !\n"); | ||
1017 | |||
990 | detect_byte_swap(chip); | 1018 | detect_byte_swap(chip); |
991 | 1019 | ||
992 | /* look for a property saying what sample rates | 1020 | /* look for a property saying what sample rates |
@@ -1091,8 +1119,10 @@ int __init snd_pmac_add_automute(pmac_t *chip) | |||
1091 | int err; | 1119 | int err; |
1092 | chip->auto_mute = 1; | 1120 | chip->auto_mute = 1; |
1093 | err = snd_ctl_add(chip->card, snd_ctl_new1(&auto_mute_controls[0], chip)); | 1121 | err = snd_ctl_add(chip->card, snd_ctl_new1(&auto_mute_controls[0], chip)); |
1094 | if (err < 0) | 1122 | if (err < 0) { |
1123 | printk(KERN_ERR "snd-powermac: Failed to add automute control\n"); | ||
1095 | return err; | 1124 | return err; |
1125 | } | ||
1096 | chip->hp_detect_ctl = snd_ctl_new1(&auto_mute_controls[1], chip); | 1126 | chip->hp_detect_ctl = snd_ctl_new1(&auto_mute_controls[1], chip); |
1097 | return snd_ctl_add(chip->card, chip->hp_detect_ctl); | 1127 | return snd_ctl_add(chip->card, chip->hp_detect_ctl); |
1098 | } | 1128 | } |
@@ -1106,6 +1136,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1106 | pmac_t *chip; | 1136 | pmac_t *chip; |
1107 | struct device_node *np; | 1137 | struct device_node *np; |
1108 | int i, err; | 1138 | int i, err; |
1139 | unsigned long ctrl_addr, txdma_addr, rxdma_addr; | ||
1109 | static snd_device_ops_t ops = { | 1140 | static snd_device_ops_t ops = { |
1110 | .dev_free = snd_pmac_dev_free, | 1141 | .dev_free = snd_pmac_dev_free, |
1111 | }; | 1142 | }; |
@@ -1127,32 +1158,59 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1127 | if ((err = snd_pmac_detect(chip)) < 0) | 1158 | if ((err = snd_pmac_detect(chip)) < 0) |
1128 | goto __error; | 1159 | goto __error; |
1129 | 1160 | ||
1130 | if (snd_pmac_dbdma_alloc(&chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 || | 1161 | if (snd_pmac_dbdma_alloc(chip, &chip->playback.cmd, PMAC_MAX_FRAGS + 1) < 0 || |
1131 | snd_pmac_dbdma_alloc(&chip->capture.cmd, PMAC_MAX_FRAGS + 1) < 0 || | 1162 | snd_pmac_dbdma_alloc(chip, &chip->capture.cmd, PMAC_MAX_FRAGS + 1) < 0 || |
1132 | snd_pmac_dbdma_alloc(&chip->extra_dma, 2) < 0) { | 1163 | snd_pmac_dbdma_alloc(chip, &chip->extra_dma, 2) < 0) { |
1133 | err = -ENOMEM; | 1164 | err = -ENOMEM; |
1134 | goto __error; | 1165 | goto __error; |
1135 | } | 1166 | } |
1136 | 1167 | ||
1137 | np = chip->node; | 1168 | np = chip->node; |
1138 | if (np->n_addrs < 3 || np->n_intrs < 3) { | 1169 | if (chip->is_k2) { |
1139 | err = -ENODEV; | 1170 | if (np->parent->n_addrs < 2 || np->n_intrs < 3) { |
1140 | goto __error; | 1171 | err = -ENODEV; |
1141 | } | 1172 | goto __error; |
1173 | } | ||
1174 | for (i = 0; i < 2; i++) { | ||
1175 | #ifndef CONFIG_PPC64 | ||
1176 | static char *name[2] = { "- Control", "- DMA" }; | ||
1177 | if (! request_OF_resource(np->parent, i, name[i])) { | ||
1178 | snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i); | ||
1179 | err = -ENODEV; | ||
1180 | goto __error; | ||
1181 | } | ||
1182 | chip->of_requested |= (1 << i); | ||
1183 | #endif /* CONFIG_PPC64 */ | ||
1184 | ctrl_addr = np->parent->addrs[0].address; | ||
1185 | txdma_addr = np->parent->addrs[1].address; | ||
1186 | rxdma_addr = txdma_addr + 0x100; | ||
1187 | } | ||
1142 | 1188 | ||
1143 | for (i = 0; i < 3; i++) { | 1189 | } else { |
1144 | static char *name[3] = { NULL, "- Tx DMA", "- Rx DMA" }; | 1190 | if (np->n_addrs < 3 || np->n_intrs < 3) { |
1145 | if (! request_OF_resource(np, i, name[i])) { | ||
1146 | snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i); | ||
1147 | err = -ENODEV; | 1191 | err = -ENODEV; |
1148 | goto __error; | 1192 | goto __error; |
1149 | } | 1193 | } |
1150 | chip->of_requested |= (1 << i); | 1194 | |
1195 | for (i = 0; i < 3; i++) { | ||
1196 | #ifndef CONFIG_PPC64 | ||
1197 | static char *name[3] = { "- Control", "- Tx DMA", "- Rx DMA" }; | ||
1198 | if (! request_OF_resource(np, i, name[i])) { | ||
1199 | snd_printk(KERN_ERR "pmac: can't request resource %d!\n", i); | ||
1200 | err = -ENODEV; | ||
1201 | goto __error; | ||
1202 | } | ||
1203 | chip->of_requested |= (1 << i); | ||
1204 | #endif /* CONFIG_PPC64 */ | ||
1205 | ctrl_addr = np->addrs[0].address; | ||
1206 | txdma_addr = np->addrs[1].address; | ||
1207 | rxdma_addr = np->addrs[2].address; | ||
1208 | } | ||
1151 | } | 1209 | } |
1152 | 1210 | ||
1153 | chip->awacs = ioremap(np->addrs[0].address, 0x1000); | 1211 | chip->awacs = ioremap(ctrl_addr, 0x1000); |
1154 | chip->playback.dma = ioremap(np->addrs[1].address, 0x100); | 1212 | chip->playback.dma = ioremap(txdma_addr, 0x100); |
1155 | chip->capture.dma = ioremap(np->addrs[2].address, 0x100); | 1213 | chip->capture.dma = ioremap(rxdma_addr, 0x100); |
1156 | if (chip->model <= PMAC_BURGUNDY) { | 1214 | if (chip->model <= PMAC_BURGUNDY) { |
1157 | if (request_irq(np->intrs[0].line, snd_pmac_ctrl_intr, 0, | 1215 | if (request_irq(np->intrs[0].line, snd_pmac_ctrl_intr, 0, |
1158 | "PMac", (void*)chip)) { | 1216 | "PMac", (void*)chip)) { |
@@ -1180,7 +1238,8 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1180 | snd_pmac_sound_feature(chip, 1); | 1238 | snd_pmac_sound_feature(chip, 1); |
1181 | 1239 | ||
1182 | /* reset */ | 1240 | /* reset */ |
1183 | out_le32(&chip->awacs->control, 0x11); | 1241 | if (chip->model == PMAC_AWACS) |
1242 | out_le32(&chip->awacs->control, 0x11); | ||
1184 | 1243 | ||
1185 | /* Powerbooks have odd ways of enabling inputs such as | 1244 | /* Powerbooks have odd ways of enabling inputs such as |
1186 | an expansion-bay CD or sound from an internal modem | 1245 | an expansion-bay CD or sound from an internal modem |
@@ -1232,6 +1291,8 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) | |||
1232 | return 0; | 1291 | return 0; |
1233 | 1292 | ||
1234 | __error: | 1293 | __error: |
1294 | if (chip->pdev) | ||
1295 | pci_dev_put(chip->pdev); | ||
1235 | snd_pmac_free(chip); | 1296 | snd_pmac_free(chip); |
1236 | return err; | 1297 | return err; |
1237 | } | 1298 | } |
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index a699b01210ee..dc6c99dd14e7 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h | |||
@@ -60,7 +60,8 @@ typedef struct snd_pmac_dbdma pmac_dbdma_t; | |||
60 | * DBDMA space | 60 | * DBDMA space |
61 | */ | 61 | */ |
62 | struct snd_pmac_dbdma { | 62 | struct snd_pmac_dbdma { |
63 | unsigned long addr; | 63 | dma_addr_t dma_base; |
64 | dma_addr_t addr; | ||
64 | struct dbdma_cmd __iomem *cmds; | 65 | struct dbdma_cmd __iomem *cmds; |
65 | void *space; | 66 | void *space; |
66 | int size; | 67 | int size; |
@@ -101,6 +102,7 @@ struct snd_pmac { | |||
101 | 102 | ||
102 | /* h/w info */ | 103 | /* h/w info */ |
103 | struct device_node *node; | 104 | struct device_node *node; |
105 | struct pci_dev *pdev; | ||
104 | unsigned int revision; | 106 | unsigned int revision; |
105 | unsigned int manufacturer; | 107 | unsigned int manufacturer; |
106 | unsigned int subframe; | 108 | unsigned int subframe; |
@@ -110,6 +112,7 @@ struct snd_pmac { | |||
110 | unsigned int has_iic : 1; | 112 | unsigned int has_iic : 1; |
111 | unsigned int is_pbook_3400 : 1; | 113 | unsigned int is_pbook_3400 : 1; |
112 | unsigned int is_pbook_G3 : 1; | 114 | unsigned int is_pbook_G3 : 1; |
115 | unsigned int is_k2 : 1; | ||
113 | 116 | ||
114 | unsigned int can_byte_swap : 1; | 117 | unsigned int can_byte_swap : 1; |
115 | unsigned int can_duplex : 1; | 118 | unsigned int can_duplex : 1; |
@@ -157,6 +160,7 @@ struct snd_pmac { | |||
157 | snd_kcontrol_t *speaker_sw_ctl; | 160 | snd_kcontrol_t *speaker_sw_ctl; |
158 | snd_kcontrol_t *drc_sw_ctl; /* only used for tumbler -ReneR */ | 161 | snd_kcontrol_t *drc_sw_ctl; /* only used for tumbler -ReneR */ |
159 | snd_kcontrol_t *hp_detect_ctl; | 162 | snd_kcontrol_t *hp_detect_ctl; |
163 | snd_kcontrol_t *lineout_sw_ctl; | ||
160 | 164 | ||
161 | /* lowlevel callbacks */ | 165 | /* lowlevel callbacks */ |
162 | void (*set_format)(pmac_t *chip); | 166 | void (*set_format)(pmac_t *chip); |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index cb6916e9b74f..c71807e069ee 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -35,14 +35,19 @@ | |||
35 | #include <sound/core.h> | 35 | #include <sound/core.h> |
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
38 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | 38 | #include <asm/machdep.h> |
39 | #include <asm/pmac_feature.h> | 39 | #include <asm/pmac_feature.h> |
40 | #else | ||
41 | #error old crap | ||
42 | #endif | ||
43 | #include "pmac.h" | 40 | #include "pmac.h" |
44 | #include "tumbler_volume.h" | 41 | #include "tumbler_volume.h" |
45 | 42 | ||
43 | #undef DEBUG | ||
44 | |||
45 | #ifdef DEBUG | ||
46 | #define DBG(fmt...) printk(fmt) | ||
47 | #else | ||
48 | #define DBG(fmt...) | ||
49 | #endif | ||
50 | |||
46 | /* i2c address for tumbler */ | 51 | /* i2c address for tumbler */ |
47 | #define TAS_I2C_ADDR 0x34 | 52 | #define TAS_I2C_ADDR 0x34 |
48 | 53 | ||
@@ -78,21 +83,22 @@ enum { | |||
78 | }; | 83 | }; |
79 | 84 | ||
80 | typedef struct pmac_gpio { | 85 | typedef struct pmac_gpio { |
81 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
82 | unsigned int addr; | 86 | unsigned int addr; |
83 | #else | 87 | u8 active_val; |
84 | void __iomem *addr; | 88 | u8 inactive_val; |
85 | #endif | 89 | u8 active_state; |
86 | int active_state; | ||
87 | } pmac_gpio_t; | 90 | } pmac_gpio_t; |
88 | 91 | ||
89 | typedef struct pmac_tumbler_t { | 92 | typedef struct pmac_tumbler_t { |
90 | pmac_keywest_t i2c; | 93 | pmac_keywest_t i2c; |
91 | pmac_gpio_t audio_reset; | 94 | pmac_gpio_t audio_reset; |
92 | pmac_gpio_t amp_mute; | 95 | pmac_gpio_t amp_mute; |
96 | pmac_gpio_t line_mute; | ||
97 | pmac_gpio_t line_detect; | ||
93 | pmac_gpio_t hp_mute; | 98 | pmac_gpio_t hp_mute; |
94 | pmac_gpio_t hp_detect; | 99 | pmac_gpio_t hp_detect; |
95 | int headphone_irq; | 100 | int headphone_irq; |
101 | int lineout_irq; | ||
96 | unsigned int master_vol[2]; | 102 | unsigned int master_vol[2]; |
97 | unsigned int save_master_switch[2]; | 103 | unsigned int save_master_switch[2]; |
98 | unsigned int master_switch[2]; | 104 | unsigned int master_switch[2]; |
@@ -120,6 +126,7 @@ static int send_init_client(pmac_keywest_t *i2c, unsigned int *regs) | |||
120 | regs[0], regs[1]); | 126 | regs[0], regs[1]); |
121 | if (err >= 0) | 127 | if (err >= 0) |
122 | break; | 128 | break; |
129 | DBG("(W) i2c error %d\n", err); | ||
123 | mdelay(10); | 130 | mdelay(10); |
124 | } while (count--); | 131 | } while (count--); |
125 | if (err < 0) | 132 | if (err < 0) |
@@ -137,6 +144,7 @@ static int tumbler_init_client(pmac_keywest_t *i2c) | |||
137 | TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0, | 144 | TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0, |
138 | 0, /* terminator */ | 145 | 0, /* terminator */ |
139 | }; | 146 | }; |
147 | DBG("(I) tumbler init client\n"); | ||
140 | return send_init_client(i2c, regs); | 148 | return send_init_client(i2c, regs); |
141 | } | 149 | } |
142 | 150 | ||
@@ -151,36 +159,27 @@ static int snapper_init_client(pmac_keywest_t *i2c) | |||
151 | TAS_REG_ACS, 0, | 159 | TAS_REG_ACS, 0, |
152 | 0, /* terminator */ | 160 | 0, /* terminator */ |
153 | }; | 161 | }; |
162 | DBG("(I) snapper init client\n"); | ||
154 | return send_init_client(i2c, regs); | 163 | return send_init_client(i2c, regs); |
155 | } | 164 | } |
156 | 165 | ||
157 | /* | 166 | /* |
158 | * gpio access | 167 | * gpio access |
159 | */ | 168 | */ |
160 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
161 | #define do_gpio_write(gp, val) \ | 169 | #define do_gpio_write(gp, val) \ |
162 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) | 170 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val) |
163 | #define do_gpio_read(gp) \ | 171 | #define do_gpio_read(gp) \ |
164 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) | 172 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0) |
165 | #define tumbler_gpio_free(gp) /* NOP */ | 173 | #define tumbler_gpio_free(gp) /* NOP */ |
166 | #else | ||
167 | #define do_gpio_write(gp, val) writeb(val, (gp)->addr) | ||
168 | #define do_gpio_read(gp) readb((gp)->addr) | ||
169 | static inline void tumbler_gpio_free(pmac_gpio_t *gp) | ||
170 | { | ||
171 | if (gp->addr) { | ||
172 | iounmap(gp->addr); | ||
173 | gp->addr = NULL; | ||
174 | } | ||
175 | } | ||
176 | #endif /* CONFIG_PPC_HAS_FEATURE_CALLS */ | ||
177 | 174 | ||
178 | static void write_audio_gpio(pmac_gpio_t *gp, int active) | 175 | static void write_audio_gpio(pmac_gpio_t *gp, int active) |
179 | { | 176 | { |
180 | if (! gp->addr) | 177 | if (! gp->addr) |
181 | return; | 178 | return; |
182 | active = active ? gp->active_state : !gp->active_state; | 179 | active = active ? gp->active_val : gp->inactive_val; |
183 | do_gpio_write(gp, active ? 0x05 : 0x04); | 180 | |
181 | do_gpio_write(gp, active); | ||
182 | DBG("(I) gpio %x write %d\n", gp->addr, active); | ||
184 | } | 183 | } |
185 | 184 | ||
186 | static int read_audio_gpio(pmac_gpio_t *gp) | 185 | static int read_audio_gpio(pmac_gpio_t *gp) |
@@ -663,7 +662,7 @@ static int snapper_put_mix(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucont | |||
663 | * to avoid codec reset on ibook M7 | 662 | * to avoid codec reset on ibook M7 |
664 | */ | 663 | */ |
665 | 664 | ||
666 | enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP }; | 665 | enum { TUMBLER_MUTE_HP, TUMBLER_MUTE_AMP, TUMBLER_MUTE_LINE }; |
667 | 666 | ||
668 | static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 667 | static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) |
669 | { | 668 | { |
@@ -672,7 +671,18 @@ static int tumbler_get_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
672 | pmac_gpio_t *gp; | 671 | pmac_gpio_t *gp; |
673 | if (! (mix = chip->mixer_data)) | 672 | if (! (mix = chip->mixer_data)) |
674 | return -ENODEV; | 673 | return -ENODEV; |
675 | gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute; | 674 | switch(kcontrol->private_value) { |
675 | case TUMBLER_MUTE_HP: | ||
676 | gp = &mix->hp_mute; break; | ||
677 | case TUMBLER_MUTE_AMP: | ||
678 | gp = &mix->amp_mute; break; | ||
679 | case TUMBLER_MUTE_LINE: | ||
680 | gp = &mix->line_mute; break; | ||
681 | default: | ||
682 | gp = NULL; | ||
683 | } | ||
684 | if (gp == NULL) | ||
685 | return -EINVAL; | ||
676 | ucontrol->value.integer.value[0] = ! read_audio_gpio(gp); | 686 | ucontrol->value.integer.value[0] = ! read_audio_gpio(gp); |
677 | return 0; | 687 | return 0; |
678 | } | 688 | } |
@@ -689,7 +699,18 @@ static int tumbler_put_mute_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_ | |||
689 | #endif | 699 | #endif |
690 | if (! (mix = chip->mixer_data)) | 700 | if (! (mix = chip->mixer_data)) |
691 | return -ENODEV; | 701 | return -ENODEV; |
692 | gp = (kcontrol->private_value == TUMBLER_MUTE_HP) ? &mix->hp_mute : &mix->amp_mute; | 702 | switch(kcontrol->private_value) { |
703 | case TUMBLER_MUTE_HP: | ||
704 | gp = &mix->hp_mute; break; | ||
705 | case TUMBLER_MUTE_AMP: | ||
706 | gp = &mix->amp_mute; break; | ||
707 | case TUMBLER_MUTE_LINE: | ||
708 | gp = &mix->line_mute; break; | ||
709 | default: | ||
710 | gp = NULL; | ||
711 | } | ||
712 | if (gp == NULL) | ||
713 | return -EINVAL; | ||
693 | val = ! read_audio_gpio(gp); | 714 | val = ! read_audio_gpio(gp); |
694 | if (val != ucontrol->value.integer.value[0]) { | 715 | if (val != ucontrol->value.integer.value[0]) { |
695 | write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); | 716 | write_audio_gpio(gp, ! ucontrol->value.integer.value[0]); |
@@ -833,6 +854,14 @@ static snd_kcontrol_new_t tumbler_speaker_sw __initdata = { | |||
833 | .put = tumbler_put_mute_switch, | 854 | .put = tumbler_put_mute_switch, |
834 | .private_value = TUMBLER_MUTE_AMP, | 855 | .private_value = TUMBLER_MUTE_AMP, |
835 | }; | 856 | }; |
857 | static snd_kcontrol_new_t tumbler_lineout_sw __initdata = { | ||
858 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
859 | .name = "Line Out Playback Switch", | ||
860 | .info = snd_pmac_boolean_mono_info, | ||
861 | .get = tumbler_get_mute_switch, | ||
862 | .put = tumbler_put_mute_switch, | ||
863 | .private_value = TUMBLER_MUTE_LINE, | ||
864 | }; | ||
836 | static snd_kcontrol_new_t tumbler_drc_sw __initdata = { | 865 | static snd_kcontrol_new_t tumbler_drc_sw __initdata = { |
837 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 866 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
838 | .name = "DRC Switch", | 867 | .name = "DRC Switch", |
@@ -849,7 +878,21 @@ static snd_kcontrol_new_t tumbler_drc_sw __initdata = { | |||
849 | static int tumbler_detect_headphone(pmac_t *chip) | 878 | static int tumbler_detect_headphone(pmac_t *chip) |
850 | { | 879 | { |
851 | pmac_tumbler_t *mix = chip->mixer_data; | 880 | pmac_tumbler_t *mix = chip->mixer_data; |
852 | return read_audio_gpio(&mix->hp_detect); | 881 | int detect = 0; |
882 | |||
883 | if (mix->hp_detect.addr) | ||
884 | detect |= read_audio_gpio(&mix->hp_detect); | ||
885 | return detect; | ||
886 | } | ||
887 | |||
888 | static int tumbler_detect_lineout(pmac_t *chip) | ||
889 | { | ||
890 | pmac_tumbler_t *mix = chip->mixer_data; | ||
891 | int detect = 0; | ||
892 | |||
893 | if (mix->line_detect.addr) | ||
894 | detect |= read_audio_gpio(&mix->line_detect); | ||
895 | return detect; | ||
853 | } | 896 | } |
854 | 897 | ||
855 | static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw) | 898 | static void check_mute(pmac_t *chip, pmac_gpio_t *gp, int val, int do_notify, snd_kcontrol_t *sw) |
@@ -868,6 +911,7 @@ static void device_change_handler(void *self) | |||
868 | { | 911 | { |
869 | pmac_t *chip = (pmac_t*) self; | 912 | pmac_t *chip = (pmac_t*) self; |
870 | pmac_tumbler_t *mix; | 913 | pmac_tumbler_t *mix; |
914 | int headphone, lineout; | ||
871 | 915 | ||
872 | if (!chip) | 916 | if (!chip) |
873 | return; | 917 | return; |
@@ -875,23 +919,35 @@ static void device_change_handler(void *self) | |||
875 | mix = chip->mixer_data; | 919 | mix = chip->mixer_data; |
876 | snd_assert(mix, return); | 920 | snd_assert(mix, return); |
877 | 921 | ||
878 | if (tumbler_detect_headphone(chip)) { | 922 | headphone = tumbler_detect_headphone(chip); |
879 | /* mute speaker */ | 923 | lineout = tumbler_detect_lineout(chip); |
880 | check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify, | 924 | |
881 | chip->master_sw_ctl); | 925 | DBG("headphone: %d, lineout: %d\n", headphone, lineout); |
926 | |||
927 | if (headphone || lineout) { | ||
928 | /* unmute headphone/lineout & mute speaker */ | ||
929 | if (headphone) | ||
930 | check_mute(chip, &mix->hp_mute, 0, mix->auto_mute_notify, | ||
931 | chip->master_sw_ctl); | ||
932 | if (lineout && mix->line_mute.addr != 0) | ||
933 | check_mute(chip, &mix->line_mute, 0, mix->auto_mute_notify, | ||
934 | chip->lineout_sw_ctl); | ||
882 | if (mix->anded_reset) | 935 | if (mix->anded_reset) |
883 | big_mdelay(10); | 936 | big_mdelay(10); |
884 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, | 937 | check_mute(chip, &mix->amp_mute, 1, mix->auto_mute_notify, |
885 | chip->speaker_sw_ctl); | 938 | chip->speaker_sw_ctl); |
886 | mix->drc_enable = 0; | 939 | mix->drc_enable = 0; |
887 | } else { | 940 | } else { |
888 | /* unmute speaker */ | 941 | /* unmute speaker, mute others */ |
889 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, | 942 | check_mute(chip, &mix->amp_mute, 0, mix->auto_mute_notify, |
890 | chip->speaker_sw_ctl); | 943 | chip->speaker_sw_ctl); |
891 | if (mix->anded_reset) | 944 | if (mix->anded_reset) |
892 | big_mdelay(10); | 945 | big_mdelay(10); |
893 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, | 946 | check_mute(chip, &mix->hp_mute, 1, mix->auto_mute_notify, |
894 | chip->master_sw_ctl); | 947 | chip->master_sw_ctl); |
948 | if (mix->line_mute.addr != 0) | ||
949 | check_mute(chip, &mix->line_mute, 1, mix->auto_mute_notify, | ||
950 | chip->lineout_sw_ctl); | ||
895 | mix->drc_enable = 1; | 951 | mix->drc_enable = 1; |
896 | } | 952 | } |
897 | if (mix->auto_mute_notify) { | 953 | if (mix->auto_mute_notify) { |
@@ -967,7 +1023,7 @@ static struct device_node *find_compatible_audio_device(const char *name) | |||
967 | } | 1023 | } |
968 | 1024 | ||
969 | /* find an audio device and get its address */ | 1025 | /* find an audio device and get its address */ |
970 | static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_compatible) | 1026 | static long tumbler_find_device(const char *device, const char *platform, pmac_gpio_t *gp, int is_compatible) |
971 | { | 1027 | { |
972 | struct device_node *node; | 1028 | struct device_node *node; |
973 | u32 *base, addr; | 1029 | u32 *base, addr; |
@@ -977,6 +1033,7 @@ static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_comp | |||
977 | else | 1033 | else |
978 | node = find_audio_device(device); | 1034 | node = find_audio_device(device); |
979 | if (! node) { | 1035 | if (! node) { |
1036 | DBG("(W) cannot find audio device %s !\n", device); | ||
980 | snd_printdd("cannot find device %s\n", device); | 1037 | snd_printdd("cannot find device %s\n", device); |
981 | return -ENODEV; | 1038 | return -ENODEV; |
982 | } | 1039 | } |
@@ -985,29 +1042,48 @@ static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_comp | |||
985 | if (! base) { | 1042 | if (! base) { |
986 | base = (u32 *)get_property(node, "reg", NULL); | 1043 | base = (u32 *)get_property(node, "reg", NULL); |
987 | if (!base) { | 1044 | if (!base) { |
1045 | DBG("(E) cannot find address for device %s !\n", device); | ||
988 | snd_printd("cannot find address for device %s\n", device); | 1046 | snd_printd("cannot find address for device %s\n", device); |
989 | return -ENODEV; | 1047 | return -ENODEV; |
990 | } | 1048 | } |
991 | /* this only work if PPC_HAS_FEATURE_CALLS is set as we | ||
992 | * are only getting the low part of the address | ||
993 | */ | ||
994 | addr = *base; | 1049 | addr = *base; |
995 | if (addr < 0x50) | 1050 | if (addr < 0x50) |
996 | addr += 0x50; | 1051 | addr += 0x50; |
997 | } else | 1052 | } else |
998 | addr = *base; | 1053 | addr = *base; |
999 | 1054 | ||
1000 | #ifdef CONFIG_PPC_HAS_FEATURE_CALLS | ||
1001 | gp->addr = addr & 0x0000ffff; | 1055 | gp->addr = addr & 0x0000ffff; |
1002 | #else | ||
1003 | gp->addr = ioremap((unsigned long)addr, 1); | ||
1004 | #endif | ||
1005 | /* Try to find the active state, default to 0 ! */ | 1056 | /* Try to find the active state, default to 0 ! */ |
1006 | base = (u32 *)get_property(node, "audio-gpio-active-state", NULL); | 1057 | base = (u32 *)get_property(node, "audio-gpio-active-state", NULL); |
1007 | if (base) | 1058 | if (base) { |
1008 | gp->active_state = *base; | 1059 | gp->active_state = *base; |
1009 | else | 1060 | gp->active_val = (*base) ? 0x5 : 0x4; |
1061 | gp->inactive_val = (*base) ? 0x4 : 0x5; | ||
1062 | } else { | ||
1063 | u32 *prop = NULL; | ||
1010 | gp->active_state = 0; | 1064 | gp->active_state = 0; |
1065 | gp->active_val = 0x4; | ||
1066 | gp->inactive_val = 0x5; | ||
1067 | /* Here are some crude hacks to extract the GPIO polarity and | ||
1068 | * open collector informations out of the do-platform script | ||
1069 | * as we don't yet have an interpreter for these things | ||
1070 | */ | ||
1071 | if (platform) | ||
1072 | prop = (u32 *)get_property(node, platform, NULL); | ||
1073 | if (prop) { | ||
1074 | if (prop[3] == 0x9 && prop[4] == 0x9) { | ||
1075 | gp->active_val = 0xd; | ||
1076 | gp->inactive_val = 0xc; | ||
1077 | } | ||
1078 | if (prop[3] == 0x1 && prop[4] == 0x1) { | ||
1079 | gp->active_val = 0x5; | ||
1080 | gp->inactive_val = 0x4; | ||
1081 | } | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n", | ||
1086 | device, gp->addr, gp->active_state); | ||
1011 | 1087 | ||
1012 | return (node->n_intrs > 0) ? node->intrs[0].line : 0; | 1088 | return (node->n_intrs > 0) ? node->intrs[0].line : 0; |
1013 | } | 1089 | } |
@@ -1018,6 +1094,7 @@ static void tumbler_reset_audio(pmac_t *chip) | |||
1018 | pmac_tumbler_t *mix = chip->mixer_data; | 1094 | pmac_tumbler_t *mix = chip->mixer_data; |
1019 | 1095 | ||
1020 | if (mix->anded_reset) { | 1096 | if (mix->anded_reset) { |
1097 | DBG("(I) codec anded reset !\n"); | ||
1021 | write_audio_gpio(&mix->hp_mute, 0); | 1098 | write_audio_gpio(&mix->hp_mute, 0); |
1022 | write_audio_gpio(&mix->amp_mute, 0); | 1099 | write_audio_gpio(&mix->amp_mute, 0); |
1023 | big_mdelay(200); | 1100 | big_mdelay(200); |
@@ -1028,6 +1105,8 @@ static void tumbler_reset_audio(pmac_t *chip) | |||
1028 | write_audio_gpio(&mix->amp_mute, 0); | 1105 | write_audio_gpio(&mix->amp_mute, 0); |
1029 | big_mdelay(100); | 1106 | big_mdelay(100); |
1030 | } else { | 1107 | } else { |
1108 | DBG("(I) codec normal reset !\n"); | ||
1109 | |||
1031 | write_audio_gpio(&mix->audio_reset, 0); | 1110 | write_audio_gpio(&mix->audio_reset, 0); |
1032 | big_mdelay(200); | 1111 | big_mdelay(200); |
1033 | write_audio_gpio(&mix->audio_reset, 1); | 1112 | write_audio_gpio(&mix->audio_reset, 1); |
@@ -1045,6 +1124,8 @@ static void tumbler_suspend(pmac_t *chip) | |||
1045 | 1124 | ||
1046 | if (mix->headphone_irq >= 0) | 1125 | if (mix->headphone_irq >= 0) |
1047 | disable_irq(mix->headphone_irq); | 1126 | disable_irq(mix->headphone_irq); |
1127 | if (mix->lineout_irq >= 0) | ||
1128 | disable_irq(mix->lineout_irq); | ||
1048 | mix->save_master_switch[0] = mix->master_switch[0]; | 1129 | mix->save_master_switch[0] = mix->master_switch[0]; |
1049 | mix->save_master_switch[1] = mix->master_switch[1]; | 1130 | mix->save_master_switch[1] = mix->master_switch[1]; |
1050 | mix->master_switch[0] = mix->master_switch[1] = 0; | 1131 | mix->master_switch[0] = mix->master_switch[1] = 0; |
@@ -1099,41 +1180,59 @@ static void tumbler_resume(pmac_t *chip) | |||
1099 | chip->update_automute(chip, 0); | 1180 | chip->update_automute(chip, 0); |
1100 | if (mix->headphone_irq >= 0) | 1181 | if (mix->headphone_irq >= 0) |
1101 | enable_irq(mix->headphone_irq); | 1182 | enable_irq(mix->headphone_irq); |
1183 | if (mix->lineout_irq >= 0) | ||
1184 | enable_irq(mix->lineout_irq); | ||
1102 | } | 1185 | } |
1103 | #endif | 1186 | #endif |
1104 | 1187 | ||
1105 | /* initialize tumbler */ | 1188 | /* initialize tumbler */ |
1106 | static int __init tumbler_init(pmac_t *chip) | 1189 | static int __init tumbler_init(pmac_t *chip) |
1107 | { | 1190 | { |
1108 | int irq, err; | 1191 | int irq; |
1109 | pmac_tumbler_t *mix = chip->mixer_data; | 1192 | pmac_tumbler_t *mix = chip->mixer_data; |
1110 | snd_assert(mix, return -EINVAL); | 1193 | snd_assert(mix, return -EINVAL); |
1111 | 1194 | ||
1112 | if (tumbler_find_device("audio-hw-reset", &mix->audio_reset, 0) < 0) | 1195 | if (tumbler_find_device("audio-hw-reset", |
1113 | tumbler_find_device("hw-reset", &mix->audio_reset, 1); | 1196 | "platform-do-hw-reset", |
1114 | if (tumbler_find_device("amp-mute", &mix->amp_mute, 0) < 0) | 1197 | &mix->audio_reset, 0) < 0) |
1115 | tumbler_find_device("amp-mute", &mix->amp_mute, 1); | 1198 | tumbler_find_device("hw-reset", |
1116 | if (tumbler_find_device("headphone-mute", &mix->hp_mute, 0) < 0) | 1199 | "platform-do-hw-reset", |
1117 | tumbler_find_device("headphone-mute", &mix->hp_mute, 1); | 1200 | &mix->audio_reset, 1); |
1118 | irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 0); | 1201 | if (tumbler_find_device("amp-mute", |
1202 | "platform-do-amp-mute", | ||
1203 | &mix->amp_mute, 0) < 0) | ||
1204 | tumbler_find_device("amp-mute", | ||
1205 | "platform-do-amp-mute", | ||
1206 | &mix->amp_mute, 1); | ||
1207 | if (tumbler_find_device("headphone-mute", | ||
1208 | "platform-do-headphone-mute", | ||
1209 | &mix->hp_mute, 0) < 0) | ||
1210 | tumbler_find_device("headphone-mute", | ||
1211 | "platform-do-headphone-mute", | ||
1212 | &mix->hp_mute, 1); | ||
1213 | if (tumbler_find_device("line-output-mute", | ||
1214 | "platform-do-lineout-mute", | ||
1215 | &mix->line_mute, 0) < 0) | ||
1216 | tumbler_find_device("line-output-mute", | ||
1217 | "platform-do-lineout-mute", | ||
1218 | &mix->line_mute, 1); | ||
1219 | irq = tumbler_find_device("headphone-detect", | ||
1220 | NULL, &mix->hp_detect, 0); | ||
1119 | if (irq < 0) | 1221 | if (irq < 0) |
1120 | irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 1); | 1222 | irq = tumbler_find_device("headphone-detect", |
1223 | NULL, &mix->hp_detect, 1); | ||
1121 | if (irq < 0) | 1224 | if (irq < 0) |
1122 | irq = tumbler_find_device("keywest-gpio15", &mix->hp_detect, 1); | 1225 | irq = tumbler_find_device("keywest-gpio15", |
1226 | NULL, &mix->hp_detect, 1); | ||
1227 | mix->headphone_irq = irq; | ||
1228 | irq = tumbler_find_device("line-output-detect", | ||
1229 | NULL, &mix->line_detect, 0); | ||
1230 | if (irq < 0) | ||
1231 | irq = tumbler_find_device("line-output-detect", | ||
1232 | NULL, &mix->line_detect, 1); | ||
1233 | mix->lineout_irq = irq; | ||
1123 | 1234 | ||
1124 | tumbler_reset_audio(chip); | 1235 | tumbler_reset_audio(chip); |
1125 | |||
1126 | /* activate headphone status interrupts */ | ||
1127 | if (irq >= 0) { | ||
1128 | unsigned char val; | ||
1129 | if ((err = request_irq(irq, headphone_intr, 0, | ||
1130 | "Tumbler Headphone Detection", chip)) < 0) | ||
1131 | return err; | ||
1132 | /* activate headphone status interrupts */ | ||
1133 | val = do_gpio_read(&mix->hp_detect); | ||
1134 | do_gpio_write(&mix->hp_detect, val | 0x80); | ||
1135 | } | ||
1136 | mix->headphone_irq = irq; | ||
1137 | 1236 | ||
1138 | return 0; | 1237 | return 0; |
1139 | } | 1238 | } |
@@ -1146,6 +1245,8 @@ static void tumbler_cleanup(pmac_t *chip) | |||
1146 | 1245 | ||
1147 | if (mix->headphone_irq >= 0) | 1246 | if (mix->headphone_irq >= 0) |
1148 | free_irq(mix->headphone_irq, chip); | 1247 | free_irq(mix->headphone_irq, chip); |
1248 | if (mix->lineout_irq >= 0) | ||
1249 | free_irq(mix->lineout_irq, chip); | ||
1149 | tumbler_gpio_free(&mix->audio_reset); | 1250 | tumbler_gpio_free(&mix->audio_reset); |
1150 | tumbler_gpio_free(&mix->amp_mute); | 1251 | tumbler_gpio_free(&mix->amp_mute); |
1151 | tumbler_gpio_free(&mix->hp_mute); | 1252 | tumbler_gpio_free(&mix->hp_mute); |
@@ -1207,6 +1308,8 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1207 | else | 1308 | else |
1208 | mix->i2c.addr = TAS_I2C_ADDR; | 1309 | mix->i2c.addr = TAS_I2C_ADDR; |
1209 | 1310 | ||
1311 | DBG("(I) TAS i2c address is: %x\n", mix->i2c.addr); | ||
1312 | |||
1210 | if (chip->model == PMAC_TUMBLER) { | 1313 | if (chip->model == PMAC_TUMBLER) { |
1211 | mix->i2c.init_client = tumbler_init_client; | 1314 | mix->i2c.init_client = tumbler_init_client; |
1212 | mix->i2c.name = "TAS3001c"; | 1315 | mix->i2c.name = "TAS3001c"; |
@@ -1242,6 +1345,11 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1242 | chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); | 1345 | chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); |
1243 | if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) | 1346 | if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) |
1244 | return err; | 1347 | return err; |
1348 | if (mix->line_mute.addr != 0) { | ||
1349 | chip->lineout_sw_ctl = snd_ctl_new1(&tumbler_lineout_sw, chip); | ||
1350 | if ((err = snd_ctl_add(chip->card, chip->lineout_sw_ctl)) < 0) | ||
1351 | return err; | ||
1352 | } | ||
1245 | chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); | 1353 | chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); |
1246 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) | 1354 | if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) |
1247 | return err; | 1355 | return err; |
@@ -1254,11 +1362,32 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) | |||
1254 | INIT_WORK(&device_change, device_change_handler, (void *)chip); | 1362 | INIT_WORK(&device_change, device_change_handler, (void *)chip); |
1255 | 1363 | ||
1256 | #ifdef PMAC_SUPPORT_AUTOMUTE | 1364 | #ifdef PMAC_SUPPORT_AUTOMUTE |
1257 | if (mix->headphone_irq >=0 && (err = snd_pmac_add_automute(chip)) < 0) | 1365 | if ((mix->headphone_irq >=0 || mix->lineout_irq >= 0) |
1366 | && (err = snd_pmac_add_automute(chip)) < 0) | ||
1258 | return err; | 1367 | return err; |
1259 | chip->detect_headphone = tumbler_detect_headphone; | 1368 | chip->detect_headphone = tumbler_detect_headphone; |
1260 | chip->update_automute = tumbler_update_automute; | 1369 | chip->update_automute = tumbler_update_automute; |
1261 | tumbler_update_automute(chip, 0); /* update the status only */ | 1370 | tumbler_update_automute(chip, 0); /* update the status only */ |
1371 | |||
1372 | /* activate headphone status interrupts */ | ||
1373 | if (mix->headphone_irq >= 0) { | ||
1374 | unsigned char val; | ||
1375 | if ((err = request_irq(mix->headphone_irq, headphone_intr, 0, | ||
1376 | "Sound Headphone Detection", chip)) < 0) | ||
1377 | return 0; | ||
1378 | /* activate headphone status interrupts */ | ||
1379 | val = do_gpio_read(&mix->hp_detect); | ||
1380 | do_gpio_write(&mix->hp_detect, val | 0x80); | ||
1381 | } | ||
1382 | if (mix->lineout_irq >= 0) { | ||
1383 | unsigned char val; | ||
1384 | if ((err = request_irq(mix->lineout_irq, headphone_intr, 0, | ||
1385 | "Sound Lineout Detection", chip)) < 0) | ||
1386 | return 0; | ||
1387 | /* activate headphone status interrupts */ | ||
1388 | val = do_gpio_read(&mix->line_detect); | ||
1389 | do_gpio_write(&mix->line_detect, val | 0x80); | ||
1390 | } | ||
1262 | #endif | 1391 | #endif |
1263 | 1392 | ||
1264 | return 0; | 1393 | return 0; |