xref: /openbmc/linux/sound/soc/codecs/wcd938x-sdw.c (revision 099ab4fc)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2021, Linaro Limited
3 
4 #include <linux/module.h>
5 #include <linux/slab.h>
6 #include <linux/platform_device.h>
7 #include <linux/device.h>
8 #include <linux/kernel.h>
9 #include <linux/component.h>
10 #include <sound/soc.h>
11 #include <linux/pm_runtime.h>
12 #include <linux/irqdomain.h>
13 #include <linux/of.h>
14 #include <linux/soundwire/sdw.h>
15 #include <linux/soundwire/sdw_type.h>
16 #include <linux/soundwire/sdw_registers.h>
17 #include <linux/regmap.h>
18 #include <sound/soc.h>
19 #include <sound/soc-dapm.h>
20 #include "wcd938x.h"
21 
22 #define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
23 
24 static struct wcd938x_sdw_ch_info wcd938x_sdw_rx_ch_info[] = {
25 	WCD_SDW_CH(WCD938X_HPH_L, WCD938X_HPH_PORT, BIT(0)),
26 	WCD_SDW_CH(WCD938X_HPH_R, WCD938X_HPH_PORT, BIT(1)),
27 	WCD_SDW_CH(WCD938X_CLSH, WCD938X_CLSH_PORT, BIT(0)),
28 	WCD_SDW_CH(WCD938X_COMP_L, WCD938X_COMP_PORT, BIT(0)),
29 	WCD_SDW_CH(WCD938X_COMP_R, WCD938X_COMP_PORT, BIT(1)),
30 	WCD_SDW_CH(WCD938X_LO, WCD938X_LO_PORT, BIT(0)),
31 	WCD_SDW_CH(WCD938X_DSD_L, WCD938X_DSD_PORT, BIT(0)),
32 	WCD_SDW_CH(WCD938X_DSD_R, WCD938X_DSD_PORT, BIT(1)),
33 };
34 
35 static struct wcd938x_sdw_ch_info wcd938x_sdw_tx_ch_info[] = {
36 	WCD_SDW_CH(WCD938X_ADC1, WCD938X_ADC_1_2_PORT, BIT(0)),
37 	WCD_SDW_CH(WCD938X_ADC2, WCD938X_ADC_1_2_PORT, BIT(1)),
38 	WCD_SDW_CH(WCD938X_ADC3, WCD938X_ADC_3_4_PORT, BIT(0)),
39 	WCD_SDW_CH(WCD938X_ADC4, WCD938X_ADC_3_4_PORT, BIT(1)),
40 	WCD_SDW_CH(WCD938X_DMIC0, WCD938X_DMIC_0_3_MBHC_PORT, BIT(0)),
41 	WCD_SDW_CH(WCD938X_DMIC1, WCD938X_DMIC_0_3_MBHC_PORT, BIT(1)),
42 	WCD_SDW_CH(WCD938X_MBHC, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
43 	WCD_SDW_CH(WCD938X_DMIC2, WCD938X_DMIC_0_3_MBHC_PORT, BIT(2)),
44 	WCD_SDW_CH(WCD938X_DMIC3, WCD938X_DMIC_0_3_MBHC_PORT, BIT(3)),
45 	WCD_SDW_CH(WCD938X_DMIC4, WCD938X_DMIC_4_7_PORT, BIT(0)),
46 	WCD_SDW_CH(WCD938X_DMIC5, WCD938X_DMIC_4_7_PORT, BIT(1)),
47 	WCD_SDW_CH(WCD938X_DMIC6, WCD938X_DMIC_4_7_PORT, BIT(2)),
48 	WCD_SDW_CH(WCD938X_DMIC7, WCD938X_DMIC_4_7_PORT, BIT(3)),
49 };
50 
51 static struct sdw_dpn_prop wcd938x_dpn_prop[WCD938X_MAX_SWR_PORTS] = {
52 	{
53 		.num = 1,
54 		.type = SDW_DPN_SIMPLE,
55 		.min_ch = 1,
56 		.max_ch = 8,
57 		.simple_ch_prep_sm = true,
58 	}, {
59 		.num = 2,
60 		.type = SDW_DPN_SIMPLE,
61 		.min_ch = 1,
62 		.max_ch = 4,
63 		.simple_ch_prep_sm = true,
64 	}, {
65 		.num = 3,
66 		.type = SDW_DPN_SIMPLE,
67 		.min_ch = 1,
68 		.max_ch = 4,
69 		.simple_ch_prep_sm = true,
70 	}, {
71 		.num = 4,
72 		.type = SDW_DPN_SIMPLE,
73 		.min_ch = 1,
74 		.max_ch = 4,
75 		.simple_ch_prep_sm = true,
76 	}, {
77 		.num = 5,
78 		.type = SDW_DPN_SIMPLE,
79 		.min_ch = 1,
80 		.max_ch = 4,
81 		.simple_ch_prep_sm = true,
82 	}
83 };
84 
85 struct device *wcd938x_sdw_device_get(struct device_node *np)
86 {
87 	return bus_find_device_by_of_node(&sdw_bus_type, np);
88 
89 }
90 EXPORT_SYMBOL_GPL(wcd938x_sdw_device_get);
91 
92 int wcd938x_swr_get_current_bank(struct sdw_slave *sdev)
93 {
94 	int bank;
95 
96 	bank  = sdw_read(sdev, SDW_SCP_CTRL);
97 
98 	return ((bank & 0x40) ? 1 : 0);
99 }
100 EXPORT_SYMBOL_GPL(wcd938x_swr_get_current_bank);
101 
102 int wcd938x_sdw_hw_params(struct wcd938x_sdw_priv *wcd,
103 			  struct snd_pcm_substream *substream,
104 			  struct snd_pcm_hw_params *params,
105 			  struct snd_soc_dai *dai)
106 {
107 	struct sdw_port_config port_config[WCD938X_MAX_SWR_PORTS];
108 	unsigned long ch_mask;
109 	int i, j;
110 
111 	wcd->sconfig.ch_count = 1;
112 	wcd->active_ports = 0;
113 	for (i = 0; i < WCD938X_MAX_SWR_PORTS; i++) {
114 		ch_mask = wcd->port_config[i].ch_mask;
115 
116 		if (!ch_mask)
117 			continue;
118 
119 		for_each_set_bit(j, &ch_mask, 4)
120 			wcd->sconfig.ch_count++;
121 
122 		port_config[wcd->active_ports] = wcd->port_config[i];
123 		wcd->active_ports++;
124 	}
125 
126 	wcd->sconfig.bps = 1;
127 	wcd->sconfig.frame_rate =  params_rate(params);
128 	if (wcd->is_tx)
129 		wcd->sconfig.direction = SDW_DATA_DIR_TX;
130 	else
131 		wcd->sconfig.direction = SDW_DATA_DIR_RX;
132 
133 	wcd->sconfig.type = SDW_STREAM_PCM;
134 
135 	return sdw_stream_add_slave(wcd->sdev, &wcd->sconfig,
136 				    &port_config[0], wcd->active_ports,
137 				    wcd->sruntime);
138 }
139 EXPORT_SYMBOL_GPL(wcd938x_sdw_hw_params);
140 
141 int wcd938x_sdw_free(struct wcd938x_sdw_priv *wcd,
142 		     struct snd_pcm_substream *substream,
143 		     struct snd_soc_dai *dai)
144 {
145 	sdw_stream_remove_slave(wcd->sdev, wcd->sruntime);
146 
147 	return 0;
148 }
149 EXPORT_SYMBOL_GPL(wcd938x_sdw_free);
150 
151 int wcd938x_sdw_set_sdw_stream(struct wcd938x_sdw_priv *wcd,
152 			       struct snd_soc_dai *dai,
153 			       void *stream, int direction)
154 {
155 	wcd->sruntime = stream;
156 
157 	return 0;
158 }
159 EXPORT_SYMBOL_GPL(wcd938x_sdw_set_sdw_stream);
160 
161 static int wcd9380_update_status(struct sdw_slave *slave,
162 				 enum sdw_slave_status status)
163 {
164 	return 0;
165 }
166 
167 static int wcd9380_bus_config(struct sdw_slave *slave,
168 			      struct sdw_bus_params *params)
169 {
170 	sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank),  0x01);
171 
172 	return 0;
173 }
174 
175 static int wcd9380_interrupt_callback(struct sdw_slave *slave,
176 				      struct sdw_slave_intr_status *status)
177 {
178 	struct wcd938x_sdw_priv *wcd = dev_get_drvdata(&slave->dev);
179 
180 	return wcd938x_handle_sdw_irq(wcd);
181 }
182 
183 static struct sdw_slave_ops wcd9380_slave_ops = {
184 	.update_status = wcd9380_update_status,
185 	.interrupt_callback = wcd9380_interrupt_callback,
186 	.bus_config = wcd9380_bus_config,
187 };
188 
189 static int wcd938x_sdw_component_bind(struct device *dev,
190 				      struct device *master, void *data)
191 {
192 	return 0;
193 }
194 
195 static void wcd938x_sdw_component_unbind(struct device *dev,
196 					 struct device *master, void *data)
197 {
198 }
199 
200 static const struct component_ops wcd938x_sdw_component_ops = {
201 	.bind   = wcd938x_sdw_component_bind,
202 	.unbind = wcd938x_sdw_component_unbind,
203 };
204 
205 static int wcd9380_probe(struct sdw_slave *pdev,
206 			 const struct sdw_device_id *id)
207 {
208 	struct device *dev = &pdev->dev;
209 	struct wcd938x_sdw_priv *wcd;
210 	int ret;
211 
212 	wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL);
213 	if (!wcd)
214 		return -ENOMEM;
215 
216 	/**
217 	 * Port map index starts with 0, however the data port for this codec
218 	 * are from index 1
219 	 */
220 	if (of_property_read_bool(dev->of_node, "qcom,tx-port-mapping")) {
221 		wcd->is_tx = true;
222 		ret = of_property_read_u32_array(dev->of_node, "qcom,tx-port-mapping",
223 						 &pdev->m_port_map[1],
224 						 WCD938X_MAX_TX_SWR_PORTS);
225 	} else {
226 		ret = of_property_read_u32_array(dev->of_node, "qcom,rx-port-mapping",
227 						 &pdev->m_port_map[1],
228 						 WCD938X_MAX_SWR_PORTS);
229 	}
230 
231 	if (ret < 0)
232 		dev_info(dev, "Static Port mapping not specified\n");
233 
234 	wcd->sdev = pdev;
235 	dev_set_drvdata(dev, wcd);
236 
237 	pdev->prop.scp_int1_mask = SDW_SCP_INT1_IMPL_DEF |
238 					SDW_SCP_INT1_BUS_CLASH |
239 					SDW_SCP_INT1_PARITY;
240 	pdev->prop.lane_control_support = true;
241 	if (wcd->is_tx) {
242 		struct regmap *rm;
243 
244 		pdev->prop.source_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
245 		pdev->prop.src_dpn_prop = wcd938x_dpn_prop;
246 		wcd->ch_info = &wcd938x_sdw_tx_ch_info[0];
247 		pdev->prop.wake_capable = true;
248 
249 		rm = devm_regmap_init_sdw(pdev, &wcd938x_regmap_config);
250 		if (IS_ERR(rm))
251 			return PTR_ERR(rm);
252 	} else {
253 		pdev->prop.sink_ports = GENMASK(WCD938X_MAX_SWR_PORTS, 0);
254 		pdev->prop.sink_dpn_prop = wcd938x_dpn_prop;
255 		wcd->ch_info = &wcd938x_sdw_rx_ch_info[0];
256 	}
257 
258 	pm_runtime_set_autosuspend_delay(dev, 3000);
259 	pm_runtime_use_autosuspend(dev);
260 	pm_runtime_mark_last_busy(dev);
261 	pm_runtime_set_active(dev);
262 	pm_runtime_enable(dev);
263 
264 	return component_add(dev, &wcd938x_sdw_component_ops);
265 }
266 
267 static const struct sdw_device_id wcd9380_slave_id[] = {
268 	SDW_SLAVE_ENTRY(0x0217, 0x10d, 0),
269 	{},
270 };
271 MODULE_DEVICE_TABLE(sdw, wcd9380_slave_id);
272 
273 static int __maybe_unused wcd938x_sdw_runtime_suspend(struct device *dev)
274 {
275 	struct regmap *regmap = dev_get_regmap(dev, NULL);
276 
277 	if (regmap) {
278 		regcache_cache_only(regmap, true);
279 		regcache_mark_dirty(regmap);
280 	}
281 	return 0;
282 }
283 
284 static int __maybe_unused wcd938x_sdw_runtime_resume(struct device *dev)
285 {
286 	struct regmap *regmap = dev_get_regmap(dev, NULL);
287 
288 	if (regmap) {
289 		regcache_cache_only(regmap, false);
290 		regcache_sync(regmap);
291 	}
292 
293 	pm_runtime_mark_last_busy(dev);
294 
295 	return 0;
296 }
297 
298 static const struct dev_pm_ops wcd938x_sdw_pm_ops = {
299 	SET_RUNTIME_PM_OPS(wcd938x_sdw_runtime_suspend, wcd938x_sdw_runtime_resume, NULL)
300 };
301 
302 
303 static struct sdw_driver wcd9380_codec_driver = {
304 	.probe	= wcd9380_probe,
305 	.ops = &wcd9380_slave_ops,
306 	.id_table = wcd9380_slave_id,
307 	.driver = {
308 		.name	= "wcd9380-codec",
309 		.pm = &wcd938x_sdw_pm_ops,
310 	}
311 };
312 module_sdw_driver(wcd9380_codec_driver);
313 
314 MODULE_DESCRIPTION("WCD938X SDW codec driver");
315 MODULE_LICENSE("GPL");
316