aboutsummaryrefslogtreecommitdiffstats
path: root/sound/ppc/pmac.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-04-16 18:24:32 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:24:32 -0400
commit7bbd827750e630003896c96d0212962276ee5d91 (patch)
tree71bb72cddbb08f9de68b2c7c05b4f5c03e8ed0bd /sound/ppc/pmac.c
parentb20af5f59797796d28b701f5d337e47c8a142eb2 (diff)
[PATCH] ppc64: very basic desktop g5 sound support
This patch hacks the current PowerMac Alsa driver to add some basic support of analog sound output to some desktop G5s. It has severe limitations though: - Only 44100Khz 16 bits - Only work on G5 models using a TAS3004 analog code, that is early single CPU desktops and all dual CPU desktops at this date, but none of the more recent ones like iMac G5. - It does analog only, no digital/SPDIF support at all, no native AC3 support Better support would require a complete rewrite of the driver (which I am working on, but don't hold your breath), to properly support the diversity of apple sound HW setup, including dual codecs, several i2s busses, all the new codecs used in the new machines, proper clock switching with digital, etc etc etc... This patch applies on top of the other PowerMac sound patches I posted in the past couple of days (new powerbook support and sleep fixes). Note: This is a FAQ entry for PowerMac sound support with TI codecs: They have a feature called "DRC" which is automatically enabled for the internal speaker (at least when auto mute control is enabled) which will cause your sound to fade out to nothing after half a second of playback if you don't set a proper "DRC Range" in the mixer. So if you have a problem like that, check alsamixer and raise your DRC Range to something reasonable. Note2: This patch will also add auto-mute of the speaker when line-out jack is used on some earlier desktop G4s (and on the G5) in addition to the headphone jack. If that behaviour isn't what you want, just disable auto-muting and use the manual mute controls in alsamixer. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'sound/ppc/pmac.c')
-rw-r--r--sound/ppc/pmac.c177
1 files changed, 119 insertions, 58 deletions
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 */
60static int snd_pmac_dbdma_alloc(pmac_dbdma_t *rec, int size) 59static 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
72static void snd_pmac_dbdma_free(pmac_dbdma_t *rec) 75static 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)
761static void snd_pmac_sound_feature(pmac_t *chip, int enable) 766static 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
787static int snd_pmac_free(pmac_t *chip) 775static 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}