.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * AMD ALSA SoC PCM Driver for ACP 2.x |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright 2014-2015 Advanced Micro Devices, Inc. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms and conditions of the GNU General Public License, |
---|
8 | | - * version 2, as published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | 6 | */ |
---|
15 | 7 | |
---|
16 | 8 | #include <linux/module.h> |
---|
.. | .. |
---|
303 | 295 | } |
---|
304 | 296 | |
---|
305 | 297 | /* Create page table entries in ACP SRAM for the allocated memory */ |
---|
306 | | -static void acp_pte_config(void __iomem *acp_mmio, struct page *pg, |
---|
| 298 | +static void acp_pte_config(void __iomem *acp_mmio, dma_addr_t addr, |
---|
307 | 299 | u16 num_of_pages, u32 pte_offset) |
---|
308 | 300 | { |
---|
309 | 301 | u16 page_idx; |
---|
310 | | - u64 addr; |
---|
311 | 302 | u32 low; |
---|
312 | 303 | u32 high; |
---|
313 | 304 | u32 offset; |
---|
.. | .. |
---|
317 | 308 | /* Load the low address of page int ACP SRAM through SRBM */ |
---|
318 | 309 | acp_reg_write((offset + (page_idx * 8)), |
---|
319 | 310 | acp_mmio, mmACP_SRBM_Targ_Idx_Addr); |
---|
320 | | - addr = page_to_phys(pg); |
---|
321 | 311 | |
---|
322 | 312 | low = lower_32_bits(addr); |
---|
323 | 313 | high = upper_32_bits(addr); |
---|
.. | .. |
---|
333 | 323 | acp_reg_write(high, acp_mmio, mmACP_SRBM_Targ_Idx_Data); |
---|
334 | 324 | |
---|
335 | 325 | /* Move to next physically contiguos page */ |
---|
336 | | - pg++; |
---|
| 326 | + addr += PAGE_SIZE; |
---|
337 | 327 | } |
---|
338 | 328 | } |
---|
339 | 329 | |
---|
.. | .. |
---|
343 | 333 | { |
---|
344 | 334 | u16 ch_acp_sysmem, ch_acp_i2s; |
---|
345 | 335 | |
---|
346 | | - acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages, |
---|
| 336 | + acp_pte_config(acp_mmio, rtd->dma_addr, rtd->num_of_pages, |
---|
347 | 337 | rtd->pte_offset); |
---|
348 | 338 | |
---|
349 | 339 | if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) { |
---|
.. | .. |
---|
769 | 759 | return IRQ_NONE; |
---|
770 | 760 | } |
---|
771 | 761 | |
---|
772 | | -static int acp_dma_open(struct snd_pcm_substream *substream) |
---|
| 762 | +static int acp_dma_open(struct snd_soc_component *component, |
---|
| 763 | + struct snd_pcm_substream *substream) |
---|
773 | 764 | { |
---|
774 | 765 | u16 bank; |
---|
775 | 766 | int ret = 0; |
---|
776 | 767 | struct snd_pcm_runtime *runtime = substream->runtime; |
---|
777 | | - struct snd_soc_pcm_runtime *prtd = substream->private_data; |
---|
778 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd, |
---|
779 | | - DRV_NAME); |
---|
780 | 768 | struct audio_drv_data *intr_data = dev_get_drvdata(component->dev); |
---|
781 | 769 | struct audio_substream_data *adata = |
---|
782 | 770 | kzalloc(sizeof(struct audio_substream_data), GFP_KERNEL); |
---|
.. | .. |
---|
844 | 832 | return 0; |
---|
845 | 833 | } |
---|
846 | 834 | |
---|
847 | | -static int acp_dma_hw_params(struct snd_pcm_substream *substream, |
---|
| 835 | +static int acp_dma_hw_params(struct snd_soc_component *component, |
---|
| 836 | + struct snd_pcm_substream *substream, |
---|
848 | 837 | struct snd_pcm_hw_params *params) |
---|
849 | 838 | { |
---|
850 | | - int status; |
---|
851 | 839 | uint64_t size; |
---|
852 | 840 | u32 val = 0; |
---|
853 | | - struct page *pg; |
---|
854 | 841 | struct snd_pcm_runtime *runtime; |
---|
855 | 842 | struct audio_substream_data *rtd; |
---|
856 | | - struct snd_soc_pcm_runtime *prtd = substream->private_data; |
---|
857 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd, |
---|
858 | | - DRV_NAME); |
---|
| 843 | + struct snd_soc_pcm_runtime *prtd = asoc_substream_to_rtd(substream); |
---|
859 | 844 | struct audio_drv_data *adata = dev_get_drvdata(component->dev); |
---|
860 | 845 | struct snd_soc_card *card = prtd->card; |
---|
861 | 846 | struct acp_platform_info *pinfo = snd_soc_card_get_drvdata(card); |
---|
.. | .. |
---|
867 | 852 | return -EINVAL; |
---|
868 | 853 | |
---|
869 | 854 | if (pinfo) { |
---|
870 | | - rtd->i2s_instance = pinfo->i2s_instance; |
---|
871 | | - rtd->capture_channel = pinfo->capture_channel; |
---|
| 855 | + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
---|
| 856 | + rtd->i2s_instance = pinfo->play_i2s_instance; |
---|
| 857 | + } else { |
---|
| 858 | + rtd->i2s_instance = pinfo->cap_i2s_instance; |
---|
| 859 | + rtd->capture_channel = pinfo->capture_channel; |
---|
| 860 | + } |
---|
872 | 861 | } |
---|
873 | 862 | if (adata->asic_type == CHIP_STONEY) { |
---|
874 | 863 | val = acp_reg_read(adata->acp_mmio, |
---|
.. | .. |
---|
977 | 966 | } |
---|
978 | 967 | |
---|
979 | 968 | size = params_buffer_bytes(params); |
---|
980 | | - status = snd_pcm_lib_malloc_pages(substream, size); |
---|
981 | | - if (status < 0) |
---|
982 | | - return status; |
---|
983 | 969 | |
---|
984 | | - memset(substream->runtime->dma_area, 0, params_buffer_bytes(params)); |
---|
985 | | - pg = virt_to_page(substream->dma_buffer.area); |
---|
| 970 | + acp_set_sram_bank_state(rtd->acp_mmio, 0, true); |
---|
| 971 | + /* Save for runtime private data */ |
---|
| 972 | + rtd->dma_addr = runtime->dma_addr; |
---|
| 973 | + rtd->order = get_order(size); |
---|
986 | 974 | |
---|
987 | | - if (pg) { |
---|
988 | | - acp_set_sram_bank_state(rtd->acp_mmio, 0, true); |
---|
989 | | - /* Save for runtime private data */ |
---|
990 | | - rtd->pg = pg; |
---|
991 | | - rtd->order = get_order(size); |
---|
| 975 | + /* Fill the page table entries in ACP SRAM */ |
---|
| 976 | + rtd->size = size; |
---|
| 977 | + rtd->num_of_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; |
---|
| 978 | + rtd->direction = substream->stream; |
---|
992 | 979 | |
---|
993 | | - /* Fill the page table entries in ACP SRAM */ |
---|
994 | | - rtd->pg = pg; |
---|
995 | | - rtd->size = size; |
---|
996 | | - rtd->num_of_pages = PAGE_ALIGN(size) >> PAGE_SHIFT; |
---|
997 | | - rtd->direction = substream->stream; |
---|
998 | | - |
---|
999 | | - config_acp_dma(rtd->acp_mmio, rtd, adata->asic_type); |
---|
1000 | | - status = 0; |
---|
1001 | | - } else { |
---|
1002 | | - status = -ENOMEM; |
---|
1003 | | - } |
---|
1004 | | - return status; |
---|
1005 | | -} |
---|
1006 | | - |
---|
1007 | | -static int acp_dma_hw_free(struct snd_pcm_substream *substream) |
---|
1008 | | -{ |
---|
1009 | | - return snd_pcm_lib_free_pages(substream); |
---|
| 980 | + config_acp_dma(rtd->acp_mmio, rtd, adata->asic_type); |
---|
| 981 | + return 0; |
---|
1010 | 982 | } |
---|
1011 | 983 | |
---|
1012 | 984 | static u64 acp_get_byte_count(struct audio_substream_data *rtd) |
---|
.. | .. |
---|
1020 | 992 | return byte_count.bytescount; |
---|
1021 | 993 | } |
---|
1022 | 994 | |
---|
1023 | | -static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) |
---|
| 995 | +static snd_pcm_uframes_t acp_dma_pointer(struct snd_soc_component *component, |
---|
| 996 | + struct snd_pcm_substream *substream) |
---|
1024 | 997 | { |
---|
1025 | 998 | u32 buffersize; |
---|
1026 | 999 | u32 pos = 0; |
---|
.. | .. |
---|
1062 | 1035 | return bytes_to_frames(runtime, pos); |
---|
1063 | 1036 | } |
---|
1064 | 1037 | |
---|
1065 | | -static int acp_dma_mmap(struct snd_pcm_substream *substream, |
---|
| 1038 | +static int acp_dma_mmap(struct snd_soc_component *component, |
---|
| 1039 | + struct snd_pcm_substream *substream, |
---|
1066 | 1040 | struct vm_area_struct *vma) |
---|
1067 | 1041 | { |
---|
1068 | 1042 | return snd_pcm_lib_default_mmap(substream, vma); |
---|
1069 | 1043 | } |
---|
1070 | 1044 | |
---|
1071 | | -static int acp_dma_prepare(struct snd_pcm_substream *substream) |
---|
| 1045 | +static int acp_dma_prepare(struct snd_soc_component *component, |
---|
| 1046 | + struct snd_pcm_substream *substream) |
---|
1072 | 1047 | { |
---|
1073 | 1048 | struct snd_pcm_runtime *runtime = substream->runtime; |
---|
1074 | 1049 | struct audio_substream_data *rtd = runtime->private_data; |
---|
.. | .. |
---|
1095 | 1070 | return 0; |
---|
1096 | 1071 | } |
---|
1097 | 1072 | |
---|
1098 | | -static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) |
---|
| 1073 | +static int acp_dma_trigger(struct snd_soc_component *component, |
---|
| 1074 | + struct snd_pcm_substream *substream, int cmd) |
---|
1099 | 1075 | { |
---|
1100 | 1076 | int ret; |
---|
1101 | 1077 | |
---|
.. | .. |
---|
1141 | 1117 | return ret; |
---|
1142 | 1118 | } |
---|
1143 | 1119 | |
---|
1144 | | -static int acp_dma_new(struct snd_soc_pcm_runtime *rtd) |
---|
| 1120 | +static int acp_dma_new(struct snd_soc_component *component, |
---|
| 1121 | + struct snd_soc_pcm_runtime *rtd) |
---|
1145 | 1122 | { |
---|
1146 | | - int ret; |
---|
1147 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, |
---|
1148 | | - DRV_NAME); |
---|
1149 | 1123 | struct audio_drv_data *adata = dev_get_drvdata(component->dev); |
---|
1150 | 1124 | struct device *parent = component->dev->parent; |
---|
1151 | 1125 | |
---|
1152 | 1126 | switch (adata->asic_type) { |
---|
1153 | 1127 | case CHIP_STONEY: |
---|
1154 | | - ret = snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, |
---|
1155 | | - SNDRV_DMA_TYPE_DEV, |
---|
1156 | | - parent, |
---|
1157 | | - ST_MIN_BUFFER, |
---|
1158 | | - ST_MAX_BUFFER); |
---|
| 1128 | + snd_pcm_set_managed_buffer_all(rtd->pcm, |
---|
| 1129 | + SNDRV_DMA_TYPE_DEV, |
---|
| 1130 | + parent, |
---|
| 1131 | + ST_MIN_BUFFER, |
---|
| 1132 | + ST_MAX_BUFFER); |
---|
1159 | 1133 | break; |
---|
1160 | 1134 | default: |
---|
1161 | | - ret = snd_pcm_lib_preallocate_pages_for_all(rtd->pcm, |
---|
1162 | | - SNDRV_DMA_TYPE_DEV, |
---|
1163 | | - parent, |
---|
1164 | | - MIN_BUFFER, |
---|
1165 | | - MAX_BUFFER); |
---|
| 1135 | + snd_pcm_set_managed_buffer_all(rtd->pcm, |
---|
| 1136 | + SNDRV_DMA_TYPE_DEV, |
---|
| 1137 | + parent, |
---|
| 1138 | + MIN_BUFFER, |
---|
| 1139 | + MAX_BUFFER); |
---|
1166 | 1140 | break; |
---|
1167 | 1141 | } |
---|
1168 | | - if (ret < 0) |
---|
1169 | | - dev_err(component->dev, |
---|
1170 | | - "buffer preallocation failure error:%d\n", ret); |
---|
1171 | | - return ret; |
---|
| 1142 | + return 0; |
---|
1172 | 1143 | } |
---|
1173 | 1144 | |
---|
1174 | | -static int acp_dma_close(struct snd_pcm_substream *substream) |
---|
| 1145 | +static int acp_dma_close(struct snd_soc_component *component, |
---|
| 1146 | + struct snd_pcm_substream *substream) |
---|
1175 | 1147 | { |
---|
1176 | 1148 | u16 bank; |
---|
1177 | 1149 | struct snd_pcm_runtime *runtime = substream->runtime; |
---|
1178 | 1150 | struct audio_substream_data *rtd = runtime->private_data; |
---|
1179 | | - struct snd_soc_pcm_runtime *prtd = substream->private_data; |
---|
1180 | | - struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd, |
---|
1181 | | - DRV_NAME); |
---|
1182 | 1151 | struct audio_drv_data *adata = dev_get_drvdata(component->dev); |
---|
1183 | 1152 | |
---|
1184 | 1153 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
---|
.. | .. |
---|
1229 | 1198 | return 0; |
---|
1230 | 1199 | } |
---|
1231 | 1200 | |
---|
1232 | | -static const struct snd_pcm_ops acp_dma_ops = { |
---|
1233 | | - .open = acp_dma_open, |
---|
1234 | | - .close = acp_dma_close, |
---|
1235 | | - .ioctl = snd_pcm_lib_ioctl, |
---|
1236 | | - .hw_params = acp_dma_hw_params, |
---|
1237 | | - .hw_free = acp_dma_hw_free, |
---|
1238 | | - .trigger = acp_dma_trigger, |
---|
1239 | | - .pointer = acp_dma_pointer, |
---|
1240 | | - .mmap = acp_dma_mmap, |
---|
1241 | | - .prepare = acp_dma_prepare, |
---|
1242 | | -}; |
---|
1243 | | - |
---|
1244 | 1201 | static const struct snd_soc_component_driver acp_asoc_platform = { |
---|
1245 | | - .name = DRV_NAME, |
---|
1246 | | - .ops = &acp_dma_ops, |
---|
1247 | | - .pcm_new = acp_dma_new, |
---|
| 1202 | + .name = DRV_NAME, |
---|
| 1203 | + .open = acp_dma_open, |
---|
| 1204 | + .close = acp_dma_close, |
---|
| 1205 | + .hw_params = acp_dma_hw_params, |
---|
| 1206 | + .trigger = acp_dma_trigger, |
---|
| 1207 | + .pointer = acp_dma_pointer, |
---|
| 1208 | + .mmap = acp_dma_mmap, |
---|
| 1209 | + .prepare = acp_dma_prepare, |
---|
| 1210 | + .pcm_construct = acp_dma_new, |
---|
1248 | 1211 | }; |
---|
1249 | 1212 | |
---|
1250 | 1213 | static int acp_audio_probe(struct platform_device *pdev) |
---|
.. | .. |
---|
1264 | 1227 | if (!audio_drv_data) |
---|
1265 | 1228 | return -ENOMEM; |
---|
1266 | 1229 | |
---|
1267 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
1268 | | - audio_drv_data->acp_mmio = devm_ioremap_resource(&pdev->dev, res); |
---|
| 1230 | + audio_drv_data->acp_mmio = devm_platform_ioremap_resource(pdev, 0); |
---|
1269 | 1231 | if (IS_ERR(audio_drv_data->acp_mmio)) |
---|
1270 | 1232 | return PTR_ERR(audio_drv_data->acp_mmio); |
---|
1271 | 1233 | |
---|