| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * intel_hdmi_audio.c - Intel HDMI audio driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 7 | 8 | * Vaibhav Agarwal <vaibhav.agarwal@intel.com> |
|---|
| 8 | 9 | * Jerome Anand <jerome.anand@intel.com> |
|---|
| 9 | 10 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 12 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 13 | | - * the Free Software Foundation; version 2 of the License. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 16 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 18 | | - * General Public License for more details. |
|---|
| 19 | 11 | * |
|---|
| 20 | 12 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 21 | 13 | * ALSA driver for Intel HDMI audio |
|---|
| .. | .. |
|---|
| 30 | 22 | #include <linux/pm_runtime.h> |
|---|
| 31 | 23 | #include <linux/dma-mapping.h> |
|---|
| 32 | 24 | #include <linux/delay.h> |
|---|
| 33 | | -#include <asm/set_memory.h> |
|---|
| 34 | 25 | #include <sound/core.h> |
|---|
| 35 | 26 | #include <sound/asoundef.h> |
|---|
| 36 | 27 | #include <sound/pcm.h> |
|---|
| .. | .. |
|---|
| 1141 | 1132 | struct snd_pcm_hw_params *hw_params) |
|---|
| 1142 | 1133 | { |
|---|
| 1143 | 1134 | struct snd_intelhad *intelhaddata; |
|---|
| 1144 | | - unsigned long addr; |
|---|
| 1145 | | - int pages, buf_size, retval; |
|---|
| 1135 | + int buf_size; |
|---|
| 1146 | 1136 | |
|---|
| 1147 | 1137 | intelhaddata = snd_pcm_substream_chip(substream); |
|---|
| 1148 | 1138 | buf_size = params_buffer_bytes(hw_params); |
|---|
| 1149 | | - retval = snd_pcm_lib_malloc_pages(substream, buf_size); |
|---|
| 1150 | | - if (retval < 0) |
|---|
| 1151 | | - return retval; |
|---|
| 1152 | 1139 | dev_dbg(intelhaddata->dev, "%s:allocated memory = %d\n", |
|---|
| 1153 | 1140 | __func__, buf_size); |
|---|
| 1154 | | - /* mark the pages as uncached region */ |
|---|
| 1155 | | - addr = (unsigned long) substream->runtime->dma_area; |
|---|
| 1156 | | - pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / PAGE_SIZE; |
|---|
| 1157 | | - retval = set_memory_uc(addr, pages); |
|---|
| 1158 | | - if (retval) { |
|---|
| 1159 | | - dev_err(intelhaddata->dev, "set_memory_uc failed.Error:%d\n", |
|---|
| 1160 | | - retval); |
|---|
| 1161 | | - return retval; |
|---|
| 1162 | | - } |
|---|
| 1163 | | - memset(substream->runtime->dma_area, 0, buf_size); |
|---|
| 1164 | | - |
|---|
| 1165 | | - return retval; |
|---|
| 1141 | + return 0; |
|---|
| 1166 | 1142 | } |
|---|
| 1167 | 1143 | |
|---|
| 1168 | 1144 | /* |
|---|
| .. | .. |
|---|
| 1171 | 1147 | static int had_pcm_hw_free(struct snd_pcm_substream *substream) |
|---|
| 1172 | 1148 | { |
|---|
| 1173 | 1149 | struct snd_intelhad *intelhaddata; |
|---|
| 1174 | | - unsigned long addr; |
|---|
| 1175 | | - u32 pages; |
|---|
| 1176 | 1150 | |
|---|
| 1177 | 1151 | intelhaddata = snd_pcm_substream_chip(substream); |
|---|
| 1178 | 1152 | had_do_reset(intelhaddata); |
|---|
| 1179 | 1153 | |
|---|
| 1180 | | - /* mark back the pages as cached/writeback region before the free */ |
|---|
| 1181 | | - if (substream->runtime->dma_area != NULL) { |
|---|
| 1182 | | - addr = (unsigned long) substream->runtime->dma_area; |
|---|
| 1183 | | - pages = (substream->runtime->dma_bytes + PAGE_SIZE - 1) / |
|---|
| 1184 | | - PAGE_SIZE; |
|---|
| 1185 | | - set_memory_wb(addr, pages); |
|---|
| 1186 | | - return snd_pcm_lib_free_pages(substream); |
|---|
| 1187 | | - } |
|---|
| 1188 | 1154 | return 0; |
|---|
| 1189 | 1155 | } |
|---|
| 1190 | 1156 | |
|---|
| .. | .. |
|---|
| 1310 | 1276 | { |
|---|
| 1311 | 1277 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
|---|
| 1312 | 1278 | return remap_pfn_range(vma, vma->vm_start, |
|---|
| 1313 | | - substream->dma_buffer.addr >> PAGE_SHIFT, |
|---|
| 1279 | + substream->runtime->dma_addr >> PAGE_SHIFT, |
|---|
| 1314 | 1280 | vma->vm_end - vma->vm_start, vma->vm_page_prot); |
|---|
| 1315 | 1281 | } |
|---|
| 1316 | 1282 | |
|---|
| .. | .. |
|---|
| 1320 | 1286 | static const struct snd_pcm_ops had_pcm_ops = { |
|---|
| 1321 | 1287 | .open = had_pcm_open, |
|---|
| 1322 | 1288 | .close = had_pcm_close, |
|---|
| 1323 | | - .ioctl = snd_pcm_lib_ioctl, |
|---|
| 1324 | 1289 | .hw_params = had_pcm_hw_params, |
|---|
| 1325 | 1290 | .hw_free = had_pcm_hw_free, |
|---|
| 1326 | 1291 | .prepare = had_pcm_prepare, |
|---|
| .. | .. |
|---|
| 1671 | 1636 | * PM callbacks |
|---|
| 1672 | 1637 | */ |
|---|
| 1673 | 1638 | |
|---|
| 1674 | | -static int hdmi_lpe_audio_runtime_suspend(struct device *dev) |
|---|
| 1675 | | -{ |
|---|
| 1676 | | - struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); |
|---|
| 1677 | | - int port; |
|---|
| 1678 | | - |
|---|
| 1679 | | - for_each_port(card_ctx, port) { |
|---|
| 1680 | | - struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; |
|---|
| 1681 | | - struct snd_pcm_substream *substream; |
|---|
| 1682 | | - |
|---|
| 1683 | | - substream = had_substream_get(ctx); |
|---|
| 1684 | | - if (substream) { |
|---|
| 1685 | | - snd_pcm_suspend(substream); |
|---|
| 1686 | | - had_substream_put(ctx); |
|---|
| 1687 | | - } |
|---|
| 1688 | | - } |
|---|
| 1689 | | - |
|---|
| 1690 | | - return 0; |
|---|
| 1691 | | -} |
|---|
| 1692 | | - |
|---|
| 1693 | 1639 | static int __maybe_unused hdmi_lpe_audio_suspend(struct device *dev) |
|---|
| 1694 | 1640 | { |
|---|
| 1695 | 1641 | struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); |
|---|
| 1696 | | - int err; |
|---|
| 1697 | 1642 | |
|---|
| 1698 | | - err = hdmi_lpe_audio_runtime_suspend(dev); |
|---|
| 1699 | | - if (!err) |
|---|
| 1700 | | - snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D3hot); |
|---|
| 1701 | | - return err; |
|---|
| 1702 | | -} |
|---|
| 1643 | + snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D3hot); |
|---|
| 1703 | 1644 | |
|---|
| 1704 | | -static int hdmi_lpe_audio_runtime_resume(struct device *dev) |
|---|
| 1705 | | -{ |
|---|
| 1706 | | - pm_runtime_mark_last_busy(dev); |
|---|
| 1707 | 1645 | return 0; |
|---|
| 1708 | 1646 | } |
|---|
| 1709 | 1647 | |
|---|
| .. | .. |
|---|
| 1711 | 1649 | { |
|---|
| 1712 | 1650 | struct snd_intelhad_card *card_ctx = dev_get_drvdata(dev); |
|---|
| 1713 | 1651 | |
|---|
| 1714 | | - hdmi_lpe_audio_runtime_resume(dev); |
|---|
| 1652 | + pm_runtime_mark_last_busy(dev); |
|---|
| 1653 | + |
|---|
| 1715 | 1654 | snd_power_change_state(card_ctx->card, SNDRV_CTL_POWER_D0); |
|---|
| 1655 | + |
|---|
| 1716 | 1656 | return 0; |
|---|
| 1717 | 1657 | } |
|---|
| 1718 | 1658 | |
|---|
| .. | .. |
|---|
| 1764 | 1704 | |
|---|
| 1765 | 1705 | /* get resources */ |
|---|
| 1766 | 1706 | irq = platform_get_irq(pdev, 0); |
|---|
| 1767 | | - if (irq < 0) { |
|---|
| 1768 | | - dev_err(&pdev->dev, "Could not get irq resource: %d\n", irq); |
|---|
| 1707 | + if (irq < 0) |
|---|
| 1769 | 1708 | return irq; |
|---|
| 1770 | | - } |
|---|
| 1771 | 1709 | |
|---|
| 1772 | 1710 | res_mmio = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 1773 | 1711 | if (!res_mmio) { |
|---|
| .. | .. |
|---|
| 1813 | 1751 | __func__, (unsigned int)res_mmio->start, |
|---|
| 1814 | 1752 | (unsigned int)res_mmio->end); |
|---|
| 1815 | 1753 | |
|---|
| 1816 | | - card_ctx->mmio_start = ioremap_nocache(res_mmio->start, |
|---|
| 1754 | + card_ctx->mmio_start = ioremap(res_mmio->start, |
|---|
| 1817 | 1755 | (size_t)(resource_size(res_mmio))); |
|---|
| 1818 | 1756 | if (!card_ctx->mmio_start) { |
|---|
| 1819 | 1757 | dev_err(&pdev->dev, "Could not get ioremap\n"); |
|---|
| .. | .. |
|---|
| 1859 | 1797 | /* allocate dma pages; |
|---|
| 1860 | 1798 | * try to allocate 600k buffer as default which is large enough |
|---|
| 1861 | 1799 | */ |
|---|
| 1862 | | - snd_pcm_lib_preallocate_pages_for_all(pcm, |
|---|
| 1863 | | - SNDRV_DMA_TYPE_DEV, NULL, |
|---|
| 1864 | | - HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER); |
|---|
| 1800 | + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_UC, |
|---|
| 1801 | + card->dev, HAD_DEFAULT_BUFFER, |
|---|
| 1802 | + HAD_MAX_BUFFER); |
|---|
| 1865 | 1803 | |
|---|
| 1866 | 1804 | /* create controls */ |
|---|
| 1867 | 1805 | for (i = 0; i < ARRAY_SIZE(had_controls); i++) { |
|---|
| .. | .. |
|---|
| 1930 | 1868 | |
|---|
| 1931 | 1869 | static const struct dev_pm_ops hdmi_lpe_audio_pm = { |
|---|
| 1932 | 1870 | SET_SYSTEM_SLEEP_PM_OPS(hdmi_lpe_audio_suspend, hdmi_lpe_audio_resume) |
|---|
| 1933 | | - SET_RUNTIME_PM_OPS(hdmi_lpe_audio_runtime_suspend, |
|---|
| 1934 | | - hdmi_lpe_audio_runtime_resume, NULL) |
|---|
| 1935 | 1871 | }; |
|---|
| 1936 | 1872 | |
|---|
| 1937 | 1873 | static struct platform_driver hdmi_lpe_audio_driver = { |
|---|