diff options
| -rw-r--r-- | sound/pci/hda/hda_intel.c | 132 |
1 files changed, 109 insertions, 23 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 4cea6bb6fade..418bfc0eb0a3 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -415,6 +415,8 @@ struct azx_dev { | |||
| 415 | unsigned int opened :1; | 415 | unsigned int opened :1; |
| 416 | unsigned int running :1; | 416 | unsigned int running :1; |
| 417 | unsigned int irq_pending :1; | 417 | unsigned int irq_pending :1; |
| 418 | unsigned int prepared:1; | ||
| 419 | unsigned int locked:1; | ||
| 418 | /* | 420 | /* |
| 419 | * For VIA: | 421 | * For VIA: |
| 420 | * A flag to ensure DMA position is 0 | 422 | * A flag to ensure DMA position is 0 |
| @@ -426,8 +428,25 @@ struct azx_dev { | |||
| 426 | 428 | ||
| 427 | struct timecounter azx_tc; | 429 | struct timecounter azx_tc; |
| 428 | struct cyclecounter azx_cc; | 430 | struct cyclecounter azx_cc; |
| 431 | |||
| 432 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
| 433 | struct mutex dsp_mutex; | ||
| 434 | #endif | ||
| 429 | }; | 435 | }; |
| 430 | 436 | ||
| 437 | /* DSP lock helpers */ | ||
| 438 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
| 439 | #define dsp_lock_init(dev) mutex_init(&(dev)->dsp_mutex) | ||
| 440 | #define dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) | ||
| 441 | #define dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) | ||
| 442 | #define dsp_is_locked(dev) ((dev)->locked) | ||
| 443 | #else | ||
| 444 | #define dsp_lock_init(dev) do {} while (0) | ||
| 445 | #define dsp_lock(dev) do {} while (0) | ||
| 446 | #define dsp_unlock(dev) do {} while (0) | ||
| 447 | #define dsp_is_locked(dev) 0 | ||
| 448 | #endif | ||
| 449 | |||
| 431 | /* CORB/RIRB */ | 450 | /* CORB/RIRB */ |
| 432 | struct azx_rb { | 451 | struct azx_rb { |
| 433 | u32 *buf; /* CORB/RIRB buffer | 452 | u32 *buf; /* CORB/RIRB buffer |
| @@ -527,6 +546,10 @@ struct azx { | |||
| 527 | 546 | ||
| 528 | /* card list (for power_save trigger) */ | 547 | /* card list (for power_save trigger) */ |
| 529 | struct list_head list; | 548 | struct list_head list; |
| 549 | |||
| 550 | #ifdef CONFIG_SND_HDA_DSP_LOADER | ||
| 551 | struct azx_dev saved_azx_dev; | ||
| 552 | #endif | ||
| 530 | }; | 553 | }; |
| 531 | 554 | ||
| 532 | #define CREATE_TRACE_POINTS | 555 | #define CREATE_TRACE_POINTS |
| @@ -1793,15 +1816,25 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream) | |||
| 1793 | dev = chip->capture_index_offset; | 1816 | dev = chip->capture_index_offset; |
| 1794 | nums = chip->capture_streams; | 1817 | nums = chip->capture_streams; |
| 1795 | } | 1818 | } |
| 1796 | for (i = 0; i < nums; i++, dev++) | 1819 | for (i = 0; i < nums; i++, dev++) { |
| 1797 | if (!chip->azx_dev[dev].opened) { | 1820 | struct azx_dev *azx_dev = &chip->azx_dev[dev]; |
| 1798 | res = &chip->azx_dev[dev]; | 1821 | dsp_lock(azx_dev); |
| 1799 | if (res->assigned_key == key) | 1822 | if (!azx_dev->opened && !dsp_is_locked(azx_dev)) { |
| 1800 | break; | 1823 | res = azx_dev; |
| 1824 | if (res->assigned_key == key) { | ||
| 1825 | res->opened = 1; | ||
| 1826 | res->assigned_key = key; | ||
| 1827 | dsp_unlock(azx_dev); | ||
| 1828 | return azx_dev; | ||
| 1829 | } | ||
| 1801 | } | 1830 | } |
| 1831 | dsp_unlock(azx_dev); | ||
| 1832 | } | ||
| 1802 | if (res) { | 1833 | if (res) { |
| 1834 | dsp_lock(res); | ||
| 1803 | res->opened = 1; | 1835 | res->opened = 1; |
| 1804 | res->assigned_key = key; | 1836 | res->assigned_key = key; |
| 1837 | dsp_unlock(res); | ||
| 1805 | } | 1838 | } |
| 1806 | return res; | 1839 | return res; |
| 1807 | } | 1840 | } |
| @@ -2009,6 +2042,12 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 2009 | struct azx_dev *azx_dev = get_azx_dev(substream); | 2042 | struct azx_dev *azx_dev = get_azx_dev(substream); |
| 2010 | int ret; | 2043 | int ret; |
| 2011 | 2044 | ||
| 2045 | dsp_lock(azx_dev); | ||
| 2046 | if (dsp_is_locked(azx_dev)) { | ||
| 2047 | ret = -EBUSY; | ||
| 2048 | goto unlock; | ||
| 2049 | } | ||
| 2050 | |||
| 2012 | mark_runtime_wc(chip, azx_dev, substream, false); | 2051 | mark_runtime_wc(chip, azx_dev, substream, false); |
| 2013 | azx_dev->bufsize = 0; | 2052 | azx_dev->bufsize = 0; |
| 2014 | azx_dev->period_bytes = 0; | 2053 | azx_dev->period_bytes = 0; |
| @@ -2016,8 +2055,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 2016 | ret = snd_pcm_lib_malloc_pages(substream, | 2055 | ret = snd_pcm_lib_malloc_pages(substream, |
| 2017 | params_buffer_bytes(hw_params)); | 2056 | params_buffer_bytes(hw_params)); |
| 2018 | if (ret < 0) | 2057 | if (ret < 0) |
| 2019 | return ret; | 2058 | goto unlock; |
| 2020 | mark_runtime_wc(chip, azx_dev, substream, true); | 2059 | mark_runtime_wc(chip, azx_dev, substream, true); |
| 2060 | unlock: | ||
| 2061 | dsp_unlock(azx_dev); | ||
| 2021 | return ret; | 2062 | return ret; |
| 2022 | } | 2063 | } |
| 2023 | 2064 | ||
| @@ -2029,16 +2070,21 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
| 2029 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 2070 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; |
| 2030 | 2071 | ||
| 2031 | /* reset BDL address */ | 2072 | /* reset BDL address */ |
| 2032 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 2073 | dsp_lock(azx_dev); |
| 2033 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 2074 | if (!dsp_is_locked(azx_dev)) { |
| 2034 | azx_sd_writel(azx_dev, SD_CTL, 0); | 2075 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
| 2035 | azx_dev->bufsize = 0; | 2076 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
| 2036 | azx_dev->period_bytes = 0; | 2077 | azx_sd_writel(azx_dev, SD_CTL, 0); |
| 2037 | azx_dev->format_val = 0; | 2078 | azx_dev->bufsize = 0; |
| 2079 | azx_dev->period_bytes = 0; | ||
| 2080 | azx_dev->format_val = 0; | ||
| 2081 | } | ||
| 2038 | 2082 | ||
| 2039 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); | 2083 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); |
| 2040 | 2084 | ||
| 2041 | mark_runtime_wc(chip, azx_dev, substream, false); | 2085 | mark_runtime_wc(chip, azx_dev, substream, false); |
| 2086 | azx_dev->prepared = 0; | ||
| 2087 | dsp_unlock(azx_dev); | ||
| 2042 | return snd_pcm_lib_free_pages(substream); | 2088 | return snd_pcm_lib_free_pages(substream); |
| 2043 | } | 2089 | } |
| 2044 | 2090 | ||
| @@ -2055,6 +2101,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 2055 | snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); | 2101 | snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid); |
| 2056 | unsigned short ctls = spdif ? spdif->ctls : 0; | 2102 | unsigned short ctls = spdif ? spdif->ctls : 0; |
| 2057 | 2103 | ||
| 2104 | dsp_lock(azx_dev); | ||
| 2105 | if (dsp_is_locked(azx_dev)) { | ||
| 2106 | err = -EBUSY; | ||
| 2107 | goto unlock; | ||
| 2108 | } | ||
| 2109 | |||
| 2058 | azx_stream_reset(chip, azx_dev); | 2110 | azx_stream_reset(chip, azx_dev); |
| 2059 | format_val = snd_hda_calc_stream_format(runtime->rate, | 2111 | format_val = snd_hda_calc_stream_format(runtime->rate, |
| 2060 | runtime->channels, | 2112 | runtime->channels, |
| @@ -2065,7 +2117,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 2065 | snd_printk(KERN_ERR SFX | 2117 | snd_printk(KERN_ERR SFX |
| 2066 | "%s: invalid format_val, rate=%d, ch=%d, format=%d\n", | 2118 | "%s: invalid format_val, rate=%d, ch=%d, format=%d\n", |
| 2067 | pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format); | 2119 | pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format); |
| 2068 | return -EINVAL; | 2120 | err = -EINVAL; |
| 2121 | goto unlock; | ||
| 2069 | } | 2122 | } |
| 2070 | 2123 | ||
| 2071 | bufsize = snd_pcm_lib_buffer_bytes(substream); | 2124 | bufsize = snd_pcm_lib_buffer_bytes(substream); |
| @@ -2084,7 +2137,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 2084 | azx_dev->no_period_wakeup = runtime->no_period_wakeup; | 2137 | azx_dev->no_period_wakeup = runtime->no_period_wakeup; |
| 2085 | err = azx_setup_periods(chip, substream, azx_dev); | 2138 | err = azx_setup_periods(chip, substream, azx_dev); |
| 2086 | if (err < 0) | 2139 | if (err < 0) |
| 2087 | return err; | 2140 | goto unlock; |
| 2088 | } | 2141 | } |
| 2089 | 2142 | ||
| 2090 | /* wallclk has 24Mhz clock source */ | 2143 | /* wallclk has 24Mhz clock source */ |
| @@ -2101,8 +2154,14 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 2101 | if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && | 2154 | if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) && |
| 2102 | stream_tag > chip->capture_streams) | 2155 | stream_tag > chip->capture_streams) |
| 2103 | stream_tag -= chip->capture_streams; | 2156 | stream_tag -= chip->capture_streams; |
| 2104 | return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, | 2157 | err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, |
| 2105 | azx_dev->format_val, substream); | 2158 | azx_dev->format_val, substream); |
| 2159 | |||
| 2160 | unlock: | ||
| 2161 | if (!err) | ||
| 2162 | azx_dev->prepared = 1; | ||
| 2163 | dsp_unlock(azx_dev); | ||
| 2164 | return err; | ||
| 2106 | } | 2165 | } |
| 2107 | 2166 | ||
| 2108 | static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 2167 | static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
| @@ -2117,6 +2176,9 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 2117 | azx_dev = get_azx_dev(substream); | 2176 | azx_dev = get_azx_dev(substream); |
| 2118 | trace_azx_pcm_trigger(chip, azx_dev, cmd); | 2177 | trace_azx_pcm_trigger(chip, azx_dev, cmd); |
| 2119 | 2178 | ||
| 2179 | if (dsp_is_locked(azx_dev) || !azx_dev->prepared) | ||
| 2180 | return -EPIPE; | ||
| 2181 | |||
| 2120 | switch (cmd) { | 2182 | switch (cmd) { |
| 2121 | case SNDRV_PCM_TRIGGER_START: | 2183 | case SNDRV_PCM_TRIGGER_START: |
| 2122 | rstart = 1; | 2184 | rstart = 1; |
| @@ -2621,17 +2683,27 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | |||
| 2621 | struct azx_dev *azx_dev; | 2683 | struct azx_dev *azx_dev; |
| 2622 | int err; | 2684 | int err; |
| 2623 | 2685 | ||
| 2624 | if (snd_hda_lock_devices(bus)) | 2686 | azx_dev = azx_get_dsp_loader_dev(chip); |
| 2625 | return -EBUSY; | 2687 | |
| 2688 | dsp_lock(azx_dev); | ||
| 2689 | spin_lock_irq(&chip->reg_lock); | ||
| 2690 | if (azx_dev->running || azx_dev->locked) { | ||
| 2691 | spin_unlock_irq(&chip->reg_lock); | ||
| 2692 | err = -EBUSY; | ||
| 2693 | goto unlock; | ||
| 2694 | } | ||
| 2695 | azx_dev->prepared = 0; | ||
| 2696 | chip->saved_azx_dev = *azx_dev; | ||
| 2697 | azx_dev->locked = 1; | ||
| 2698 | spin_unlock_irq(&chip->reg_lock); | ||
| 2626 | 2699 | ||
| 2627 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, | 2700 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, |
| 2628 | snd_dma_pci_data(chip->pci), | 2701 | snd_dma_pci_data(chip->pci), |
| 2629 | byte_size, bufp); | 2702 | byte_size, bufp); |
| 2630 | if (err < 0) | 2703 | if (err < 0) |
| 2631 | goto unlock; | 2704 | goto err_alloc; |
| 2632 | 2705 | ||
| 2633 | mark_pages_wc(chip, bufp, true); | 2706 | mark_pages_wc(chip, bufp, true); |
| 2634 | azx_dev = azx_get_dsp_loader_dev(chip); | ||
| 2635 | azx_dev->bufsize = byte_size; | 2707 | azx_dev->bufsize = byte_size; |
| 2636 | azx_dev->period_bytes = byte_size; | 2708 | azx_dev->period_bytes = byte_size; |
| 2637 | azx_dev->format_val = format; | 2709 | azx_dev->format_val = format; |
| @@ -2649,13 +2721,20 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format, | |||
| 2649 | goto error; | 2721 | goto error; |
| 2650 | 2722 | ||
| 2651 | azx_setup_controller(chip, azx_dev); | 2723 | azx_setup_controller(chip, azx_dev); |
| 2724 | dsp_unlock(azx_dev); | ||
| 2652 | return azx_dev->stream_tag; | 2725 | return azx_dev->stream_tag; |
| 2653 | 2726 | ||
| 2654 | error: | 2727 | error: |
| 2655 | mark_pages_wc(chip, bufp, false); | 2728 | mark_pages_wc(chip, bufp, false); |
| 2656 | snd_dma_free_pages(bufp); | 2729 | snd_dma_free_pages(bufp); |
| 2657 | unlock: | 2730 | err_alloc: |
| 2658 | snd_hda_unlock_devices(bus); | 2731 | spin_lock_irq(&chip->reg_lock); |
| 2732 | if (azx_dev->opened) | ||
| 2733 | *azx_dev = chip->saved_azx_dev; | ||
| 2734 | azx_dev->locked = 0; | ||
| 2735 | spin_unlock_irq(&chip->reg_lock); | ||
| 2736 | unlock: | ||
| 2737 | dsp_unlock(azx_dev); | ||
| 2659 | return err; | 2738 | return err; |
| 2660 | } | 2739 | } |
| 2661 | 2740 | ||
| @@ -2677,9 +2756,10 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus, | |||
| 2677 | struct azx *chip = bus->private_data; | 2756 | struct azx *chip = bus->private_data; |
| 2678 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); | 2757 | struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip); |
| 2679 | 2758 | ||
| 2680 | if (!dmab->area) | 2759 | if (!dmab->area || !azx_dev->locked) |
| 2681 | return; | 2760 | return; |
| 2682 | 2761 | ||
| 2762 | dsp_lock(azx_dev); | ||
| 2683 | /* reset BDL address */ | 2763 | /* reset BDL address */ |
| 2684 | azx_sd_writel(azx_dev, SD_BDLPL, 0); | 2764 | azx_sd_writel(azx_dev, SD_BDLPL, 0); |
| 2685 | azx_sd_writel(azx_dev, SD_BDLPU, 0); | 2765 | azx_sd_writel(azx_dev, SD_BDLPU, 0); |
| @@ -2692,7 +2772,12 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus, | |||
| 2692 | snd_dma_free_pages(dmab); | 2772 | snd_dma_free_pages(dmab); |
| 2693 | dmab->area = NULL; | 2773 | dmab->area = NULL; |
| 2694 | 2774 | ||
| 2695 | snd_hda_unlock_devices(bus); | 2775 | spin_lock_irq(&chip->reg_lock); |
| 2776 | if (azx_dev->opened) | ||
| 2777 | *azx_dev = chip->saved_azx_dev; | ||
| 2778 | azx_dev->locked = 0; | ||
| 2779 | spin_unlock_irq(&chip->reg_lock); | ||
| 2780 | dsp_unlock(azx_dev); | ||
| 2696 | } | 2781 | } |
| 2697 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ | 2782 | #endif /* CONFIG_SND_HDA_DSP_LOADER */ |
| 2698 | 2783 | ||
| @@ -3481,6 +3566,7 @@ static int azx_first_init(struct azx *chip) | |||
| 3481 | } | 3566 | } |
| 3482 | 3567 | ||
| 3483 | for (i = 0; i < chip->num_streams; i++) { | 3568 | for (i = 0; i < chip->num_streams; i++) { |
| 3569 | dsp_lock_init(&chip->azx_dev[i]); | ||
| 3484 | /* allocate memory for the BDL for each stream */ | 3570 | /* allocate memory for the BDL for each stream */ |
| 3485 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, | 3571 | err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, |
| 3486 | snd_dma_pci_data(chip->pci), | 3572 | snd_dma_pci_data(chip->pci), |
