Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2021 Advanced Micro Devices, Inc.
7//
8// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9
10/*
11 * Hardware interface for Audio DSP on Renoir platform
12 */
13
14#include <linux/platform_device.h>
15#include <linux/module.h>
16
17#include "../ops.h"
18#include "../sof-audio.h"
19#include "acp.h"
20#include "acp-dsp-offset.h"
21
22#define I2S_BT_INSTANCE 0
23#define I2S_SP_INSTANCE 1
24#define PDM_DMIC_INSTANCE 2
25
26#define I2S_MODE 0x04
27
28static int renoir_dai_probe(struct snd_soc_dai *dai)
29{
30 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(dai->component);
31 unsigned int val;
32
33 val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_I2S_PIN_CONFIG);
34 if (val != I2S_MODE) {
35 dev_err(sdev->dev, "I2S Mode is not supported (I2S_PIN_CONFIG: %#x)\n", val);
36 return -EINVAL;
37 }
38
39 return 0;
40}
41
42static struct snd_soc_dai_driver renoir_sof_dai[] = {
43 [I2S_BT_INSTANCE] = {
44 .id = I2S_BT_INSTANCE,
45 .name = "acp-sof-bt",
46 .playback = {
47 .rates = SNDRV_PCM_RATE_8000_96000,
48 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
49 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
50 .channels_min = 2,
51 .channels_max = 8,
52 .rate_min = 8000,
53 .rate_max = 96000,
54 },
55 .capture = {
56 .rates = SNDRV_PCM_RATE_8000_48000,
57 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
58 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
59 /* Supporting only stereo for I2S BT controller capture */
60 .channels_min = 2,
61 .channels_max = 2,
62 .rate_min = 8000,
63 .rate_max = 48000,
64 },
65 .probe = &renoir_dai_probe,
66 },
67
68 [I2S_SP_INSTANCE] = {
69 .id = I2S_SP_INSTANCE,
70 .name = "acp-sof-sp",
71 .playback = {
72 .rates = SNDRV_PCM_RATE_8000_96000,
73 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
74 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
75 .channels_min = 2,
76 .channels_max = 8,
77 .rate_min = 8000,
78 .rate_max = 96000,
79 },
80 .capture = {
81 .rates = SNDRV_PCM_RATE_8000_48000,
82 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
83 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
84 /* Supporting only stereo for I2S SP controller capture */
85 .channels_min = 2,
86 .channels_max = 2,
87 .rate_min = 8000,
88 .rate_max = 48000,
89 },
90 .probe = &renoir_dai_probe,
91 },
92
93 [PDM_DMIC_INSTANCE] = {
94 .id = PDM_DMIC_INSTANCE,
95 .name = "acp-sof-dmic",
96 .capture = {
97 .rates = SNDRV_PCM_RATE_8000_48000,
98 .formats = SNDRV_PCM_FMTBIT_S32_LE,
99 .channels_min = 2,
100 .channels_max = 4,
101 .rate_min = 8000,
102 .rate_max = 48000,
103 },
104 },
105};
106
107static struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev)
108{
109 struct snd_sof_pdata *sof_pdata = sdev->pdata;
110 const struct sof_dev_desc *desc = sof_pdata->desc;
111 struct snd_soc_acpi_mach *mach;
112
113 mach = snd_soc_acpi_find_machine(desc->machines);
114 if (!mach) {
115 dev_warn(sdev->dev, "No matching ASoC machine driver found\n");
116 return NULL;
117 }
118
119 sof_pdata->tplg_filename = mach->sof_tplg_filename;
120 sof_pdata->fw_filename = mach->fw_filename;
121
122 return mach;
123}
124
125/* AMD Renoir DSP ops */
126struct snd_sof_dsp_ops sof_renoir_ops = {
127 /* probe and remove */
128 .probe = amd_sof_acp_probe,
129 .remove = amd_sof_acp_remove,
130
131 /* Register IO */
132 .write = sof_io_write,
133 .read = sof_io_read,
134
135 /* Block IO */
136 .block_read = acp_dsp_block_read,
137 .block_write = acp_dsp_block_write,
138
139 /*Firmware loading */
140 .load_firmware = snd_sof_load_firmware_memcpy,
141 .pre_fw_run = acp_dsp_pre_fw_run,
142 .get_bar_index = acp_get_bar_index,
143
144 /* DSP core boot */
145 .run = acp_sof_dsp_run,
146
147 /*IPC */
148 .send_msg = acp_sof_ipc_send_msg,
149 .ipc_msg_data = acp_sof_ipc_msg_data,
150 .get_mailbox_offset = acp_sof_ipc_get_mailbox_offset,
151 .irq_thread = acp_sof_ipc_irq_thread,
152
153 /* DAI drivers */
154 .drv = renoir_sof_dai,
155 .num_drv = ARRAY_SIZE(renoir_sof_dai),
156
157 /* stream callbacks */
158 .pcm_open = acp_pcm_open,
159 .pcm_close = acp_pcm_close,
160 .pcm_hw_params = acp_pcm_hw_params,
161
162 .hw_info = SNDRV_PCM_INFO_MMAP |
163 SNDRV_PCM_INFO_MMAP_VALID |
164 SNDRV_PCM_INFO_INTERLEAVED |
165 SNDRV_PCM_INFO_PAUSE |
166 SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
167
168 /* Machine driver callbacks */
169 .machine_select = amd_sof_machine_select,
170 .machine_register = sof_machine_register,
171 .machine_unregister = sof_machine_unregister,
172
173 /* Trace Logger */
174 .trace_init = acp_sof_trace_init,
175 .trace_release = acp_sof_trace_release,
176};
177EXPORT_SYMBOL(sof_renoir_ops);
178
179MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
180MODULE_DESCRIPTION("RENOIR SOF Driver");
181MODULE_LICENSE("Dual BSD/GPL");