diff options
Diffstat (limited to 'sound/ppc/pmac.c')
-rw-r--r-- | sound/ppc/pmac.c | 177 |
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 | */ |
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 | } |