diff options
author | Takashi Iwai <tiwai@suse.de> | 2018-08-08 16:31:52 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2018-08-28 07:56:48 -0400 |
commit | 4985ddbf1edb06f0dc4ae22e9886bde267925e6c (patch) | |
tree | 5dfd255e8643f2eff2504bc62e926db20db6e780 | |
parent | 193c7e14762a58003af7914183f9b963c0267788 (diff) |
ALSA: intel8x0: Use the new non-cached allocation for 440MX workaround
intel8x0 driver requires the non-cached pages for 440MX workaround,
and this can be implemented more easily with the new memalloc type,
SNDRV_DMA_TYPE_DEV_UC. This allows us to reduce lots of code.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/intel8x0.c | 89 |
1 files changed, 12 insertions, 77 deletions
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 5ee468d1aefe..9517f9b8f1d4 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
@@ -38,11 +38,6 @@ | |||
38 | #include <sound/ac97_codec.h> | 38 | #include <sound/ac97_codec.h> |
39 | #include <sound/info.h> | 39 | #include <sound/info.h> |
40 | #include <sound/initval.h> | 40 | #include <sound/initval.h> |
41 | /* for 440MX workaround */ | ||
42 | #include <asm/pgtable.h> | ||
43 | #ifdef CONFIG_X86 | ||
44 | #include <asm/set_memory.h> | ||
45 | #endif | ||
46 | 41 | ||
47 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); | 42 | MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); |
48 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); | 43 | MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455"); |
@@ -374,7 +369,6 @@ struct ichdev { | |||
374 | unsigned int ali_slot; /* ALI DMA slot */ | 369 | unsigned int ali_slot; /* ALI DMA slot */ |
375 | struct ac97_pcm *pcm; | 370 | struct ac97_pcm *pcm; |
376 | int pcm_open_flag; | 371 | int pcm_open_flag; |
377 | unsigned int page_attr_changed: 1; | ||
378 | unsigned int suspended: 1; | 372 | unsigned int suspended: 1; |
379 | }; | 373 | }; |
380 | 374 | ||
@@ -724,25 +718,6 @@ static void snd_intel8x0_setup_periods(struct intel8x0 *chip, struct ichdev *ich | |||
724 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); | 718 | iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI); |
725 | } | 719 | } |
726 | 720 | ||
727 | #ifdef __i386__ | ||
728 | /* | ||
729 | * Intel 82443MX running a 100MHz processor system bus has a hardware bug, | ||
730 | * which aborts PCI busmaster for audio transfer. A workaround is to set | ||
731 | * the pages as non-cached. For details, see the errata in | ||
732 | * http://download.intel.com/design/chipsets/specupdt/24505108.pdf | ||
733 | */ | ||
734 | static void fill_nocache(void *buf, int size, int nocache) | ||
735 | { | ||
736 | size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
737 | if (nocache) | ||
738 | set_pages_uc(virt_to_page(buf), size); | ||
739 | else | ||
740 | set_pages_wb(virt_to_page(buf), size); | ||
741 | } | ||
742 | #else | ||
743 | #define fill_nocache(buf, size, nocache) do { ; } while (0) | ||
744 | #endif | ||
745 | |||
746 | /* | 721 | /* |
747 | * Interrupt handler | 722 | * Interrupt handler |
748 | */ | 723 | */ |
@@ -938,23 +913,12 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream, | |||
938 | { | 913 | { |
939 | struct intel8x0 *chip = snd_pcm_substream_chip(substream); | 914 | struct intel8x0 *chip = snd_pcm_substream_chip(substream); |
940 | struct ichdev *ichdev = get_ichdev(substream); | 915 | struct ichdev *ichdev = get_ichdev(substream); |
941 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
942 | int dbl = params_rate(hw_params) > 48000; | 916 | int dbl = params_rate(hw_params) > 48000; |
943 | int err; | 917 | int err; |
944 | 918 | ||
945 | if (chip->fix_nocache && ichdev->page_attr_changed) { | ||
946 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); /* clear */ | ||
947 | ichdev->page_attr_changed = 0; | ||
948 | } | ||
949 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); | 919 | err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); |
950 | if (err < 0) | 920 | if (err < 0) |
951 | return err; | 921 | return err; |
952 | if (chip->fix_nocache) { | ||
953 | if (runtime->dma_area && ! ichdev->page_attr_changed) { | ||
954 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 1); | ||
955 | ichdev->page_attr_changed = 1; | ||
956 | } | ||
957 | } | ||
958 | if (ichdev->pcm_open_flag) { | 922 | if (ichdev->pcm_open_flag) { |
959 | snd_ac97_pcm_close(ichdev->pcm); | 923 | snd_ac97_pcm_close(ichdev->pcm); |
960 | ichdev->pcm_open_flag = 0; | 924 | ichdev->pcm_open_flag = 0; |
@@ -974,17 +938,12 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream, | |||
974 | 938 | ||
975 | static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream) | 939 | static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream) |
976 | { | 940 | { |
977 | struct intel8x0 *chip = snd_pcm_substream_chip(substream); | ||
978 | struct ichdev *ichdev = get_ichdev(substream); | 941 | struct ichdev *ichdev = get_ichdev(substream); |
979 | 942 | ||
980 | if (ichdev->pcm_open_flag) { | 943 | if (ichdev->pcm_open_flag) { |
981 | snd_ac97_pcm_close(ichdev->pcm); | 944 | snd_ac97_pcm_close(ichdev->pcm); |
982 | ichdev->pcm_open_flag = 0; | 945 | ichdev->pcm_open_flag = 0; |
983 | } | 946 | } |
984 | if (chip->fix_nocache && ichdev->page_attr_changed) { | ||
985 | fill_nocache(substream->runtime->dma_area, substream->runtime->dma_bytes, 0); | ||
986 | ichdev->page_attr_changed = 0; | ||
987 | } | ||
988 | return snd_pcm_lib_free_pages(substream); | 947 | return snd_pcm_lib_free_pages(substream); |
989 | } | 948 | } |
990 | 949 | ||
@@ -1510,6 +1469,9 @@ struct ich_pcm_table { | |||
1510 | int ac97_idx; | 1469 | int ac97_idx; |
1511 | }; | 1470 | }; |
1512 | 1471 | ||
1472 | #define intel8x0_dma_type(chip) \ | ||
1473 | ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_UC : SNDRV_DMA_TYPE_DEV) | ||
1474 | |||
1513 | static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device, | 1475 | static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device, |
1514 | struct ich_pcm_table *rec) | 1476 | struct ich_pcm_table *rec) |
1515 | { | 1477 | { |
@@ -1540,7 +1502,7 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device, | |||
1540 | strcpy(pcm->name, chip->card->shortname); | 1502 | strcpy(pcm->name, chip->card->shortname); |
1541 | chip->pcm[device] = pcm; | 1503 | chip->pcm[device] = pcm; |
1542 | 1504 | ||
1543 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1505 | snd_pcm_lib_preallocate_pages_for_all(pcm, intel8x0_dma_type(chip), |
1544 | snd_dma_pci_data(chip->pci), | 1506 | snd_dma_pci_data(chip->pci), |
1545 | rec->prealloc_size, rec->prealloc_max_size); | 1507 | rec->prealloc_size, rec->prealloc_max_size); |
1546 | 1508 | ||
@@ -2629,11 +2591,8 @@ static int snd_intel8x0_free(struct intel8x0 *chip) | |||
2629 | __hw_end: | 2591 | __hw_end: |
2630 | if (chip->irq >= 0) | 2592 | if (chip->irq >= 0) |
2631 | free_irq(chip->irq, chip); | 2593 | free_irq(chip->irq, chip); |
2632 | if (chip->bdbars.area) { | 2594 | if (chip->bdbars.area) |
2633 | if (chip->fix_nocache) | ||
2634 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0); | ||
2635 | snd_dma_free_pages(&chip->bdbars); | 2595 | snd_dma_free_pages(&chip->bdbars); |
2636 | } | ||
2637 | if (chip->addr) | 2596 | if (chip->addr) |
2638 | pci_iounmap(chip->pci, chip->addr); | 2597 | pci_iounmap(chip->pci, chip->addr); |
2639 | if (chip->bmaddr) | 2598 | if (chip->bmaddr) |
@@ -2657,17 +2616,6 @@ static int intel8x0_suspend(struct device *dev) | |||
2657 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 2616 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
2658 | for (i = 0; i < chip->pcm_devs; i++) | 2617 | for (i = 0; i < chip->pcm_devs; i++) |
2659 | snd_pcm_suspend_all(chip->pcm[i]); | 2618 | snd_pcm_suspend_all(chip->pcm[i]); |
2660 | /* clear nocache */ | ||
2661 | if (chip->fix_nocache) { | ||
2662 | for (i = 0; i < chip->bdbars_count; i++) { | ||
2663 | struct ichdev *ichdev = &chip->ichd[i]; | ||
2664 | if (ichdev->substream && ichdev->page_attr_changed) { | ||
2665 | struct snd_pcm_runtime *runtime = ichdev->substream->runtime; | ||
2666 | if (runtime->dma_area) | ||
2667 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 0); | ||
2668 | } | ||
2669 | } | ||
2670 | } | ||
2671 | for (i = 0; i < chip->ncodecs; i++) | 2619 | for (i = 0; i < chip->ncodecs; i++) |
2672 | snd_ac97_suspend(chip->ac97[i]); | 2620 | snd_ac97_suspend(chip->ac97[i]); |
2673 | if (chip->device_type == DEVICE_INTEL_ICH4) | 2621 | if (chip->device_type == DEVICE_INTEL_ICH4) |
@@ -2708,25 +2656,9 @@ static int intel8x0_resume(struct device *dev) | |||
2708 | ICH_PCM_SPDIF_1011); | 2656 | ICH_PCM_SPDIF_1011); |
2709 | } | 2657 | } |
2710 | 2658 | ||
2711 | /* refill nocache */ | ||
2712 | if (chip->fix_nocache) | ||
2713 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | ||
2714 | |||
2715 | for (i = 0; i < chip->ncodecs; i++) | 2659 | for (i = 0; i < chip->ncodecs; i++) |
2716 | snd_ac97_resume(chip->ac97[i]); | 2660 | snd_ac97_resume(chip->ac97[i]); |
2717 | 2661 | ||
2718 | /* refill nocache */ | ||
2719 | if (chip->fix_nocache) { | ||
2720 | for (i = 0; i < chip->bdbars_count; i++) { | ||
2721 | struct ichdev *ichdev = &chip->ichd[i]; | ||
2722 | if (ichdev->substream && ichdev->page_attr_changed) { | ||
2723 | struct snd_pcm_runtime *runtime = ichdev->substream->runtime; | ||
2724 | if (runtime->dma_area) | ||
2725 | fill_nocache(runtime->dma_area, runtime->dma_bytes, 1); | ||
2726 | } | ||
2727 | } | ||
2728 | } | ||
2729 | |||
2730 | /* resume status */ | 2662 | /* resume status */ |
2731 | for (i = 0; i < chip->bdbars_count; i++) { | 2663 | for (i = 0; i < chip->bdbars_count; i++) { |
2732 | struct ichdev *ichdev = &chip->ichd[i]; | 2664 | struct ichdev *ichdev = &chip->ichd[i]; |
@@ -3057,6 +2989,12 @@ static int snd_intel8x0_create(struct snd_card *card, | |||
3057 | 2989 | ||
3058 | chip->inside_vm = snd_intel8x0_inside_vm(pci); | 2990 | chip->inside_vm = snd_intel8x0_inside_vm(pci); |
3059 | 2991 | ||
2992 | /* | ||
2993 | * Intel 82443MX running a 100MHz processor system bus has a hardware | ||
2994 | * bug, which aborts PCI busmaster for audio transfer. A workaround | ||
2995 | * is to set the pages as non-cached. For details, see the errata in | ||
2996 | * http://download.intel.com/design/chipsets/specupdt/24505108.pdf | ||
2997 | */ | ||
3060 | if (pci->vendor == PCI_VENDOR_ID_INTEL && | 2998 | if (pci->vendor == PCI_VENDOR_ID_INTEL && |
3061 | pci->device == PCI_DEVICE_ID_INTEL_440MX) | 2999 | pci->device == PCI_DEVICE_ID_INTEL_440MX) |
3062 | chip->fix_nocache = 1; /* enable workaround */ | 3000 | chip->fix_nocache = 1; /* enable workaround */ |
@@ -3128,7 +3066,7 @@ static int snd_intel8x0_create(struct snd_card *card, | |||
3128 | 3066 | ||
3129 | /* allocate buffer descriptor lists */ | 3067 | /* allocate buffer descriptor lists */ |
3130 | /* the start of each lists must be aligned to 8 bytes */ | 3068 | /* the start of each lists must be aligned to 8 bytes */ |
3131 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | 3069 | if (snd_dma_alloc_pages(intel8x0_dma_type(chip), snd_dma_pci_data(pci), |
3132 | chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, | 3070 | chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2, |
3133 | &chip->bdbars) < 0) { | 3071 | &chip->bdbars) < 0) { |
3134 | snd_intel8x0_free(chip); | 3072 | snd_intel8x0_free(chip); |
@@ -3137,9 +3075,6 @@ static int snd_intel8x0_create(struct snd_card *card, | |||
3137 | } | 3075 | } |
3138 | /* tables must be aligned to 8 bytes here, but the kernel pages | 3076 | /* tables must be aligned to 8 bytes here, but the kernel pages |
3139 | are much bigger, so we don't care (on i386) */ | 3077 | are much bigger, so we don't care (on i386) */ |
3140 | /* workaround for 440MX */ | ||
3141 | if (chip->fix_nocache) | ||
3142 | fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 1); | ||
3143 | int_sta_masks = 0; | 3078 | int_sta_masks = 0; |
3144 | for (i = 0; i < chip->bdbars_count; i++) { | 3079 | for (i = 0; i < chip->bdbars_count; i++) { |
3145 | ichdev = &chip->ichd[i]; | 3080 | ichdev = &chip->ichd[i]; |