blob: 34227a0b47de4ee4f89d08e859625a45a403aef7 [file] [log] [blame]
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/device.h>
13#include <linux/module.h>
14#include <linux/io.h>
15#include <linux/init.h>
16#include <linux/platform_device.h>
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +053017#include <linux/mfd/msm-cdc-pinctrl.h>
Laxminath Kasam2d20bc92016-11-24 17:31:45 +053018#include <linux/printk.h>
19#include <linux/debugfs.h>
20#include <linux/bitops.h>
21#include <linux/regmap.h>
22#include <linux/delay.h>
23#include <linux/kernel.h>
24#include <linux/qdsp6v2/apr.h>
25#include <linux/soundwire/swr-wcd.h>
26#include <linux/qdsp6v2/audio_notifier.h>
27#include <sound/apr_audio-v2.h>
28#include <sound/pcm.h>
29#include <sound/pcm_params.h>
30#include <sound/soc.h>
31#include <sound/soc-dapm.h>
32#include <sound/q6core.h>
33#include <sound/tlv.h>
34#include "msm_sdw.h"
35#include "msm_sdw_registers.h"
36
37#define MSM_SDW_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
38 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
39#define MSM_SDW_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
40 SNDRV_PCM_FMTBIT_S24_LE |\
41 SNDRV_PCM_FMTBIT_S24_3LE)
42
43#define MSM_SDW_STRING_LEN 80
44
45#define INT_MCLK1_FREQ 9600000
46#define SDW_NPL_FREQ 153600000
47
48#define MSM_SDW_VERSION_1_0 0x0001
49#define MSM_SDW_VERSION_ENTRY_SIZE 32
50
Laxminath Kasam716a45b2017-02-13 19:36:27 +053051/*
52 * 200 Milliseconds sufficient for DSP bring up in the modem
53 * after Sub System Restart
54 */
55#define ADSP_STATE_READY_TIMEOUT_MS 200
56
Laxminath Kasam2d20bc92016-11-24 17:31:45 +053057static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
58static struct snd_soc_dai_driver msm_sdw_dai[];
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +053059static bool skip_irq = true;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +053060
61static int msm_sdw_config_ear_spkr_gain(struct snd_soc_codec *codec,
62 int event, int gain_reg);
63static int msm_sdw_config_compander(struct snd_soc_codec *, int, int);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +053064static int msm_sdw_mclk_enable(struct msm_sdw_priv *msm_sdw,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +053065 int mclk_enable, bool dapm);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +053066static int msm_int_enable_sdw_cdc_clk(struct msm_sdw_priv *msm_sdw,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +053067 int enable, bool dapm);
68
69enum {
70 VI_SENSE_1,
71 VI_SENSE_2,
72};
73
74enum {
75 AIF1_SDW_PB = 0,
76 AIF1_SDW_VIFEED,
77 NUM_CODEC_DAIS,
78};
79
80static const struct msm_sdw_reg_mask_val msm_sdw_spkr_default[] = {
81 {MSM_SDW_COMPANDER7_CTL3, 0x80, 0x80},
82 {MSM_SDW_COMPANDER8_CTL3, 0x80, 0x80},
83 {MSM_SDW_COMPANDER7_CTL7, 0x01, 0x01},
84 {MSM_SDW_COMPANDER8_CTL7, 0x01, 0x01},
85 {MSM_SDW_BOOST0_BOOST_CTL, 0x7C, 0x50},
86 {MSM_SDW_BOOST1_BOOST_CTL, 0x7C, 0x50},
87};
88
89static const struct msm_sdw_reg_mask_val msm_sdw_spkr_mode1[] = {
90 {MSM_SDW_COMPANDER7_CTL3, 0x80, 0x00},
91 {MSM_SDW_COMPANDER8_CTL3, 0x80, 0x00},
92 {MSM_SDW_COMPANDER7_CTL7, 0x01, 0x00},
93 {MSM_SDW_COMPANDER8_CTL7, 0x01, 0x00},
94 {MSM_SDW_BOOST0_BOOST_CTL, 0x7C, 0x44},
95 {MSM_SDW_BOOST1_BOOST_CTL, 0x7C, 0x44},
96};
97
98/**
99 * msm_sdw_set_spkr_gain_offset - offset the speaker path
100 * gain with the given offset value.
101 *
102 * @codec: codec instance
103 * @offset: Indicates speaker path gain offset value.
104 *
105 * Returns 0 on success or -EINVAL on error.
106 */
107int msm_sdw_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset)
108{
109 struct msm_sdw_priv *priv;
110
111 if (!codec) {
112 pr_err("%s: NULL codec pointer!\n", __func__);
113 return -EINVAL;
114 }
115
116 priv = snd_soc_codec_get_drvdata(codec);
117 if (!priv)
118 return -EINVAL;
119
120 priv->spkr_gain_offset = offset;
121 return 0;
122}
123EXPORT_SYMBOL(msm_sdw_set_spkr_gain_offset);
124
125/**
126 * msm_sdw_set_spkr_mode - Configures speaker compander and smartboost
127 * settings based on speaker mode.
128 *
129 * @codec: codec instance
130 * @mode: Indicates speaker configuration mode.
131 *
132 * Returns 0 on success or -EINVAL on error.
133 */
134int msm_sdw_set_spkr_mode(struct snd_soc_codec *codec, int mode)
135{
136 struct msm_sdw_priv *priv;
137 int i;
138 const struct msm_sdw_reg_mask_val *regs;
139 int size;
140
141 if (!codec) {
142 pr_err("%s: NULL codec pointer!\n", __func__);
143 return -EINVAL;
144 }
145
146 priv = snd_soc_codec_get_drvdata(codec);
147 if (!priv)
148 return -EINVAL;
149
150 switch (mode) {
151 case SPKR_MODE_1:
152 regs = msm_sdw_spkr_mode1;
153 size = ARRAY_SIZE(msm_sdw_spkr_mode1);
154 break;
155 default:
156 regs = msm_sdw_spkr_default;
157 size = ARRAY_SIZE(msm_sdw_spkr_default);
158 break;
159 }
160
161 priv->spkr_mode = mode;
162 for (i = 0; i < size; i++)
163 snd_soc_update_bits(codec, regs[i].reg,
164 regs[i].mask, regs[i].val);
165 return 0;
166}
167EXPORT_SYMBOL(msm_sdw_set_spkr_mode);
168
169static int msm_enable_sdw_npl_clk(struct msm_sdw_priv *msm_sdw, int enable)
170{
171 int ret = 0;
172
173 dev_dbg(msm_sdw->dev, "%s: enable %d\n", __func__, enable);
174
175 mutex_lock(&msm_sdw->sdw_npl_clk_mutex);
176 if (enable) {
177 if (msm_sdw->sdw_npl_clk_enabled == false) {
178 msm_sdw->sdw_npl_clk.enable = 1;
179 ret = afe_set_lpass_clock_v2(
180 AFE_PORT_ID_INT4_MI2S_RX,
181 &msm_sdw->sdw_npl_clk);
182 if (ret < 0) {
183 dev_err(msm_sdw->dev,
184 "%s: failed to enable SDW NPL CLK\n",
185 __func__);
186 mutex_unlock(&msm_sdw->sdw_npl_clk_mutex);
187 return ret;
188 }
189 dev_dbg(msm_sdw->dev, "enabled sdw npl clk\n");
190 msm_sdw->sdw_npl_clk_enabled = true;
191 }
192 } else {
193 if (msm_sdw->sdw_npl_clk_enabled == true) {
194 msm_sdw->sdw_npl_clk.enable = 0;
195 ret = afe_set_lpass_clock_v2(
196 AFE_PORT_ID_INT4_MI2S_RX,
197 &msm_sdw->sdw_npl_clk);
198 if (ret < 0)
199 dev_err(msm_sdw->dev,
200 "%s: failed to disable SDW NPL CLK\n",
201 __func__);
202 msm_sdw->sdw_npl_clk_enabled = false;
203 }
204 }
205 mutex_unlock(&msm_sdw->sdw_npl_clk_mutex);
206 return ret;
207}
208
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530209static int msm_int_enable_sdw_cdc_clk(struct msm_sdw_priv *msm_sdw,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530210 int enable, bool dapm)
211{
212 int ret = 0;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530213
214 mutex_lock(&msm_sdw->cdc_int_mclk1_mutex);
215 dev_dbg(msm_sdw->dev, "%s: enable %d mclk1 ref counter %d\n",
216 __func__, enable, msm_sdw->int_mclk1_rsc_ref);
217 if (enable) {
218 if (msm_sdw->int_mclk1_rsc_ref == 0) {
219 cancel_delayed_work_sync(
220 &msm_sdw->disable_int_mclk1_work);
221 if (msm_sdw->int_mclk1_enabled == false) {
222 msm_sdw->sdw_cdc_core_clk.enable = 1;
223 ret = afe_set_lpass_clock_v2(
224 AFE_PORT_ID_INT4_MI2S_RX,
225 &msm_sdw->sdw_cdc_core_clk);
226 if (ret < 0) {
227 dev_err(msm_sdw->dev,
228 "%s: failed to enable SDW MCLK\n",
229 __func__);
230 goto rtn;
231 }
232 dev_dbg(msm_sdw->dev,
233 "enabled sdw codec core mclk\n");
234 msm_sdw->int_mclk1_enabled = true;
235 }
236 }
237 msm_sdw->int_mclk1_rsc_ref++;
238 } else {
239 cancel_delayed_work_sync(&msm_sdw->disable_int_mclk1_work);
240 if (msm_sdw->int_mclk1_rsc_ref > 0) {
241 msm_sdw->int_mclk1_rsc_ref--;
242 dev_dbg(msm_sdw->dev,
243 "%s: decrementing mclk_res_ref %d\n",
244 __func__, msm_sdw->int_mclk1_rsc_ref);
245 }
246 if (msm_sdw->int_mclk1_enabled == true &&
247 msm_sdw->int_mclk1_rsc_ref == 0) {
248 msm_sdw->sdw_cdc_core_clk.enable = 0;
249 ret = afe_set_lpass_clock_v2(
250 AFE_PORT_ID_INT4_MI2S_RX,
251 &msm_sdw->sdw_cdc_core_clk);
252 if (ret < 0)
253 dev_err(msm_sdw->dev,
254 "%s: failed to disable SDW MCLK\n",
255 __func__);
256 msm_sdw->int_mclk1_enabled = false;
257 }
258 }
259 mutex_unlock(&msm_sdw->cdc_int_mclk1_mutex);
260rtn:
261 return ret;
262}
263EXPORT_SYMBOL(msm_int_enable_sdw_cdc_clk);
264
265static void msm_disable_int_mclk1(struct work_struct *work)
266{
267 struct msm_sdw_priv *msm_sdw = NULL;
268 struct delayed_work *dwork;
269 int ret = 0;
270
271 dwork = to_delayed_work(work);
272 msm_sdw = container_of(dwork, struct msm_sdw_priv,
273 disable_int_mclk1_work);
274 mutex_lock(&msm_sdw->cdc_int_mclk1_mutex);
275 dev_dbg(msm_sdw->dev, "%s: mclk1_enabled %d mclk1_rsc_ref %d\n",
276 __func__, msm_sdw->int_mclk1_enabled,
277 msm_sdw->int_mclk1_rsc_ref);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530278 if (msm_sdw->int_mclk1_enabled == true
279 && msm_sdw->int_mclk1_rsc_ref == 0) {
280 dev_dbg(msm_sdw->dev, "Disable the mclk1\n");
281 msm_sdw->sdw_cdc_core_clk.enable = 0;
282 ret = afe_set_lpass_clock_v2(
283 AFE_PORT_ID_INT4_MI2S_RX,
284 &msm_sdw->sdw_cdc_core_clk);
285 if (ret < 0)
286 dev_err(msm_sdw->dev,
287 "%s failed to disable the MCLK1\n",
288 __func__);
289 msm_sdw->int_mclk1_enabled = false;
290 }
291 mutex_unlock(&msm_sdw->cdc_int_mclk1_mutex);
292}
293
294static int msm_int_mclk1_event(struct snd_soc_dapm_widget *w,
295 struct snd_kcontrol *kcontrol, int event)
296{
297 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
298 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
299 int ret = 0;
300
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530301 dev_dbg(msm_sdw->dev, "%s: event = %d\n", __func__, event);
302 switch (event) {
303 case SND_SOC_DAPM_PRE_PMU:
304 /* enable the codec mclk config */
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530305 msm_int_enable_sdw_cdc_clk(msm_sdw, 1, true);
306 msm_sdw_mclk_enable(msm_sdw, 1, true);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530307 break;
308 case SND_SOC_DAPM_POST_PMD:
309 /* disable the codec mclk config */
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530310 msm_sdw_mclk_enable(msm_sdw, 0, true);
311 msm_int_enable_sdw_cdc_clk(msm_sdw, 0, true);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530312 break;
313 default:
314 dev_err(msm_sdw->dev,
315 "%s: invalid DAPM event %d\n", __func__, event);
316 ret = -EINVAL;
317 }
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530318 return ret;
319}
320
321static int msm_sdw_ahb_write_device(struct msm_sdw_priv *msm_sdw,
322 u16 reg, u8 *value)
323{
324 u32 temp = (u32)(*value) & 0x000000FF;
325
326 if (!msm_sdw->dev_up) {
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530327 dev_err_ratelimited(msm_sdw->dev, "%s: q6 not ready\n",
328 __func__);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530329 return 0;
330 }
331
332 iowrite32(temp, msm_sdw->sdw_base + reg);
333 return 0;
334}
335
336static int msm_sdw_ahb_read_device(struct msm_sdw_priv *msm_sdw,
337 u16 reg, u8 *value)
338{
339 u32 temp;
340
341 if (!msm_sdw->dev_up) {
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530342 dev_err_ratelimited(msm_sdw->dev, "%s: q6 not ready\n",
343 __func__);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530344 return 0;
345 }
346
347 temp = ioread32(msm_sdw->sdw_base + reg);
348 *value = (u8)temp;
349 return 0;
350}
351
352static int __msm_sdw_reg_read(struct msm_sdw_priv *msm_sdw, unsigned short reg,
353 int bytes, void *dest)
354{
355 int ret = -EINVAL, i;
356 u8 temp = 0;
357
358 dev_dbg(msm_sdw->dev, "%s reg = %x\n", __func__, reg);
359 mutex_lock(&msm_sdw->cdc_int_mclk1_mutex);
360 if (msm_sdw->int_mclk1_enabled == false) {
361 msm_sdw->sdw_cdc_core_clk.enable = 1;
362 ret = afe_set_lpass_clock_v2(
363 AFE_PORT_ID_INT4_MI2S_RX,
364 &msm_sdw->sdw_cdc_core_clk);
365 if (ret < 0) {
366 dev_err(msm_sdw->dev,
367 "%s:failed to enable the INT_MCLK1\n",
368 __func__);
369 goto unlock_exit;
370 }
371 dev_dbg(msm_sdw->dev, "%s:enabled sdw codec core clk\n",
372 __func__);
373 for (i = 0; i < bytes; i++) {
374 ret = msm_sdw_ahb_read_device(
375 msm_sdw, reg + (4 * i), &temp);
376 ((u8 *)dest)[i] = temp;
377 }
378 msm_sdw->int_mclk1_enabled = true;
379 schedule_delayed_work(&msm_sdw->disable_int_mclk1_work, 50);
380 goto unlock_exit;
381 }
382 for (i = 0; i < bytes; i++) {
383 ret = msm_sdw_ahb_read_device(
384 msm_sdw, reg + (4 * i), &temp);
385 ((u8 *)dest)[i] = temp;
386 }
387unlock_exit:
388 mutex_unlock(&msm_sdw->cdc_int_mclk1_mutex);
389 if (ret < 0) {
390 dev_err_ratelimited(msm_sdw->dev,
391 "%s: codec read failed for reg 0x%x\n",
392 __func__, reg);
393 return ret;
394 }
395 dev_dbg(msm_sdw->dev, "Read 0x%02x from 0x%x\n", temp, reg);
396
397 return 0;
398}
399
400static int __msm_sdw_reg_write(struct msm_sdw_priv *msm_sdw, unsigned short reg,
401 int bytes, void *src)
402{
403 int ret = -EINVAL, i;
404
405 mutex_lock(&msm_sdw->cdc_int_mclk1_mutex);
406 if (msm_sdw->int_mclk1_enabled == false) {
407 msm_sdw->sdw_cdc_core_clk.enable = 1;
408 ret = afe_set_lpass_clock_v2(AFE_PORT_ID_INT4_MI2S_RX,
409 &msm_sdw->sdw_cdc_core_clk);
410 if (ret < 0) {
411 dev_err(msm_sdw->dev,
412 "%s: failed to enable the INT_MCLK1\n",
413 __func__);
414 ret = 0;
415 goto unlock_exit;
416 }
417 dev_dbg(msm_sdw->dev, "%s: enabled INT_MCLK1\n", __func__);
418 for (i = 0; i < bytes; i++)
419 ret = msm_sdw_ahb_write_device(msm_sdw, reg + (4 * i),
420 &((u8 *)src)[i]);
421 msm_sdw->int_mclk1_enabled = true;
422 schedule_delayed_work(&msm_sdw->disable_int_mclk1_work, 50);
423 goto unlock_exit;
424 }
425 for (i = 0; i < bytes; i++)
426 ret = msm_sdw_ahb_write_device(msm_sdw, reg + (4 * i),
427 &((u8 *)src)[i]);
428unlock_exit:
429 mutex_unlock(&msm_sdw->cdc_int_mclk1_mutex);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530430 dev_dbg(msm_sdw->dev, "Write 0x%x val 0x%02x\n",
431 reg, (u32)(*(u32 *)src));
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530432
433 return ret;
434}
435
436static int msm_sdw_codec_enable_vi_feedback(struct snd_soc_dapm_widget *w,
437 struct snd_kcontrol *kcontrol,
438 int event)
439{
440 struct snd_soc_codec *codec = NULL;
441 struct msm_sdw_priv *msm_sdw_p = NULL;
442 int ret = 0;
443
444 if (!w) {
445 pr_err("%s invalid params\n", __func__);
446 return -EINVAL;
447 }
448 codec = snd_soc_dapm_to_codec(w->dapm);
449 msm_sdw_p = snd_soc_codec_get_drvdata(codec);
450
451 dev_dbg(codec->dev, "%s: num_dai %d stream name %s\n",
452 __func__, codec->component.num_dai, w->sname);
453
454 dev_dbg(codec->dev, "%s(): w->name %s event %d w->shift %d\n",
455 __func__, w->name, event, w->shift);
456 if (w->shift != AIF1_SDW_VIFEED) {
457 dev_err(codec->dev,
458 "%s:Error in enabling the vi feedback path\n",
459 __func__);
460 ret = -EINVAL;
461 goto out_vi;
462 }
463 switch (event) {
464 case SND_SOC_DAPM_POST_PMU:
465 if (test_bit(VI_SENSE_1, &msm_sdw_p->status_mask)) {
466 dev_dbg(codec->dev, "%s: spkr1 enabled\n", __func__);
467 /* Enable V&I sensing */
468 snd_soc_update_bits(codec,
469 MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
470 snd_soc_update_bits(codec,
471 MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x20,
472 0x20);
473 snd_soc_update_bits(codec,
Laxminath Kasam93efc172017-02-23 18:23:21 +0530474 MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x0F, 0x04);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530475 snd_soc_update_bits(codec,
Laxminath Kasam93efc172017-02-23 18:23:21 +0530476 MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x0F, 0x04);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530477 snd_soc_update_bits(codec,
478 MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x10);
479 snd_soc_update_bits(codec,
480 MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x10,
481 0x10);
482 snd_soc_update_bits(codec,
483 MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x00);
484 snd_soc_update_bits(codec,
485 MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x20,
486 0x00);
487 }
488 if (test_bit(VI_SENSE_2, &msm_sdw_p->status_mask)) {
489 dev_dbg(codec->dev, "%s: spkr2 enabled\n", __func__);
490 /* Enable V&I sensing */
491 snd_soc_update_bits(codec,
492 MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x20,
493 0x20);
494 snd_soc_update_bits(codec,
495 MSM_SDW_TX12_SPKR_PROT_PATH_CTL, 0x20,
496 0x20);
497 snd_soc_update_bits(codec,
498 MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x0F,
Laxminath Kasam93efc172017-02-23 18:23:21 +0530499 0x04);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530500 snd_soc_update_bits(codec,
501 MSM_SDW_TX12_SPKR_PROT_PATH_CTL, 0x0F,
Laxminath Kasam93efc172017-02-23 18:23:21 +0530502 0x04);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530503 snd_soc_update_bits(codec,
504 MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x10,
505 0x10);
506 snd_soc_update_bits(codec,
507 MSM_SDW_TX12_SPKR_PROT_PATH_CTL, 0x10,
508 0x10);
509 snd_soc_update_bits(codec,
510 MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x20,
511 0x00);
512 snd_soc_update_bits(codec,
513 MSM_SDW_TX12_SPKR_PROT_PATH_CTL, 0x20,
514 0x00);
515 }
516 break;
517 case SND_SOC_DAPM_POST_PMD:
518 if (test_bit(VI_SENSE_1, &msm_sdw_p->status_mask)) {
519 /* Disable V&I sensing */
520 dev_dbg(codec->dev, "%s: spkr1 disabled\n", __func__);
521 snd_soc_update_bits(codec,
522 MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x20, 0x20);
523 snd_soc_update_bits(codec,
524 MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x20,
525 0x20);
526 snd_soc_update_bits(codec,
527 MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x00);
528 snd_soc_update_bits(codec,
529 MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x10,
530 0x00);
531 }
532 if (test_bit(VI_SENSE_2, &msm_sdw_p->status_mask)) {
533 /* Disable V&I sensing */
534 dev_dbg(codec->dev, "%s: spkr2 disabled\n", __func__);
535 snd_soc_update_bits(codec,
536 MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x20,
537 0x20);
538 snd_soc_update_bits(codec,
539 MSM_SDW_TX12_SPKR_PROT_PATH_CTL, 0x20,
540 0x20);
541 snd_soc_update_bits(codec,
542 MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x10,
543 0x00);
544 snd_soc_update_bits(codec,
545 MSM_SDW_TX12_SPKR_PROT_PATH_CTL, 0x10,
546 0x00);
547 }
548 break;
549 }
550out_vi:
551 return ret;
552}
553
554static int msm_sdwm_handle_irq(void *handle,
555 irqreturn_t (*swrm_irq_handler)(int irq,
556 void *data),
557 void *swrm_handle,
558 int action)
559{
560 struct msm_sdw_priv *msm_sdw;
561 int ret = 0;
562
563 if (!handle) {
564 pr_err("%s: null handle received\n", __func__);
565 return -EINVAL;
566 }
567 msm_sdw = (struct msm_sdw_priv *) handle;
568
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530569 if (skip_irq)
570 return ret;
571
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530572 if (action) {
573 ret = request_threaded_irq(msm_sdw->sdw_irq, NULL,
574 swrm_irq_handler,
575 IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
576 "swr_master_irq", swrm_handle);
577 if (ret)
578 dev_err(msm_sdw->dev, "%s: Failed to request irq %d\n",
579 __func__, ret);
580 } else
581 free_irq(msm_sdw->sdw_irq, swrm_handle);
582
583 return ret;
584}
585
586static void msm_sdw_codec_hd2_control(struct snd_soc_codec *codec,
587 u16 reg, int event)
588{
589 u16 hd2_scale_reg;
590 u16 hd2_enable_reg = 0;
591
592 if (reg == MSM_SDW_RX7_RX_PATH_CTL) {
593 hd2_scale_reg = MSM_SDW_RX7_RX_PATH_SEC3;
594 hd2_enable_reg = MSM_SDW_RX7_RX_PATH_CFG0;
595 }
596 if (reg == MSM_SDW_RX8_RX_PATH_CTL) {
597 hd2_scale_reg = MSM_SDW_RX8_RX_PATH_SEC3;
598 hd2_enable_reg = MSM_SDW_RX8_RX_PATH_CFG0;
599 }
600
601 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_ON(event)) {
602 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x10);
603 snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x01);
604 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x04);
605 }
606
607 if (hd2_enable_reg && SND_SOC_DAPM_EVENT_OFF(event)) {
608 snd_soc_update_bits(codec, hd2_enable_reg, 0x04, 0x00);
609 snd_soc_update_bits(codec, hd2_scale_reg, 0x03, 0x00);
610 snd_soc_update_bits(codec, hd2_scale_reg, 0x3C, 0x00);
611 }
612}
613
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530614static int msm_sdw_enable_swr(struct snd_soc_dapm_widget *w,
615 struct snd_kcontrol *kcontrol, int event)
616{
617 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
618 struct msm_sdw_priv *msm_sdw;
619 int i, ch_cnt;
620
621 msm_sdw = snd_soc_codec_get_drvdata(codec);
622
623 if (!msm_sdw->nr)
624 return 0;
625
626 switch (event) {
627 case SND_SOC_DAPM_PRE_PMU:
628 if (!(strnstr(w->name, "RX4", sizeof("RX4 MIX"))) &&
629 !msm_sdw->rx_4_count)
630 msm_sdw->rx_4_count++;
631 if (!(strnstr(w->name, "RX5", sizeof("RX5 MIX"))) &&
632 !msm_sdw->rx_5_count)
633 msm_sdw->rx_5_count++;
634 ch_cnt = msm_sdw->rx_4_count + msm_sdw->rx_5_count;
635
636 for (i = 0; i < msm_sdw->nr; i++) {
637 swrm_wcd_notify(msm_sdw->sdw_ctrl_data[i].sdw_pdev,
638 SWR_DEVICE_UP, NULL);
639 swrm_wcd_notify(msm_sdw->sdw_ctrl_data[i].sdw_pdev,
640 SWR_SET_NUM_RX_CH, &ch_cnt);
641 }
642 break;
643 case SND_SOC_DAPM_POST_PMD:
644 if (!(strnstr(w->name, "RX4", sizeof("RX4 MIX"))) &&
645 msm_sdw->rx_4_count)
646 msm_sdw->rx_4_count--;
647 if (!(strnstr(w->name, "RX5", sizeof("RX5 MIX"))) &&
648 msm_sdw->rx_5_count)
649 msm_sdw->rx_5_count--;
650 ch_cnt = msm_sdw->rx_4_count + msm_sdw->rx_5_count;
651
652 for (i = 0; i < msm_sdw->nr; i++)
653 swrm_wcd_notify(msm_sdw->sdw_ctrl_data[i].sdw_pdev,
654 SWR_SET_NUM_RX_CH, &ch_cnt);
655 break;
656 }
657 dev_dbg(msm_sdw->dev, "%s: current swr ch cnt: %d\n",
658 __func__, msm_sdw->rx_4_count + msm_sdw->rx_5_count);
659
660 return 0;
661}
662
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530663static int msm_sdw_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
664 struct snd_kcontrol *kcontrol,
665 int event)
666{
667 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
668 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
669 u16 gain_reg;
670 u16 reg;
671 int val;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530672 int offset_val = 0;
673
674 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
675
676 if (!(strcmp(w->name, "RX INT4 INTERP"))) {
677 reg = MSM_SDW_RX7_RX_PATH_CTL;
678 gain_reg = MSM_SDW_RX7_RX_VOL_CTL;
679 } else if (!(strcmp(w->name, "RX INT5 INTERP"))) {
680 reg = MSM_SDW_RX8_RX_PATH_CTL;
681 gain_reg = MSM_SDW_RX8_RX_VOL_CTL;
682 } else {
683 dev_err(codec->dev, "%s: Interpolator reg not found\n",
684 __func__);
685 return -EINVAL;
686 }
687
688 switch (event) {
689 case SND_SOC_DAPM_PRE_PMU:
690 snd_soc_update_bits(codec, reg, 0x10, 0x10);
691 msm_sdw_codec_hd2_control(codec, reg, event);
692 snd_soc_update_bits(codec, reg, 1 << 0x5, 1 << 0x5);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530693 break;
694 case SND_SOC_DAPM_POST_PMU:
695 msm_sdw_config_compander(codec, w->shift, event);
696 /* apply gain after int clk is enabled */
697 if ((msm_sdw->spkr_gain_offset == RX_GAIN_OFFSET_M1P5_DB) &&
698 (msm_sdw->comp_enabled[COMP1] ||
699 msm_sdw->comp_enabled[COMP2]) &&
700 (gain_reg == MSM_SDW_RX7_RX_VOL_CTL ||
701 gain_reg == MSM_SDW_RX8_RX_VOL_CTL)) {
702 snd_soc_update_bits(codec, MSM_SDW_RX7_RX_PATH_SEC1,
703 0x01, 0x01);
704 snd_soc_update_bits(codec,
705 MSM_SDW_RX7_RX_PATH_MIX_SEC0,
706 0x01, 0x01);
707 snd_soc_update_bits(codec, MSM_SDW_RX8_RX_PATH_SEC1,
708 0x01, 0x01);
709 snd_soc_update_bits(codec,
710 MSM_SDW_RX8_RX_PATH_MIX_SEC0,
711 0x01, 0x01);
712 offset_val = -2;
713 }
714 val = snd_soc_read(codec, gain_reg);
715 val += offset_val;
716 snd_soc_write(codec, gain_reg, val);
717 msm_sdw_config_ear_spkr_gain(codec, event, gain_reg);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530718 snd_soc_update_bits(codec, reg, 0x10, 0x00);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530719 break;
720 case SND_SOC_DAPM_POST_PMD:
721 snd_soc_update_bits(codec, reg, 1 << 0x5, 0 << 0x5);
722 snd_soc_update_bits(codec, reg, 0x40, 0x40);
723 snd_soc_update_bits(codec, reg, 0x40, 0x00);
724 msm_sdw_codec_hd2_control(codec, reg, event);
725 msm_sdw_config_compander(codec, w->shift, event);
726 if ((msm_sdw->spkr_gain_offset == RX_GAIN_OFFSET_M1P5_DB) &&
727 (msm_sdw->comp_enabled[COMP1] ||
728 msm_sdw->comp_enabled[COMP2]) &&
729 (gain_reg == MSM_SDW_RX7_RX_VOL_CTL ||
730 gain_reg == MSM_SDW_RX8_RX_VOL_CTL)) {
731 snd_soc_update_bits(codec, MSM_SDW_RX7_RX_PATH_SEC1,
732 0x01, 0x00);
733 snd_soc_update_bits(codec,
734 MSM_SDW_RX7_RX_PATH_MIX_SEC0,
735 0x01, 0x00);
736 snd_soc_update_bits(codec, MSM_SDW_RX8_RX_PATH_SEC1,
737 0x01, 0x00);
738 snd_soc_update_bits(codec,
739 MSM_SDW_RX8_RX_PATH_MIX_SEC0,
740 0x01, 0x00);
741 offset_val = 2;
742 val = snd_soc_read(codec, gain_reg);
743 val += offset_val;
744 snd_soc_write(codec, gain_reg, val);
745 }
746 msm_sdw_config_ear_spkr_gain(codec, event, gain_reg);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530747 break;
748 };
749
750 return 0;
751}
752
753static int msm_sdw_config_ear_spkr_gain(struct snd_soc_codec *codec,
754 int event, int gain_reg)
755{
756 int comp_gain_offset, val;
757 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
758
759 switch (msm_sdw->spkr_mode) {
760 /* Compander gain in SPKR_MODE1 case is 12 dB */
761 case SPKR_MODE_1:
762 comp_gain_offset = -12;
763 break;
764 /* Default case compander gain is 15 dB */
765 default:
766 comp_gain_offset = -15;
767 break;
768 }
769
770 switch (event) {
771 case SND_SOC_DAPM_POST_PMU:
772 /* Apply ear spkr gain only if compander is enabled */
773 if (msm_sdw->comp_enabled[COMP1] &&
774 (gain_reg == MSM_SDW_RX7_RX_VOL_CTL) &&
775 (msm_sdw->ear_spkr_gain != 0)) {
776 /* For example, val is -8(-12+5-1) for 4dB of gain */
777 val = comp_gain_offset + msm_sdw->ear_spkr_gain - 1;
778 snd_soc_write(codec, gain_reg, val);
779
780 dev_dbg(codec->dev, "%s: RX4 Volume %d dB\n",
781 __func__, val);
782 }
783 break;
784 case SND_SOC_DAPM_POST_PMD:
785 /*
786 * Reset RX4 volume to 0 dB if compander is enabled and
787 * ear_spkr_gain is non-zero.
788 */
789 if (msm_sdw->comp_enabled[COMP1] &&
790 (gain_reg == MSM_SDW_RX7_RX_VOL_CTL) &&
791 (msm_sdw->ear_spkr_gain != 0)) {
792 snd_soc_write(codec, gain_reg, 0x0);
793
794 dev_dbg(codec->dev, "%s: Reset RX4 Volume to 0 dB\n",
795 __func__);
796 }
797 break;
798 }
799
800 return 0;
801}
802
803static int msm_sdw_codec_spk_boost_event(struct snd_soc_dapm_widget *w,
804 struct snd_kcontrol *kcontrol,
805 int event)
806{
807 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
808 u16 boost_path_ctl, boost_path_cfg1;
809 u16 reg;
810
811 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
812
813 if (!strcmp(w->name, "RX INT4 CHAIN")) {
814 boost_path_ctl = MSM_SDW_BOOST0_BOOST_PATH_CTL;
815 boost_path_cfg1 = MSM_SDW_RX7_RX_PATH_CFG1;
816 reg = MSM_SDW_RX7_RX_PATH_CTL;
817 } else if (!strcmp(w->name, "RX INT5 CHAIN")) {
818 boost_path_ctl = MSM_SDW_BOOST1_BOOST_PATH_CTL;
819 boost_path_cfg1 = MSM_SDW_RX8_RX_PATH_CFG1;
820 reg = MSM_SDW_RX8_RX_PATH_CTL;
821 } else {
822 dev_err(codec->dev, "%s: boost reg not found\n",
823 __func__);
824 return -EINVAL;
825 }
826
827 switch (event) {
828 case SND_SOC_DAPM_PRE_PMU:
829 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x10);
830 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x01);
831 snd_soc_update_bits(codec, reg, 0x10, 0x00);
832 break;
833 case SND_SOC_DAPM_POST_PMD:
834 snd_soc_update_bits(codec, boost_path_cfg1, 0x01, 0x00);
835 snd_soc_update_bits(codec, boost_path_ctl, 0x10, 0x00);
836 break;
837 };
838
839 return 0;
840}
841
842static int msm_sdw_config_compander(struct snd_soc_codec *codec, int comp,
843 int event)
844{
845 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
846 u16 comp_ctl0_reg, rx_path_cfg0_reg;
847
848 if (comp < COMP1 || comp >= COMP_MAX)
849 return 0;
850
851 dev_dbg(codec->dev, "%s: event %d compander %d, enabled %d\n",
852 __func__, event, comp + 1, msm_sdw->comp_enabled[comp]);
853
854 if (!msm_sdw->comp_enabled[comp])
855 return 0;
856
Laxminath Kasam23f6a5b2017-03-15 22:04:26 +0530857 comp_ctl0_reg = MSM_SDW_COMPANDER7_CTL0 + (comp * 0x20);
858 rx_path_cfg0_reg = MSM_SDW_RX7_RX_PATH_CFG0 + (comp * 0x1E0);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530859
860 if (SND_SOC_DAPM_EVENT_ON(event)) {
861 /* Enable Compander Clock */
862 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x01);
863 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
864 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
865 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x02);
866 }
867
868 if (SND_SOC_DAPM_EVENT_OFF(event)) {
869 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x04);
870 snd_soc_update_bits(codec, rx_path_cfg0_reg, 0x02, 0x00);
871 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x02);
872 snd_soc_update_bits(codec, comp_ctl0_reg, 0x02, 0x00);
873 snd_soc_update_bits(codec, comp_ctl0_reg, 0x01, 0x00);
874 snd_soc_update_bits(codec, comp_ctl0_reg, 0x04, 0x00);
875 }
876
877 return 0;
878}
879
880static int msm_sdw_get_compander(struct snd_kcontrol *kcontrol,
881 struct snd_ctl_elem_value *ucontrol)
882{
883
884 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
885 int comp = ((struct soc_multi_mixer_control *)
886 kcontrol->private_value)->shift;
887 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
888
889 ucontrol->value.integer.value[0] = msm_sdw->comp_enabled[comp];
890 return 0;
891}
892
893static int msm_sdw_set_compander(struct snd_kcontrol *kcontrol,
894 struct snd_ctl_elem_value *ucontrol)
895{
896 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
897 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
898 int comp = ((struct soc_multi_mixer_control *)
899 kcontrol->private_value)->shift;
900 int value = ucontrol->value.integer.value[0];
901
902 dev_dbg(codec->dev, "%s: Compander %d enable current %d, new %d\n",
903 __func__, comp + 1, msm_sdw->comp_enabled[comp], value);
904 msm_sdw->comp_enabled[comp] = value;
905
906 return 0;
907}
908
909static int msm_sdw_ear_spkr_pa_gain_get(struct snd_kcontrol *kcontrol,
910 struct snd_ctl_elem_value *ucontrol)
911{
912 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
913 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
914
915 ucontrol->value.integer.value[0] = msm_sdw->ear_spkr_gain;
916
917 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
918 __func__, ucontrol->value.integer.value[0]);
919
920 return 0;
921}
922
923static int msm_sdw_ear_spkr_pa_gain_put(struct snd_kcontrol *kcontrol,
924 struct snd_ctl_elem_value *ucontrol)
925{
926 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
927 struct msm_sdw_priv *msm_sdw = snd_soc_codec_get_drvdata(codec);
928
929 msm_sdw->ear_spkr_gain = ucontrol->value.integer.value[0];
930
931 dev_dbg(codec->dev, "%s: gain = %d\n", __func__,
932 msm_sdw->ear_spkr_gain);
933
934 return 0;
935}
936
937static int msm_sdw_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
938 struct snd_ctl_elem_value *ucontrol)
939{
Banajit Goswami8b3579b2017-07-21 01:11:17 -0700940 struct snd_soc_dapm_widget *widget =
941 snd_soc_dapm_kcontrol_widget(kcontrol);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530942 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
943 struct msm_sdw_priv *msm_sdw_p = snd_soc_codec_get_drvdata(codec);
944
945 ucontrol->value.integer.value[0] = msm_sdw_p->vi_feed_value;
946
947 return 0;
948}
949
950static int msm_sdw_vi_feed_mixer_put(struct snd_kcontrol *kcontrol,
951 struct snd_ctl_elem_value *ucontrol)
952{
Banajit Goswami8b3579b2017-07-21 01:11:17 -0700953 struct snd_soc_dapm_widget *widget =
954 snd_soc_dapm_kcontrol_widget(kcontrol);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530955 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(widget->dapm);
956 struct msm_sdw_priv *msm_sdw_p = snd_soc_codec_get_drvdata(codec);
957 struct soc_multi_mixer_control *mixer =
958 ((struct soc_multi_mixer_control *)kcontrol->private_value);
959 u32 dai_id = widget->shift;
960 u32 port_id = mixer->shift;
961 u32 enable = ucontrol->value.integer.value[0];
962
963 dev_dbg(codec->dev, "%s: enable: %d, port_id:%d, dai_id: %d\n",
964 __func__, enable, port_id, dai_id);
965
966 msm_sdw_p->vi_feed_value = ucontrol->value.integer.value[0];
967
968 mutex_lock(&msm_sdw_p->codec_mutex);
969 if (enable) {
970 if (port_id == MSM_SDW_TX0 && !test_bit(VI_SENSE_1,
971 &msm_sdw_p->status_mask))
972 set_bit(VI_SENSE_1, &msm_sdw_p->status_mask);
973 if (port_id == MSM_SDW_TX1 && !test_bit(VI_SENSE_2,
974 &msm_sdw_p->status_mask))
975 set_bit(VI_SENSE_2, &msm_sdw_p->status_mask);
976 } else {
977 if (port_id == MSM_SDW_TX0 && test_bit(VI_SENSE_1,
978 &msm_sdw_p->status_mask))
979 clear_bit(VI_SENSE_1, &msm_sdw_p->status_mask);
980 if (port_id == MSM_SDW_TX1 && test_bit(VI_SENSE_2,
981 &msm_sdw_p->status_mask))
982 clear_bit(VI_SENSE_2, &msm_sdw_p->status_mask);
983 }
984 mutex_unlock(&msm_sdw_p->codec_mutex);
985 snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
986
987 return 0;
988}
989
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530990static int msm_sdw_mclk_enable(struct msm_sdw_priv *msm_sdw,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530991 int mclk_enable, bool dapm)
992{
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530993 dev_dbg(msm_sdw->dev, "%s: mclk_enable = %u, dapm = %d clk_users= %d\n",
994 __func__, mclk_enable, dapm, msm_sdw->sdw_mclk_users);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +0530995 if (mclk_enable) {
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +0530996 msm_sdw->sdw_mclk_users++;
997 if (msm_sdw->sdw_mclk_users == 1) {
998 regmap_update_bits(msm_sdw->regmap,
999 MSM_SDW_CLK_RST_CTRL_FS_CNT_CONTROL,
1000 0x01, 0x01);
1001 regmap_update_bits(msm_sdw->regmap,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301002 MSM_SDW_CLK_RST_CTRL_MCLK_CONTROL,
1003 0x01, 0x01);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301004 /* 9.6MHz MCLK, set value 0x00 if other frequency */
1005 regmap_update_bits(msm_sdw->regmap,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301006 MSM_SDW_TOP_FREQ_MCLK, 0x01, 0x01);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301007 }
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301008 } else {
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301009 msm_sdw->sdw_mclk_users--;
1010 if (msm_sdw->sdw_mclk_users == 0) {
1011 regmap_update_bits(msm_sdw->regmap,
1012 MSM_SDW_CLK_RST_CTRL_FS_CNT_CONTROL,
1013 0x01, 0x00);
1014 regmap_update_bits(msm_sdw->regmap,
1015 MSM_SDW_CLK_RST_CTRL_MCLK_CONTROL,
1016 0x01, 0x00);
1017 }
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301018 }
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301019 return 0;
1020}
1021EXPORT_SYMBOL(msm_sdw_mclk_enable);
1022
1023static int msm_sdw_swrm_read(void *handle, int reg)
1024{
1025 struct msm_sdw_priv *msm_sdw;
1026 unsigned short sdw_rd_addr_base;
1027 unsigned short sdw_rd_data_base;
1028 int val, ret;
1029
1030 if (!handle) {
1031 pr_err("%s: NULL handle\n", __func__);
1032 return -EINVAL;
1033 }
1034 msm_sdw = (struct msm_sdw_priv *)handle;
1035
1036 dev_dbg(msm_sdw->dev, "%s: Reading soundwire register, 0x%x\n",
1037 __func__, reg);
1038 sdw_rd_addr_base = MSM_SDW_AHB_BRIDGE_RD_ADDR_0;
1039 sdw_rd_data_base = MSM_SDW_AHB_BRIDGE_RD_DATA_0;
Laxminath Kasam578305c2017-02-20 22:49:12 +05301040 /*
1041 * Add sleep as SWR slave access read takes time.
1042 * Allow for RD_DONE to complete for previous register if any.
1043 */
Laxminath Kasam83b76722017-03-18 12:37:30 +05301044 usleep_range(100, 105);
Laxminath Kasam578305c2017-02-20 22:49:12 +05301045
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301046 /* read_lock */
1047 mutex_lock(&msm_sdw->sdw_read_lock);
1048 ret = regmap_bulk_write(msm_sdw->regmap, sdw_rd_addr_base,
1049 (u8 *)&reg, 4);
1050 if (ret < 0) {
1051 dev_err(msm_sdw->dev, "%s: RD Addr Failure\n", __func__);
1052 goto err;
1053 }
Laxminath Kasamb5b7adf2017-05-26 20:09:52 +05301054 /* Add sleep for SWR register read value to get updated. */
1055 usleep_range(100, 105);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301056 /* Check for RD value */
1057 ret = regmap_bulk_read(msm_sdw->regmap, sdw_rd_data_base,
1058 (u8 *)&val, 4);
1059 if (ret < 0) {
1060 dev_err(msm_sdw->dev, "%s: RD Data Failure\n", __func__);
1061 goto err;
1062 }
1063 ret = val;
1064err:
1065 /* read_unlock */
1066 mutex_unlock(&msm_sdw->sdw_read_lock);
1067 return ret;
1068}
1069
1070static int msm_sdw_bulk_write(struct msm_sdw_priv *msm_sdw,
1071 struct msm_sdw_reg_val *bulk_reg,
1072 size_t len)
1073{
1074 int i, ret = 0;
1075 unsigned short sdw_wr_addr_base;
1076 unsigned short sdw_wr_data_base;
1077
1078 sdw_wr_addr_base = MSM_SDW_AHB_BRIDGE_WR_ADDR_0;
1079 sdw_wr_data_base = MSM_SDW_AHB_BRIDGE_WR_DATA_0;
1080
1081 for (i = 0; i < len; i += 2) {
Laxminath Kasamb5b7adf2017-05-26 20:09:52 +05301082 /*
1083 * Add sleep as SWR slave write takes time.
1084 * Allow for any previous pending write to complete.
1085 */
1086 usleep_range(100, 105);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301087 /* First Write the Data to register */
1088 ret = regmap_bulk_write(msm_sdw->regmap,
1089 sdw_wr_data_base, bulk_reg[i].buf, 4);
1090 if (ret < 0) {
1091 dev_err(msm_sdw->dev, "%s: WR Data Failure\n",
1092 __func__);
1093 break;
1094 }
1095 /* Next Write Address */
1096 ret = regmap_bulk_write(msm_sdw->regmap,
1097 sdw_wr_addr_base, bulk_reg[i+1].buf, 4);
1098 if (ret < 0) {
1099 dev_err(msm_sdw->dev,
1100 "%s: WR Addr Failure: 0x%x\n",
1101 __func__, (u32)(bulk_reg[i+1].buf[0]));
1102 break;
1103 }
1104 }
1105 return ret;
1106}
1107
1108static int msm_sdw_swrm_bulk_write(void *handle, u32 *reg, u32 *val, size_t len)
1109{
1110 struct msm_sdw_priv *msm_sdw;
1111 struct msm_sdw_reg_val *bulk_reg;
1112 unsigned short sdw_wr_addr_base;
1113 unsigned short sdw_wr_data_base;
1114 int i, j, ret;
1115
1116 if (!handle) {
1117 pr_err("%s: NULL handle\n", __func__);
1118 return -EINVAL;
1119 }
1120
1121 msm_sdw = (struct msm_sdw_priv *)handle;
1122 if (len <= 0) {
1123 dev_err(msm_sdw->dev,
1124 "%s: Invalid size: %zu\n", __func__, len);
1125 return -EINVAL;
1126 }
1127
1128 sdw_wr_addr_base = MSM_SDW_AHB_BRIDGE_WR_ADDR_0;
1129 sdw_wr_data_base = MSM_SDW_AHB_BRIDGE_WR_DATA_0;
1130
1131 bulk_reg = kzalloc((2 * len * sizeof(struct msm_sdw_reg_val)),
1132 GFP_KERNEL);
1133 if (!bulk_reg)
1134 return -ENOMEM;
1135
1136 for (i = 0, j = 0; i < (len * 2); i += 2, j++) {
1137 bulk_reg[i].reg = sdw_wr_data_base;
1138 bulk_reg[i].buf = (u8 *)(&val[j]);
1139 bulk_reg[i].bytes = 4;
1140 bulk_reg[i+1].reg = sdw_wr_addr_base;
1141 bulk_reg[i+1].buf = (u8 *)(&reg[j]);
1142 bulk_reg[i+1].bytes = 4;
1143 }
1144 mutex_lock(&msm_sdw->sdw_write_lock);
1145
1146 ret = msm_sdw_bulk_write(msm_sdw, bulk_reg, (len * 2));
1147 if (ret)
1148 dev_err(msm_sdw->dev, "%s: swrm bulk write failed, ret: %d\n",
1149 __func__, ret);
1150
1151 mutex_unlock(&msm_sdw->sdw_write_lock);
1152 kfree(bulk_reg);
1153
1154 return ret;
1155}
1156
1157static int msm_sdw_swrm_write(void *handle, int reg, int val)
1158{
1159 struct msm_sdw_priv *msm_sdw;
1160 unsigned short sdw_wr_addr_base;
1161 unsigned short sdw_wr_data_base;
1162 struct msm_sdw_reg_val bulk_reg[2];
1163 int ret;
1164
1165 if (!handle) {
1166 pr_err("%s: NULL handle\n", __func__);
1167 return -EINVAL;
1168 }
1169 msm_sdw = (struct msm_sdw_priv *)handle;
1170
1171 sdw_wr_addr_base = MSM_SDW_AHB_BRIDGE_WR_ADDR_0;
1172 sdw_wr_data_base = MSM_SDW_AHB_BRIDGE_WR_DATA_0;
1173
1174 /* First Write the Data to register */
1175 bulk_reg[0].reg = sdw_wr_data_base;
1176 bulk_reg[0].buf = (u8 *)(&val);
1177 bulk_reg[0].bytes = 4;
1178 bulk_reg[1].reg = sdw_wr_addr_base;
1179 bulk_reg[1].buf = (u8 *)(&reg);
1180 bulk_reg[1].bytes = 4;
1181
1182 mutex_lock(&msm_sdw->sdw_write_lock);
1183
1184 ret = msm_sdw_bulk_write(msm_sdw, bulk_reg, 2);
1185 if (ret < 0)
1186 dev_err(msm_sdw->dev, "%s: WR Data Failure\n", __func__);
1187
1188 mutex_unlock(&msm_sdw->sdw_write_lock);
1189 return ret;
1190}
1191
1192static int msm_sdw_swrm_clock(void *handle, bool enable)
1193{
1194 struct msm_sdw_priv *msm_sdw = (struct msm_sdw_priv *) handle;
1195
1196 mutex_lock(&msm_sdw->sdw_clk_lock);
1197
1198 dev_dbg(msm_sdw->dev, "%s: swrm clock %s\n",
1199 __func__, (enable ? "enable" : "disable"));
1200 if (enable) {
1201 msm_sdw->sdw_clk_users++;
1202 if (msm_sdw->sdw_clk_users == 1) {
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301203 msm_int_enable_sdw_cdc_clk(msm_sdw, 1, true);
1204 msm_sdw_mclk_enable(msm_sdw, 1, true);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301205 regmap_update_bits(msm_sdw->regmap,
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301206 MSM_SDW_CLK_RST_CTRL_SWR_CONTROL, 0x01, 0x01);
1207 msm_enable_sdw_npl_clk(msm_sdw, true);
1208 msm_cdc_pinctrl_select_active_state(
1209 msm_sdw->sdw_gpio_p);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301210 }
1211 } else {
1212 msm_sdw->sdw_clk_users--;
1213 if (msm_sdw->sdw_clk_users == 0) {
1214 regmap_update_bits(msm_sdw->regmap,
1215 MSM_SDW_CLK_RST_CTRL_SWR_CONTROL,
1216 0x01, 0x00);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301217 msm_sdw_mclk_enable(msm_sdw, 0, true);
1218 msm_int_enable_sdw_cdc_clk(msm_sdw, 0, true);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301219 msm_enable_sdw_npl_clk(msm_sdw, false);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301220 msm_cdc_pinctrl_select_sleep_state(msm_sdw->sdw_gpio_p);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301221 }
1222 }
1223 dev_dbg(msm_sdw->dev, "%s: swrm clock users %d\n",
1224 __func__, msm_sdw->sdw_clk_users);
1225 mutex_unlock(&msm_sdw->sdw_clk_lock);
1226 return 0;
1227}
1228
1229static int msm_sdw_startup(struct snd_pcm_substream *substream,
1230 struct snd_soc_dai *dai)
1231{
1232 dev_dbg(dai->codec->dev, "%s(): substream = %s stream = %d\n",
1233 __func__,
1234 substream->name, substream->stream);
1235 return 0;
1236}
1237
1238static int msm_sdw_hw_params(struct snd_pcm_substream *substream,
1239 struct snd_pcm_hw_params *params,
1240 struct snd_soc_dai *dai)
1241{
Laxminath Kasam93efc172017-02-23 18:23:21 +05301242 u8 clk_fs_rate, fs_rate;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301243
1244 dev_dbg(dai->codec->dev,
1245 "%s: dai_name = %s DAI-ID %x rate %d num_ch %d format %d\n",
1246 __func__, dai->name, dai->id, params_rate(params),
1247 params_channels(params), params_format(params));
1248
1249 switch (params_rate(params)) {
1250 case 8000:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301251 clk_fs_rate = 0x00;
1252 fs_rate = 0x00;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301253 break;
1254 case 16000:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301255 clk_fs_rate = 0x01;
1256 fs_rate = 0x01;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301257 break;
1258 case 32000:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301259 clk_fs_rate = 0x02;
1260 fs_rate = 0x03;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301261 break;
1262 case 48000:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301263 clk_fs_rate = 0x03;
1264 fs_rate = 0x04;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301265 break;
1266 case 96000:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301267 clk_fs_rate = 0x04;
1268 fs_rate = 0x05;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301269 break;
1270 case 192000:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301271 clk_fs_rate = 0x05;
1272 fs_rate = 0x06;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301273 break;
1274 default:
1275 dev_err(dai->codec->dev,
1276 "%s: Invalid sampling rate %d\n", __func__,
1277 params_rate(params));
1278 return -EINVAL;
1279 }
1280
Laxminath Kasam93efc172017-02-23 18:23:21 +05301281 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1282 snd_soc_update_bits(dai->codec,
1283 MSM_SDW_TOP_TX_I2S_CTL, 0x1C,
1284 (clk_fs_rate << 2));
1285 } else {
1286 snd_soc_update_bits(dai->codec,
1287 MSM_SDW_TOP_RX_I2S_CTL, 0x1C,
1288 (clk_fs_rate << 2));
1289 snd_soc_update_bits(dai->codec,
1290 MSM_SDW_RX7_RX_PATH_CTL, 0x0F,
1291 fs_rate);
1292 snd_soc_update_bits(dai->codec,
1293 MSM_SDW_RX8_RX_PATH_CTL, 0x0F,
1294 fs_rate);
1295 }
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301296
1297 switch (params_format(params)) {
1298 case SNDRV_PCM_FORMAT_S16_LE:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301299 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1300 snd_soc_update_bits(dai->codec,
1301 MSM_SDW_TOP_TX_I2S_CTL, 0x20, 0x20);
1302 else
1303 snd_soc_update_bits(dai->codec,
1304 MSM_SDW_TOP_RX_I2S_CTL, 0x20, 0x20);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301305 break;
1306 case SNDRV_PCM_FORMAT_S24_LE:
1307 case SNDRV_PCM_FORMAT_S24_3LE:
Laxminath Kasam93efc172017-02-23 18:23:21 +05301308 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1309 snd_soc_update_bits(dai->codec,
1310 MSM_SDW_TOP_TX_I2S_CTL, 0x20, 0x00);
1311 else
1312 snd_soc_update_bits(dai->codec,
1313 MSM_SDW_TOP_RX_I2S_CTL, 0x20, 0x00);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301314 break;
1315 default:
1316 dev_err(dai->codec->dev, "%s: wrong format selected\n",
1317 __func__);
1318 return -EINVAL;
1319 }
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301320
1321 return 0;
1322}
1323
1324static void msm_sdw_shutdown(struct snd_pcm_substream *substream,
1325 struct snd_soc_dai *dai)
1326{
1327 dev_dbg(dai->codec->dev,
1328 "%s(): substream = %s stream = %d\n", __func__,
1329 substream->name, substream->stream);
1330}
1331
1332static ssize_t msm_sdw_codec_version_read(struct snd_info_entry *entry,
1333 void *file_private_data,
1334 struct file *file,
1335 char __user *buf, size_t count,
1336 loff_t pos)
1337{
1338 struct msm_sdw_priv *msm_sdw;
1339 char buffer[MSM_SDW_VERSION_ENTRY_SIZE];
1340 int len = 0;
1341
1342 msm_sdw = (struct msm_sdw_priv *) entry->private_data;
1343 if (!msm_sdw) {
1344 pr_err("%s: msm_sdw priv is null\n", __func__);
1345 return -EINVAL;
1346 }
1347
1348 switch (msm_sdw->version) {
1349 case MSM_SDW_VERSION_1_0:
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301350 len = snprintf(buffer, sizeof(buffer), "SDW-CDC_1_0\n");
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301351 break;
1352 default:
1353 len = snprintf(buffer, sizeof(buffer), "VER_UNDEFINED\n");
1354 }
1355
1356 return simple_read_from_buffer(buf, count, &pos, buffer, len);
1357}
1358
1359static struct snd_info_entry_ops msm_sdw_codec_info_ops = {
1360 .read = msm_sdw_codec_version_read,
1361};
1362
1363/*
1364 * msm_sdw_codec_info_create_codec_entry - creates msm_sdw module
1365 * @codec_root: The parent directory
1366 * @codec: Codec instance
1367 *
1368 * Creates msm_sdw module and version entry under the given
1369 * parent directory.
1370 *
1371 * Return: 0 on success or negative error code on failure.
1372 */
1373int msm_sdw_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
1374 struct snd_soc_codec *codec)
1375{
1376 struct snd_info_entry *version_entry;
1377 struct msm_sdw_priv *msm_sdw;
1378 struct snd_soc_card *card;
1379
1380 if (!codec_root || !codec)
1381 return -EINVAL;
1382
1383 msm_sdw = snd_soc_codec_get_drvdata(codec);
1384 card = codec->component.card;
Rohit Kumard5eb3e12017-06-28 15:18:46 +05301385 msm_sdw->entry = snd_info_create_subdir(codec_root->module,
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301386 "152c1000.msm-sdw-codec",
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301387 codec_root);
1388 if (!msm_sdw->entry) {
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301389 dev_err(codec->dev, "%s: failed to create msm_sdw entry\n",
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301390 __func__);
1391 return -ENOMEM;
1392 }
1393
1394 version_entry = snd_info_create_card_entry(card->snd_card,
1395 "version",
1396 msm_sdw->entry);
1397 if (!version_entry) {
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301398 dev_err(codec->dev, "%s: failed to create msm_sdw version entry\n",
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301399 __func__);
1400 return -ENOMEM;
1401 }
1402
1403 version_entry->private_data = msm_sdw;
1404 version_entry->size = MSM_SDW_VERSION_ENTRY_SIZE;
1405 version_entry->content = SNDRV_INFO_CONTENT_DATA;
1406 version_entry->c.ops = &msm_sdw_codec_info_ops;
1407
1408 if (snd_info_register(version_entry) < 0) {
1409 snd_info_free_entry(version_entry);
1410 return -ENOMEM;
1411 }
1412 msm_sdw->version_entry = version_entry;
1413
1414 return 0;
1415}
1416EXPORT_SYMBOL(msm_sdw_codec_info_create_codec_entry);
1417
1418static struct snd_soc_dai_ops msm_sdw_dai_ops = {
1419 .startup = msm_sdw_startup,
1420 .shutdown = msm_sdw_shutdown,
1421 .hw_params = msm_sdw_hw_params,
1422};
1423
1424static struct snd_soc_dai_driver msm_sdw_dai[] = {
1425 {
1426 .name = "msm_sdw_i2s_rx1",
1427 .id = AIF1_SDW_PB,
1428 .playback = {
1429 .stream_name = "AIF1_SDW Playback",
1430 .rates = MSM_SDW_RATES,
1431 .formats = MSM_SDW_FORMATS,
1432 .rate_max = 192000,
1433 .rate_min = 8000,
1434 .channels_min = 1,
Laxminath Kasam93efc172017-02-23 18:23:21 +05301435 .channels_max = 4,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301436 },
1437 .ops = &msm_sdw_dai_ops,
1438 },
1439 {
1440 .name = "msm_sdw_vifeedback",
1441 .id = AIF1_SDW_VIFEED,
1442 .capture = {
1443 .stream_name = "VIfeed_SDW",
Laxminath Kasam93efc172017-02-23 18:23:21 +05301444 .rates = MSM_SDW_RATES,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301445 .formats = SNDRV_PCM_FMTBIT_S16_LE,
Laxminath Kasam93efc172017-02-23 18:23:21 +05301446 .rate_max = 48000,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301447 .rate_min = 8000,
1448 .channels_min = 2,
1449 .channels_max = 4,
1450 },
1451 .ops = &msm_sdw_dai_ops,
1452 },
1453};
1454
1455static const char * const rx_mix1_text[] = {
1456 "ZERO", "RX4", "RX5"
1457};
1458
1459static const char * const msm_sdw_ear_spkr_pa_gain_text[] = {
1460 "G_DEFAULT", "G_0_DB", "G_1_DB", "G_2_DB", "G_3_DB",
1461 "G_4_DB", "G_5_DB", "G_6_DB"
1462};
1463
1464static SOC_ENUM_SINGLE_EXT_DECL(msm_sdw_ear_spkr_pa_gain_enum,
1465 msm_sdw_ear_spkr_pa_gain_text);
1466/* RX4 MIX1 */
1467static const struct soc_enum rx4_mix1_inp1_chain_enum =
1468 SOC_ENUM_SINGLE(MSM_SDW_TOP_RX7_PATH_INPUT0_MUX,
1469 0, 3, rx_mix1_text);
1470
1471static const struct soc_enum rx4_mix1_inp2_chain_enum =
1472 SOC_ENUM_SINGLE(MSM_SDW_TOP_RX7_PATH_INPUT1_MUX,
1473 0, 3, rx_mix1_text);
1474
1475/* RX5 MIX1 */
1476static const struct soc_enum rx5_mix1_inp1_chain_enum =
1477 SOC_ENUM_SINGLE(MSM_SDW_TOP_RX8_PATH_INPUT0_MUX,
1478 0, 3, rx_mix1_text);
1479
1480static const struct soc_enum rx5_mix1_inp2_chain_enum =
1481 SOC_ENUM_SINGLE(MSM_SDW_TOP_RX8_PATH_INPUT1_MUX,
1482 0, 3, rx_mix1_text);
1483
1484static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
1485 SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
1486
1487static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
1488 SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
1489
1490static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
1491 SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
1492
1493static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
1494 SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
1495
1496static const struct snd_kcontrol_new aif1_vi_mixer[] = {
1497 SOC_SINGLE_EXT("SPKR_VI_1", SND_SOC_NOPM, MSM_SDW_TX0, 1, 0,
1498 msm_sdw_vi_feed_mixer_get, msm_sdw_vi_feed_mixer_put),
1499 SOC_SINGLE_EXT("SPKR_VI_2", SND_SOC_NOPM, MSM_SDW_TX1, 1, 0,
1500 msm_sdw_vi_feed_mixer_get, msm_sdw_vi_feed_mixer_put),
1501};
1502
1503static const struct snd_soc_dapm_widget msm_sdw_dapm_widgets[] = {
1504 SND_SOC_DAPM_AIF_IN("I2S RX4", "AIF1_SDW Playback", 0,
1505 SND_SOC_NOPM, 0, 0),
1506
1507 SND_SOC_DAPM_AIF_IN("I2S RX5", "AIF1_SDW Playback", 0,
1508 SND_SOC_NOPM, 0, 0),
1509
1510 SND_SOC_DAPM_AIF_OUT_E("AIF1_SDW VI", "VIfeed_SDW", 0, SND_SOC_NOPM,
1511 AIF1_SDW_VIFEED, 0, msm_sdw_codec_enable_vi_feedback,
1512 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1513 SND_SOC_DAPM_MIXER("AIF1_VI_SDW Mixer", SND_SOC_NOPM, AIF1_SDW_VIFEED,
1514 0, aif1_vi_mixer, ARRAY_SIZE(aif1_vi_mixer)),
1515
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301516 SND_SOC_DAPM_MUX_E("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1517 &rx4_mix1_inp1_mux, msm_sdw_enable_swr,
1518 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1519 SND_SOC_DAPM_MUX_E("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1520 &rx4_mix1_inp2_mux, msm_sdw_enable_swr,
1521 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1522 SND_SOC_DAPM_MUX_E("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
1523 &rx5_mix1_inp1_mux, msm_sdw_enable_swr,
1524 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1525 SND_SOC_DAPM_MUX_E("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
1526 &rx5_mix1_inp2_mux, msm_sdw_enable_swr,
1527 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301528 SND_SOC_DAPM_MIXER("RX4 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
1529 SND_SOC_DAPM_MIXER("RX5 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
1530
1531 SND_SOC_DAPM_MIXER_E("RX INT4 INTERP", SND_SOC_NOPM,
1532 COMP1, 0, NULL, 0, msm_sdw_codec_enable_interpolator,
1533 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1534 SND_SOC_DAPM_POST_PMD),
1535 SND_SOC_DAPM_MIXER_E("RX INT5 INTERP", SND_SOC_NOPM,
1536 COMP2, 0, NULL, 0, msm_sdw_codec_enable_interpolator,
1537 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
1538 SND_SOC_DAPM_POST_PMD),
1539
1540 SND_SOC_DAPM_MIXER_E("RX INT4 CHAIN", SND_SOC_NOPM, 0, 0,
1541 NULL, 0, msm_sdw_codec_spk_boost_event,
1542 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1543 SND_SOC_DAPM_MIXER_E("RX INT5 CHAIN", SND_SOC_NOPM, 0, 0,
1544 NULL, 0, msm_sdw_codec_spk_boost_event,
1545 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1546
1547 SND_SOC_DAPM_INPUT("VIINPUT_SDW"),
1548
1549 SND_SOC_DAPM_OUTPUT("SPK1 OUT"),
1550 SND_SOC_DAPM_OUTPUT("SPK2 OUT"),
1551
1552 SND_SOC_DAPM_SUPPLY_S("SDW_CONN", -1, MSM_SDW_TOP_I2S_CLK,
1553 0, 0, NULL, 0),
1554
1555 SND_SOC_DAPM_SUPPLY_S("INT_MCLK1", -2, SND_SOC_NOPM, 0, 0,
1556 msm_int_mclk1_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
1557 SND_SOC_DAPM_SUPPLY("SDW_RX_I2S_CLK",
1558 MSM_SDW_TOP_RX_I2S_CTL, 0, 0, NULL, 0),
1559 SND_SOC_DAPM_SUPPLY("SDW_TX_I2S_CLK",
1560 MSM_SDW_TOP_TX_I2S_CTL, 0, 0, NULL, 0),
1561};
1562
1563static const struct snd_kcontrol_new msm_sdw_snd_controls[] = {
1564 SOC_ENUM_EXT("EAR SPKR PA Gain", msm_sdw_ear_spkr_pa_gain_enum,
1565 msm_sdw_ear_spkr_pa_gain_get,
1566 msm_sdw_ear_spkr_pa_gain_put),
1567 SOC_SINGLE_SX_TLV("RX4 Digital Volume", MSM_SDW_RX7_RX_VOL_CTL,
1568 0, -84, 40, digital_gain),
1569 SOC_SINGLE_SX_TLV("RX5 Digital Volume", MSM_SDW_RX8_RX_VOL_CTL,
1570 0, -84, 40, digital_gain),
1571 SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMP1, 1, 0,
1572 msm_sdw_get_compander, msm_sdw_set_compander),
1573 SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMP2, 1, 0,
1574 msm_sdw_get_compander, msm_sdw_set_compander),
1575};
1576
1577static const struct snd_soc_dapm_route audio_map[] = {
1578
1579 {"AIF1_SDW VI", NULL, "SDW_TX_I2S_CLK"},
1580 {"SDW_TX_I2S_CLK", NULL, "INT_MCLK1"},
1581 {"SDW_TX_I2S_CLK", NULL, "SDW_CONN"},
1582
1583 /* VI Feedback */
1584 {"AIF1_VI_SDW Mixer", "SPKR_VI_1", "VIINPUT_SDW"},
1585 {"AIF1_VI_SDW Mixer", "SPKR_VI_2", "VIINPUT_SDW"},
1586 {"AIF1_SDW VI", NULL, "AIF1_VI_SDW Mixer"},
1587
1588 {"SDW_RX_I2S_CLK", NULL, "INT_MCLK1"},
1589 {"SDW_RX_I2S_CLK", NULL, "SDW_CONN"},
1590 {"I2S RX4", NULL, "SDW_RX_I2S_CLK"},
1591 {"I2S RX5", NULL, "SDW_RX_I2S_CLK"},
1592
1593 {"RX4 MIX1 INP1", "RX4", "I2S RX4"},
1594 {"RX4 MIX1 INP1", "RX5", "I2S RX5"},
1595 {"RX4 MIX1 INP2", "RX4", "I2S RX4"},
1596 {"RX4 MIX1 INP2", "RX5", "I2S RX5"},
1597 {"RX5 MIX1 INP1", "RX4", "I2S RX4"},
1598 {"RX5 MIX1 INP1", "RX5", "I2S RX5"},
1599 {"RX5 MIX1 INP2", "RX4", "I2S RX4"},
1600 {"RX5 MIX1 INP2", "RX5", "I2S RX5"},
1601
1602 {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
1603 {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
1604 {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
1605 {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
1606
1607 {"RX INT4 INTERP", NULL, "RX4 MIX1"},
1608 {"RX INT4 CHAIN", NULL, "RX INT4 INTERP"},
1609 {"SPK1 OUT", NULL, "RX INT4 CHAIN"},
1610
1611 {"RX INT5 INTERP", NULL, "RX5 MIX1"},
1612 {"RX INT5 CHAIN", NULL, "RX INT5 INTERP"},
1613 {"SPK2 OUT", NULL, "RX INT5 CHAIN"},
1614};
1615
1616static const struct msm_sdw_reg_mask_val msm_sdw_reg_init[] = {
1617 {MSM_SDW_BOOST0_BOOST_CFG1, 0x3F, 0x12},
1618 {MSM_SDW_BOOST0_BOOST_CFG2, 0x1C, 0x08},
1619 {MSM_SDW_COMPANDER7_CTL7, 0x1E, 0x18},
1620 {MSM_SDW_BOOST1_BOOST_CFG1, 0x3F, 0x12},
1621 {MSM_SDW_BOOST1_BOOST_CFG2, 0x1C, 0x08},
1622 {MSM_SDW_COMPANDER8_CTL7, 0x1E, 0x18},
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301623 {MSM_SDW_BOOST0_BOOST_CTL, 0x70, 0x50},
1624 {MSM_SDW_BOOST1_BOOST_CTL, 0x70, 0x50},
1625 {MSM_SDW_RX7_RX_PATH_CFG1, 0x08, 0x08},
1626 {MSM_SDW_RX8_RX_PATH_CFG1, 0x08, 0x08},
1627 {MSM_SDW_TOP_TOP_CFG1, 0x02, 0x02},
1628 {MSM_SDW_TOP_TOP_CFG1, 0x01, 0x01},
1629 {MSM_SDW_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
1630 {MSM_SDW_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
1631 {MSM_SDW_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
1632 {MSM_SDW_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
1633 {MSM_SDW_COMPANDER7_CTL3, 0x80, 0x80},
1634 {MSM_SDW_COMPANDER8_CTL3, 0x80, 0x80},
1635 {MSM_SDW_COMPANDER7_CTL7, 0x01, 0x01},
1636 {MSM_SDW_COMPANDER8_CTL7, 0x01, 0x01},
1637 {MSM_SDW_RX7_RX_PATH_CFG0, 0x01, 0x01},
1638 {MSM_SDW_RX8_RX_PATH_CFG0, 0x01, 0x01},
1639 {MSM_SDW_RX7_RX_PATH_MIX_CFG, 0x01, 0x01},
1640 {MSM_SDW_RX8_RX_PATH_MIX_CFG, 0x01, 0x01},
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301641};
1642
1643static void msm_sdw_init_reg(struct snd_soc_codec *codec)
1644{
1645 int i;
1646
1647 for (i = 0; i < ARRAY_SIZE(msm_sdw_reg_init); i++)
1648 snd_soc_update_bits(codec,
1649 msm_sdw_reg_init[i].reg,
1650 msm_sdw_reg_init[i].mask,
1651 msm_sdw_reg_init[i].val);
1652}
1653
1654static int msm_sdw_notifier_service_cb(struct notifier_block *nb,
1655 unsigned long opcode, void *ptr)
1656{
1657 int i;
1658 struct msm_sdw_priv *msm_sdw = container_of(nb,
1659 struct msm_sdw_priv,
1660 service_nb);
Laxminath Kasam716a45b2017-02-13 19:36:27 +05301661 bool adsp_ready = false;
1662 unsigned long timeout;
Laxminath Kasambfde6162017-03-19 16:20:24 +05301663 static bool initial_boot = true;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301664
1665 pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
1666
1667 mutex_lock(&msm_sdw->codec_mutex);
1668 switch (opcode) {
1669 case AUDIO_NOTIFIER_SERVICE_DOWN:
Ramprasad Katkam34426192017-05-17 23:51:44 +05301670 if (initial_boot) {
1671 initial_boot = false;
Laxminath Kasambfde6162017-03-19 16:20:24 +05301672 break;
Ramprasad Katkam34426192017-05-17 23:51:44 +05301673 }
Laxminath Kasam5e4b0e62017-03-10 14:15:47 +05301674 msm_sdw->int_mclk1_enabled = false;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301675 msm_sdw->dev_up = false;
1676 for (i = 0; i < msm_sdw->nr; i++)
1677 swrm_wcd_notify(msm_sdw->sdw_ctrl_data[i].sdw_pdev,
1678 SWR_DEVICE_DOWN, NULL);
1679 break;
1680 case AUDIO_NOTIFIER_SERVICE_UP:
Laxminath Kasambfde6162017-03-19 16:20:24 +05301681 if (initial_boot)
1682 initial_boot = false;
Laxminath Kasam716a45b2017-02-13 19:36:27 +05301683 if (!q6core_is_adsp_ready()) {
1684 dev_dbg(msm_sdw->dev, "ADSP isn't ready\n");
1685 timeout = jiffies +
1686 msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
1687 while (!time_after(jiffies, timeout)) {
1688 if (!q6core_is_adsp_ready()) {
1689 dev_dbg(msm_sdw->dev,
1690 "ADSP isn't ready\n");
1691 } else {
1692 dev_dbg(msm_sdw->dev,
1693 "ADSP is ready\n");
1694 adsp_ready = true;
1695 goto powerup;
1696 }
1697 }
1698 } else {
1699 adsp_ready = true;
1700 dev_dbg(msm_sdw->dev, "%s: DSP is ready\n", __func__);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301701 }
Laxminath Kasam716a45b2017-02-13 19:36:27 +05301702powerup:
1703 if (adsp_ready) {
1704 msm_sdw->dev_up = true;
1705 msm_sdw_init_reg(msm_sdw->codec);
1706 regcache_mark_dirty(msm_sdw->regmap);
1707 regcache_sync(msm_sdw->regmap);
1708 msm_sdw_set_spkr_mode(msm_sdw->codec,
1709 msm_sdw->spkr_mode);
1710 }
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301711 break;
1712 default:
1713 break;
1714 }
1715 mutex_unlock(&msm_sdw->codec_mutex);
1716 return NOTIFY_OK;
1717}
1718
1719static int msm_sdw_codec_probe(struct snd_soc_codec *codec)
1720{
1721 struct msm_sdw_priv *msm_sdw;
1722 int i, ret;
1723
1724 msm_sdw = snd_soc_codec_get_drvdata(codec);
1725 if (!msm_sdw) {
1726 pr_err("%s:SDW priv data null\n", __func__);
1727 return -EINVAL;
1728 }
1729 msm_sdw->codec = codec;
1730 for (i = 0; i < COMP_MAX; i++)
1731 msm_sdw->comp_enabled[i] = 0;
1732
1733 msm_sdw->spkr_gain_offset = RX_GAIN_OFFSET_0_DB;
1734 msm_sdw_init_reg(codec);
1735 msm_sdw->version = MSM_SDW_VERSION_1_0;
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301736
Laxminath Kasam716a45b2017-02-13 19:36:27 +05301737 msm_sdw->service_nb.notifier_call = msm_sdw_notifier_service_cb;
1738 ret = audio_notifier_register("msm_sdw",
1739 AUDIO_NOTIFIER_ADSP_DOMAIN,
1740 &msm_sdw->service_nb);
1741 if (ret < 0)
1742 dev_err(msm_sdw->dev,
1743 "%s: Audio notifier register failed ret = %d\n",
1744 __func__, ret);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301745 return 0;
1746}
1747
1748static int msm_sdw_codec_remove(struct snd_soc_codec *codec)
1749{
1750 return 0;
1751}
1752
1753static struct regmap *msm_sdw_get_regmap(struct device *dev)
1754{
1755 struct msm_sdw_priv *msm_sdw = dev_get_drvdata(dev);
1756
1757 return msm_sdw->regmap;
1758}
1759
1760static struct snd_soc_codec_driver soc_codec_dev_msm_sdw = {
1761 .probe = msm_sdw_codec_probe,
1762 .remove = msm_sdw_codec_remove,
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301763 .get_regmap = msm_sdw_get_regmap,
Rohit Kumar9ba3a2b2017-06-28 14:07:19 +05301764 .component_driver = {
1765 .controls = msm_sdw_snd_controls,
1766 .num_controls = ARRAY_SIZE(msm_sdw_snd_controls),
1767 .dapm_widgets = msm_sdw_dapm_widgets,
1768 .num_dapm_widgets = ARRAY_SIZE(msm_sdw_dapm_widgets),
1769 .dapm_routes = audio_map,
1770 .num_dapm_routes = ARRAY_SIZE(audio_map),
1771 },
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301772};
1773
1774static void msm_sdw_add_child_devices(struct work_struct *work)
1775{
1776 struct msm_sdw_priv *msm_sdw;
1777 struct platform_device *pdev;
1778 struct device_node *node;
1779 struct msm_sdw_ctrl_data *sdw_ctrl_data = NULL, *temp;
1780 int ret, ctrl_num = 0;
1781 struct wcd_sdw_ctrl_platform_data *platdata;
1782 char plat_dev_name[MSM_SDW_STRING_LEN];
1783
1784 msm_sdw = container_of(work, struct msm_sdw_priv,
1785 msm_sdw_add_child_devices_work);
1786 if (!msm_sdw) {
1787 pr_err("%s: Memory for msm_sdw does not exist\n",
1788 __func__);
1789 return;
1790 }
1791 if (!msm_sdw->dev->of_node) {
1792 dev_err(msm_sdw->dev,
1793 "%s: DT node for msm_sdw does not exist\n", __func__);
1794 return;
1795 }
1796
1797 platdata = &msm_sdw->sdw_plat_data;
1798
1799 for_each_available_child_of_node(msm_sdw->dev->of_node, node) {
1800 if (!strcmp(node->name, "swr_master"))
1801 strlcpy(plat_dev_name, "msm_sdw_swr_ctrl",
1802 (MSM_SDW_STRING_LEN - 1));
1803 else if (strnstr(node->name, "msm_cdc_pinctrl",
1804 strlen("msm_cdc_pinctrl")) != NULL)
1805 strlcpy(plat_dev_name, node->name,
1806 (MSM_SDW_STRING_LEN - 1));
1807 else
1808 continue;
1809
1810 pdev = platform_device_alloc(plat_dev_name, -1);
1811 if (!pdev) {
1812 dev_err(msm_sdw->dev, "%s: pdev memory alloc failed\n",
1813 __func__);
1814 ret = -ENOMEM;
1815 goto err;
1816 }
1817 pdev->dev.parent = msm_sdw->dev;
1818 pdev->dev.of_node = node;
1819
1820 if (!strcmp(node->name, "swr_master")) {
1821 ret = platform_device_add_data(pdev, platdata,
1822 sizeof(*platdata));
1823 if (ret) {
1824 dev_err(&pdev->dev,
1825 "%s: cannot add plat data ctrl:%d\n",
1826 __func__, ctrl_num);
1827 goto fail_pdev_add;
1828 }
1829 }
1830
1831 ret = platform_device_add(pdev);
1832 if (ret) {
1833 dev_err(&pdev->dev,
1834 "%s: Cannot add platform device\n",
1835 __func__);
1836 goto fail_pdev_add;
1837 }
1838
1839 if (!strcmp(node->name, "swr_master")) {
1840 temp = krealloc(sdw_ctrl_data,
1841 (ctrl_num + 1) * sizeof(
1842 struct msm_sdw_ctrl_data),
1843 GFP_KERNEL);
1844 if (!temp) {
1845 dev_err(&pdev->dev, "out of memory\n");
1846 ret = -ENOMEM;
1847 goto err;
1848 }
1849 sdw_ctrl_data = temp;
1850 sdw_ctrl_data[ctrl_num].sdw_pdev = pdev;
1851 ctrl_num++;
1852 dev_dbg(&pdev->dev,
1853 "%s: Added soundwire ctrl device(s)\n",
1854 __func__);
1855 msm_sdw->nr = ctrl_num;
1856 msm_sdw->sdw_ctrl_data = sdw_ctrl_data;
1857 }
1858 }
1859
1860 return;
1861fail_pdev_add:
1862 platform_device_put(pdev);
1863err:
1864 return;
1865}
1866
1867static int msm_sdw_probe(struct platform_device *pdev)
1868{
1869 int ret = 0;
1870 struct msm_sdw_priv *msm_sdw;
1871 int adsp_state;
1872
1873 adsp_state = apr_get_subsys_state();
1874 if (adsp_state != APR_SUBSYS_LOADED) {
1875 dev_err(&pdev->dev, "Adsp is not loaded yet %d\n",
1876 adsp_state);
1877 return -EPROBE_DEFER;
1878 }
1879
1880 msm_sdw = devm_kzalloc(&pdev->dev, sizeof(struct msm_sdw_priv),
1881 GFP_KERNEL);
1882 if (!msm_sdw)
1883 return -ENOMEM;
1884 dev_set_drvdata(&pdev->dev, msm_sdw);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301885 msm_sdw->dev_up = true;
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301886
1887 msm_sdw->dev = &pdev->dev;
1888 INIT_WORK(&msm_sdw->msm_sdw_add_child_devices_work,
1889 msm_sdw_add_child_devices);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301890 msm_sdw->sdw_plat_data.handle = (void *) msm_sdw;
1891 msm_sdw->sdw_plat_data.read = msm_sdw_swrm_read;
1892 msm_sdw->sdw_plat_data.write = msm_sdw_swrm_write;
1893 msm_sdw->sdw_plat_data.bulk_write = msm_sdw_swrm_bulk_write;
1894 msm_sdw->sdw_plat_data.clk = msm_sdw_swrm_clock;
1895 msm_sdw->sdw_plat_data.handle_irq = msm_sdwm_handle_irq;
1896 ret = of_property_read_u32(pdev->dev.of_node, "reg",
1897 &msm_sdw->sdw_base_addr);
1898 if (ret) {
1899 dev_err(&pdev->dev, "%s: could not find %s entry in dt\n",
1900 __func__, "reg");
1901 goto err_sdw_cdc;
1902 }
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301903
1904 msm_sdw->sdw_gpio_p = of_parse_phandle(pdev->dev.of_node,
1905 "qcom,cdc-sdw-gpios", 0);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301906 msm_sdw->sdw_base = ioremap(msm_sdw->sdw_base_addr,
1907 MSM_SDW_MAX_REGISTER);
1908 msm_sdw->read_dev = __msm_sdw_reg_read;
1909 msm_sdw->write_dev = __msm_sdw_reg_write;
1910
1911 msm_sdw->regmap = msm_sdw_regmap_init(msm_sdw->dev,
1912 &msm_sdw_regmap_config);
1913 msm_sdw->sdw_irq = platform_get_irq_byname(pdev, "swr_master_irq");
1914 if (msm_sdw->sdw_irq < 0) {
1915 dev_err(msm_sdw->dev, "%s() error getting irq handle: %d\n",
1916 __func__, msm_sdw->sdw_irq);
1917 ret = -ENODEV;
1918 goto err_sdw_cdc;
1919 }
1920 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_msm_sdw,
1921 msm_sdw_dai, ARRAY_SIZE(msm_sdw_dai));
1922 if (ret) {
1923 dev_err(&pdev->dev, "%s: Codec registration failed, ret = %d\n",
1924 __func__, ret);
1925 goto err_sdw_cdc;
1926 }
1927 /* initialize the int_mclk1 */
1928 msm_sdw->sdw_cdc_core_clk.clk_set_minor_version =
1929 AFE_API_VERSION_I2S_CONFIG;
1930 msm_sdw->sdw_cdc_core_clk.clk_id =
1931 Q6AFE_LPASS_CLK_ID_INT_MCLK_1;
1932 msm_sdw->sdw_cdc_core_clk.clk_freq_in_hz =
1933 INT_MCLK1_FREQ;
1934 msm_sdw->sdw_cdc_core_clk.clk_attri =
1935 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
1936 msm_sdw->sdw_cdc_core_clk.clk_root =
1937 Q6AFE_LPASS_CLK_ROOT_DEFAULT;
1938 msm_sdw->sdw_cdc_core_clk.enable = 0;
1939
1940 /* initialize the sdw_npl_clk */
1941 msm_sdw->sdw_npl_clk.clk_set_minor_version =
1942 AFE_API_VERSION_I2S_CONFIG;
1943 msm_sdw->sdw_npl_clk.clk_id =
1944 AFE_CLOCK_SET_CLOCK_ID_SWR_NPL_CLK;
1945 msm_sdw->sdw_npl_clk.clk_freq_in_hz = SDW_NPL_FREQ;
1946 msm_sdw->sdw_npl_clk.clk_attri =
1947 Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
1948 msm_sdw->sdw_npl_clk.clk_root =
1949 Q6AFE_LPASS_CLK_ROOT_DEFAULT;
1950 msm_sdw->sdw_npl_clk.enable = 0;
1951
1952 INIT_DELAYED_WORK(&msm_sdw->disable_int_mclk1_work,
1953 msm_disable_int_mclk1);
1954 mutex_init(&msm_sdw->cdc_int_mclk1_mutex);
1955 mutex_init(&msm_sdw->sdw_npl_clk_mutex);
Laxminath Kasam9f05dfa2017-02-01 10:21:00 +05301956 mutex_init(&msm_sdw->io_lock);
1957 mutex_init(&msm_sdw->sdw_read_lock);
1958 mutex_init(&msm_sdw->sdw_write_lock);
1959 mutex_init(&msm_sdw->sdw_clk_lock);
1960 mutex_init(&msm_sdw->codec_mutex);
Laxminath Kasam2d20bc92016-11-24 17:31:45 +05301961 schedule_work(&msm_sdw->msm_sdw_add_child_devices_work);
1962
1963 dev_dbg(&pdev->dev, "%s: msm_sdw driver probe done\n", __func__);
1964 return ret;
1965
1966err_sdw_cdc:
1967 devm_kfree(&pdev->dev, msm_sdw);
1968 return ret;
1969}
1970
1971static int msm_sdw_remove(struct platform_device *pdev)
1972{
1973 struct msm_sdw_priv *msm_sdw;
1974
1975 msm_sdw = dev_get_drvdata(&pdev->dev);
1976
1977 mutex_destroy(&msm_sdw->io_lock);
1978 mutex_destroy(&msm_sdw->sdw_read_lock);
1979 mutex_destroy(&msm_sdw->sdw_write_lock);
1980 mutex_destroy(&msm_sdw->sdw_clk_lock);
1981 mutex_destroy(&msm_sdw->codec_mutex);
1982 mutex_destroy(&msm_sdw->cdc_int_mclk1_mutex);
1983 devm_kfree(&pdev->dev, msm_sdw);
1984 snd_soc_unregister_codec(&pdev->dev);
1985 return 0;
1986}
1987
1988static const struct of_device_id msm_sdw_codec_dt_match[] = {
1989 { .compatible = "qcom,msm-sdw-codec", },
1990 {}
1991};
1992
1993static struct platform_driver msm_sdw_codec_driver = {
1994 .probe = msm_sdw_probe,
1995 .remove = msm_sdw_remove,
1996 .driver = {
1997 .name = "msm_sdw_codec",
1998 .owner = THIS_MODULE,
1999 .of_match_table = msm_sdw_codec_dt_match,
2000 },
2001};
2002module_platform_driver(msm_sdw_codec_driver);
2003
2004MODULE_DESCRIPTION("MSM Soundwire Codec driver");
2005MODULE_LICENSE("GPL v2");