blob: c8647fb1777d1681146845c2f68e48880c14441b [file] [log] [blame]
Kuirong Wang265f3592012-12-05 16:17:41 -08001/* Copyright (c) 2013, 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/module.h>
13#include <linux/init.h>
14#include <linux/firmware.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <linux/device.h>
18#include <linux/printk.h>
19#include <linux/ratelimit.h>
20#include <linux/debugfs.h>
21#include <linux/io.h>
22#include <linux/bitops.h>
23#include <linux/delay.h>
24#include <linux/pm_runtime.h>
25#include <linux/kernel.h>
26#include <linux/gpio.h>
27#include <linux/i2c.h>
28#include <linux/of_gpio.h>
29#include <linux/regulator/consumer.h>
30#include <linux/mfd/wcd9xxx/core.h>
31#include <linux/mfd/wcd9xxx/pdata.h>
32#include <sound/pcm.h>
33#include <sound/pcm_params.h>
34#include <sound/soc.h>
35#include <sound/soc-dapm.h>
36#include <sound/tlv.h>
37#include "msm8x10-wcd.h"
38#include "wcd9xxx-resmgr.h"
39#include "msm8x10_wcd_registers.h"
40
41#define MSM8X10_WCD_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
42 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
43#define MSM8X10_WCD_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
44
45#define NUM_DECIMATORS 2
46#define NUM_INTERPOLATORS 3
47#define BITS_PER_REG 8
48#define MSM8X10_WCD_TX_PORT_NUMBER 4
49
50#define MSM8X10_WCD_I2S_MASTER_MODE_MASK 0x08
51#define MSM8X10_DINO_CODEC_BASE_ADDR 0xFE043000
52
Kuirong Wang3a6408d2013-02-20 17:46:46 -080053#define MAX_MSM8X10_WCD_DEVICE 4
Kuirong Wang265f3592012-12-05 16:17:41 -080054#define CODEC_DT_MAX_PROP_SIZE 40
Kuirong Wang3a6408d2013-02-20 17:46:46 -080055#define MSM8X10_WCD_I2C_GSBI_SLAVE_ID "1-000d"
Kuirong Wang265f3592012-12-05 16:17:41 -080056
57enum {
58 MSM8X10_WCD_I2C_TOP_LEVEL = 0,
59 MSM8X10_WCD_I2C_ANALOG,
60 MSM8X10_WCD_I2C_DIGITAL_1,
61 MSM8X10_WCD_I2C_DIGITAL_2,
62};
63
64enum {
65 AIF1_PB = 0,
66 AIF1_CAP,
67 NUM_CODEC_DAIS,
68};
69
70enum {
71 RX_MIX1_INP_SEL_ZERO = 0,
72 RX_MIX1_INP_SEL_IIR1,
73 RX_MIX1_INP_SEL_IIR2,
74 RX_MIX1_INP_SEL_RX1,
75 RX_MIX1_INP_SEL_RX2,
76 RX_MIX1_INP_SEL_RX3,
77};
78
79static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
80static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
81static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
82static struct snd_soc_dai_driver msm8x10_wcd_i2s_dai[];
83static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
84
85/* Codec supports 2 IIR filters */
86enum {
87 IIR1 = 0,
88 IIR2,
89 IIR_MAX,
90};
Kuirong Wang3a6408d2013-02-20 17:46:46 -080091
Kuirong Wang265f3592012-12-05 16:17:41 -080092/* Codec supports 5 bands */
93enum {
94 BAND1 = 0,
95 BAND2,
96 BAND3,
97 BAND4,
98 BAND5,
99 BAND_MAX,
100};
101
102struct hpf_work {
103 struct msm8x10_wcd_priv *msm8x10_wcd;
104 u32 decimator;
105 u8 tx_hpf_cut_of_freq;
106 struct delayed_work dwork;
107};
108
109static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
110
111struct msm8x10_wcd_priv {
112 struct snd_soc_codec *codec;
113 u32 adc_count;
114 u32 rx_bias_count;
115 s32 dmic_1_2_clk_cnt;
116
117 /* resmgr module */
118 struct wcd9xxx_resmgr resmgr;
119 /* mbhc module */
120 struct wcd9xxx_mbhc mbhc;
121};
122
Kuirong Wang265f3592012-12-05 16:17:41 -0800123static unsigned short rx_digital_gain_reg[] = {
124 MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL,
125 MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL,
126 MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL,
127};
128
129static unsigned short tx_digital_gain_reg[] = {
130 MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN,
131 MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN,
132};
133
134struct msm8x10_wcd_i2c {
135 struct i2c_client *client;
136 struct i2c_msg xfer_msg[2];
137 struct mutex xfer_lock;
138 int mod_id;
139};
140
141static char *msm8x10_wcd_supplies[] = {
142 "cdc-vdd-mic-bias", "cdc-vdda-h", "cdc-vdd-1p2", "cdc-vdd-px",
143 "cdc-vdda-cp",
144};
145
146static int msm8x10_wcd_dt_parse_vreg_info(struct device *dev,
147 struct msm8x10_wcd_regulator *vreg, const char *vreg_name);
148static int msm8x10_wcd_dt_parse_micbias_info(struct device *dev,
149 struct msm8x10_wcd_micbias_setting *micbias);
150static struct msm8x10_wcd_pdata *msm8x10_wcd_populate_dt_pdata(
151 struct device *dev);
152
153struct msm8x10_wcd_i2c msm8x10_wcd_modules[MAX_MSM8X10_WCD_DEVICE];
154
155
156static int get_i2c_msm8x10_wcd_device_info(u16 reg,
157 struct msm8x10_wcd_i2c **msm8x10_wcd)
158{
159 int rtn = 0;
160 int value = ((reg & 0x0f00) >> 8) & 0x000f;
161 pr_debug("%s: reg(0x%x) value(%d)\n", __func__, reg, value);
162 switch (value) {
163 case 0:
164 case 1:
165 *msm8x10_wcd = &msm8x10_wcd_modules[value];
166 break;
167 default:
168 rtn = -EINVAL;
169 break;
170 }
171 return rtn;
172}
173
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800174static int msm8x10_wcd_abh_write_device(u16 reg, unsigned int *value, u32 bytes)
Kuirong Wang265f3592012-12-05 16:17:41 -0800175{
176 u32 temp = ((u32)(*value)) & 0x000000FF;
177 u32 offset = (((u32)(reg)) ^ 0x00000400) & 0x00000FFF;
178 iowrite32(temp, ioremap(MSM8X10_DINO_CODEC_BASE_ADDR + offset, 4));
179 return 0;
180}
181
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800182static int msm8x10_wcd_abh_read_device(u16 reg, u32 bytes, unsigned int *value)
Kuirong Wang265f3592012-12-05 16:17:41 -0800183{
184 u32 offset = (((u32)(reg)) ^ 0x00000400) & 0x00000FFF;
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800185 *value = ioread32(ioremap(MSM8X10_DINO_CODEC_BASE_ADDR +
Kuirong Wang265f3592012-12-05 16:17:41 -0800186 offset, 4));
187 return 0;
188}
189
190static int msm8x10_wcd_i2c_write_device(u16 reg, u8 *value, u32 bytes)
191{
192
193 struct i2c_msg *msg;
194 int ret;
195 u8 reg_addr = 0;
196 u8 data[bytes + 1];
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800197 struct msm8x10_wcd_i2c *msm8x10_wcd = NULL;
Kuirong Wang265f3592012-12-05 16:17:41 -0800198
199 ret = get_i2c_msm8x10_wcd_device_info(reg, &msm8x10_wcd);
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800200 if (ret) {
Kuirong Wang265f3592012-12-05 16:17:41 -0800201 pr_err("%s: Invalid register address\n", __func__);
202 return ret;
203 }
204
205 if (msm8x10_wcd == NULL || msm8x10_wcd->client == NULL) {
206 pr_err("%s: Failed to get device info\n", __func__);
207 return -ENODEV;
208 }
209 reg_addr = (u8)reg;
210 msg = &msm8x10_wcd->xfer_msg[0];
211 msg->addr = msm8x10_wcd->client->addr;
212 msg->len = bytes + 1;
213 msg->flags = 0;
214 data[0] = reg;
215 data[1] = *value;
216 msg->buf = data;
217 ret = i2c_transfer(msm8x10_wcd->client->adapter,
218 msm8x10_wcd->xfer_msg, 1);
219 /* Try again if the write fails */
220 if (ret != 1) {
221 ret = i2c_transfer(msm8x10_wcd->client->adapter,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800222 msm8x10_wcd->xfer_msg, 1);
Kuirong Wang265f3592012-12-05 16:17:41 -0800223 if (ret != 1) {
224 pr_err("failed to write the device\n");
225 return ret;
226 }
227 }
228 pr_debug("write sucess register = %x val = %x\n", reg, data[1]);
229 return 0;
230}
231
232
233int msm8x10_wcd_i2c_read_device(u32 reg, u32 bytes, u8 *dest)
234{
235 struct i2c_msg *msg;
236 int ret = 0;
237 u8 reg_addr = 0;
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800238 struct msm8x10_wcd_i2c *msm8x10_wcd = NULL;
Kuirong Wang265f3592012-12-05 16:17:41 -0800239 u8 i = 0;
240
241 ret = get_i2c_msm8x10_wcd_device_info(reg, &msm8x10_wcd);
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800242 if (ret) {
Kuirong Wang265f3592012-12-05 16:17:41 -0800243 pr_err("%s: Invalid register address\n", __func__);
244 return ret;
245 }
246
247 if (msm8x10_wcd == NULL || msm8x10_wcd->client == NULL) {
248 pr_err("%s: Failed to get device info\n", __func__);
249 return -ENODEV;
250 }
251
252 for (i = 0; i < bytes; i++) {
253 reg_addr = (u8)reg++;
254 msg = &msm8x10_wcd->xfer_msg[0];
255 msg->addr = msm8x10_wcd->client->addr;
256 msg->len = 1;
257 msg->flags = 0;
258 msg->buf = &reg_addr;
Kuirong Wang265f3592012-12-05 16:17:41 -0800259 msg = &msm8x10_wcd->xfer_msg[1];
260 msg->addr = msm8x10_wcd->client->addr;
261 msg->len = 1;
262 msg->flags = I2C_M_RD;
263 msg->buf = dest++;
264 ret = i2c_transfer(msm8x10_wcd->client->adapter,
265 msm8x10_wcd->xfer_msg, 2);
266
267 /* Try again if read fails first time */
268 if (ret != 2) {
269 ret = i2c_transfer(msm8x10_wcd->client->adapter,
270 msm8x10_wcd->xfer_msg, 2);
271 if (ret != 2) {
272 pr_err("failed to read msm8x10_wcd register\n");
273 return ret;
274 }
275 }
276 }
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800277 pr_debug("%s: Reg 0x%x = 0x%x\n", __func__, reg, *dest);
Kuirong Wang265f3592012-12-05 16:17:41 -0800278 return 0;
279}
280
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800281int msm8x10_wcd_i2c_read(unsigned short reg, int bytes, void *dest)
Kuirong Wang265f3592012-12-05 16:17:41 -0800282{
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800283 return msm8x10_wcd_i2c_read_device(reg, bytes, dest);
284}
285
286int msm8x10_wcd_i2c_write(unsigned short reg, int bytes, void *src)
287{
288 return msm8x10_wcd_i2c_write_device(reg, src, bytes);
289}
290
291static int msm8x10_wcd_reg_read(struct msm8x10_wcd *msm8x10_wcd,
292 u16 reg, unsigned int *val)
293{
Kuirong Wang265f3592012-12-05 16:17:41 -0800294 int ret = -EINVAL;
295
296 /* check if use I2C interface for Helicon or AHB for Dino */
297 mutex_lock(&msm8x10_wcd->io_lock);
298 if (MSM8X10_WCD_IS_HELICON_REG(reg))
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800299 ret = msm8x10_wcd_i2c_read(reg, 1, val);
Kuirong Wang265f3592012-12-05 16:17:41 -0800300 else if (MSM8X10_WCD_IS_DINO_REG(reg))
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800301 ret = msm8x10_wcd_abh_read_device(reg, 1, val);
Kuirong Wang265f3592012-12-05 16:17:41 -0800302 mutex_unlock(&msm8x10_wcd->io_lock);
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800303 return ret;
Kuirong Wang265f3592012-12-05 16:17:41 -0800304}
305
306
307static int msm8x10_wcd_reg_write(struct msm8x10_wcd *msm8x10_wcd, u16 reg,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800308 unsigned int val)
Kuirong Wang265f3592012-12-05 16:17:41 -0800309{
310 int ret = -EINVAL;
311
312 /* check if use I2C interface for Helicon or AHB for Dino */
313 mutex_lock(&msm8x10_wcd->io_lock);
314 if (MSM8X10_WCD_IS_HELICON_REG(reg))
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800315 ret = msm8x10_wcd_i2c_write(reg, 1, &val);
Kuirong Wang265f3592012-12-05 16:17:41 -0800316 else if (MSM8X10_WCD_IS_DINO_REG(reg))
317 ret = msm8x10_wcd_abh_write_device(reg, &val, 1);
318 mutex_unlock(&msm8x10_wcd->io_lock);
319
320 return ret;
321}
322
323static bool msm8x10_wcd_is_digital_gain_register(unsigned int reg)
324{
325 bool rtn = false;
326 switch (reg) {
327 case MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL:
328 case MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL:
329 case MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL:
330 case MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN:
331 case MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN:
332 rtn = true;
333 break;
334 default:
335 break;
336 }
337 return rtn;
338}
339
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800340static int msm8x10_wcd_volatile(struct snd_soc_codec *codec, unsigned int reg)
Kuirong Wang265f3592012-12-05 16:17:41 -0800341{
342 /*
343 * Registers lower than 0x100 are top level registers which can be
344 * written by the Taiko core driver.
345 */
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800346 dev_dbg(codec->dev, "%s: reg 0x%x\n", __func__, reg);
Kuirong Wang265f3592012-12-05 16:17:41 -0800347
348 if ((reg >= MSM8X10_WCD_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
349 return 1;
350
351 /* IIR Coeff registers are not cacheable */
352 if ((reg >= MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL) &&
353 (reg <= MSM8X10_WCD_A_CDC_IIR2_COEF_B2_CTL))
354 return 1;
355
356 /*
357 * Digital gain register is not cacheable so we have to write
358 * the setting even it is the same
359 */
360 if (msm8x10_wcd_is_digital_gain_register(reg))
361 return 1;
362
363 /* HPH status registers */
364 if (reg == MSM8X10_WCD_A_RX_HPH_L_STATUS ||
365 reg == MSM8X10_WCD_A_RX_HPH_R_STATUS)
366 return 1;
367
368 if (reg == MSM8X10_WCD_A_MBHC_INSERT_DET_STATUS)
369 return 1;
370
371 return 0;
372}
373
374static int msm8x10_wcd_readable(struct snd_soc_codec *ssc, unsigned int reg)
375{
376 return msm8x10_wcd_reg_readable[reg];
377}
378
379static int msm8x10_wcd_write(struct snd_soc_codec *codec, unsigned int reg,
380 unsigned int value)
381{
382 int ret;
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800383 dev_dbg(codec->dev, "%s: Write from reg 0x%x\n", __func__, reg);
Kuirong Wang265f3592012-12-05 16:17:41 -0800384 if (reg == SND_SOC_NOPM)
385 return 0;
386
387 BUG_ON(reg > MSM8X10_WCD_MAX_REGISTER);
388
389 if (!msm8x10_wcd_volatile(codec, reg)) {
390 ret = snd_soc_cache_write(codec, reg, value);
391 if (ret != 0)
392 dev_err(codec->dev, "Cache write to %x failed: %d\n",
393 reg, ret);
394 }
395
396 return msm8x10_wcd_reg_write(codec->control_data, reg, value);
397}
398
399static unsigned int msm8x10_wcd_read(struct snd_soc_codec *codec,
400 unsigned int reg)
401{
402 unsigned int val;
403 int ret;
404
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800405 dev_dbg(codec->dev, "%s: Read from reg 0x%x\n", __func__, reg);
Kuirong Wang265f3592012-12-05 16:17:41 -0800406 if (reg == SND_SOC_NOPM)
407 return 0;
408
409 BUG_ON(reg > MSM8X10_WCD_MAX_REGISTER);
410
411 if (!msm8x10_wcd_volatile(codec, reg) &&
412 msm8x10_wcd_readable(codec, reg) &&
413 reg < codec->driver->reg_cache_size) {
414 ret = snd_soc_cache_read(codec, reg, &val);
415 if (ret >= 0) {
416 return val;
417 } else
418 dev_err(codec->dev, "Cache read from %x failed: %d\n",
419 reg, ret);
420 }
421
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800422 ret = msm8x10_wcd_reg_read(codec->control_data, reg, &val);
Kuirong Wang265f3592012-12-05 16:17:41 -0800423 return val;
424}
425
426
427static int msm8x10_wcd_dt_parse_vreg_info(struct device *dev,
428 struct msm8x10_wcd_regulator *vreg, const char *vreg_name)
429{
430 int len, ret = 0;
431 const __be32 *prop;
432 char prop_name[CODEC_DT_MAX_PROP_SIZE];
433 struct device_node *regnode = NULL;
434 u32 prop_val;
435
436 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
437 vreg_name);
438 regnode = of_parse_phandle(dev->of_node, prop_name, 0);
439
440 if (!regnode) {
441 dev_err(dev, "Looking up %s property in node %s failed",
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800442 prop_name, dev->of_node->full_name);
Kuirong Wang265f3592012-12-05 16:17:41 -0800443 return -ENODEV;
444 }
445 vreg->name = vreg_name;
446
447 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
448 "qcom,%s-voltage", vreg_name);
449 prop = of_get_property(dev->of_node, prop_name, &len);
450
451 if (!prop || (len != (2 * sizeof(__be32)))) {
452 dev_err(dev, "%s %s property\n",
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800453 prop ? "invalid format" : "no", prop_name);
Kuirong Wang265f3592012-12-05 16:17:41 -0800454 return -ENODEV;
455 } else {
456 vreg->min_uV = be32_to_cpup(&prop[0]);
457 vreg->max_uV = be32_to_cpup(&prop[1]);
458 }
459
460 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800461 "qcom,%s-current", vreg_name);
Kuirong Wang265f3592012-12-05 16:17:41 -0800462
463 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
464 if (ret) {
465 dev_err(dev, "Looking up %s property in node %s failed",
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800466 prop_name, dev->of_node->full_name);
Kuirong Wang265f3592012-12-05 16:17:41 -0800467 return -ENODEV;
468 }
469 vreg->optimum_uA = prop_val;
470
471 dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800472 vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
Kuirong Wang265f3592012-12-05 16:17:41 -0800473 return 0;
474}
475
476static int msm8x10_wcd_dt_parse_micbias_info(struct device *dev,
477 struct msm8x10_wcd_micbias_setting *micbias)
478{
479 int ret = 0;
480 char prop_name[CODEC_DT_MAX_PROP_SIZE];
481 u32 prop_val;
482
483 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800484 "qcom,cdc-micbias-ldoh-v");
Kuirong Wang265f3592012-12-05 16:17:41 -0800485 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
486 if (ret) {
487 dev_err(dev, "Looking up %s property in node %s failed",
488 prop_name, dev->of_node->full_name);
489 return -ENODEV;
490 }
491 micbias->ldoh_v = (u8)prop_val;
492
493 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800494 "qcom,cdc-micbias-cfilt1-mv");
Kuirong Wang265f3592012-12-05 16:17:41 -0800495 ret = of_property_read_u32(dev->of_node, prop_name,
496 &micbias->cfilt1_mv);
497 if (ret) {
498 dev_err(dev, "Looking up %s property in node %s failed",
499 prop_name, dev->of_node->full_name);
500 return -ENODEV;
501 }
502
503 snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800504 "qcom,cdc-micbias1-cfilt-sel");
Kuirong Wang265f3592012-12-05 16:17:41 -0800505 ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
506 if (ret) {
507 dev_err(dev, "Looking up %s property in node %s failed",
508 prop_name, dev->of_node->full_name);
509 return -ENODEV;
510 }
511 micbias->bias1_cfilt_sel = (u8)prop_val;
512
513 /* micbias external cap */
514 micbias->bias1_cap_mode =
515 (of_property_read_bool(dev->of_node, "qcom,cdc-micbias1-ext-cap") ?
516 MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
517
518 dev_dbg(dev, "ldoh_v %u cfilt1_mv %u\n",
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800519 (u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv);
Kuirong Wang265f3592012-12-05 16:17:41 -0800520 dev_dbg(dev, "bias1_cfilt_sel %u\n", (u32)micbias->bias1_cfilt_sel);
521 dev_dbg(dev, "bias1_ext_cap %d\n", micbias->bias1_cap_mode);
522
523 return 0;
524}
525
526static struct msm8x10_wcd_pdata *msm8x10_wcd_populate_dt_pdata(
527 struct device *dev)
528{
529 struct msm8x10_wcd_pdata *pdata;
530 int ret, i;
531 char **codec_supplies;
532 u32 num_of_supplies = 0;
533
534 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
535 if (!pdata) {
536 dev_err(dev, "could not allocate memory for platform data\n");
537 return NULL;
538 }
539 if ((!strcmp(dev_name(dev), MSM8X10_WCD_I2C_GSBI_SLAVE_ID))) {
540 codec_supplies = msm8x10_wcd_supplies;
541 num_of_supplies = ARRAY_SIZE(msm8x10_wcd_supplies);
542 } else {
543 dev_err(dev, "%s unsupported device %s\n",
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800544 __func__, dev_name(dev));
Kuirong Wang265f3592012-12-05 16:17:41 -0800545 goto err;
546 }
547
548 if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
549 dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800550 __func__, num_of_supplies,
551 ARRAY_SIZE(pdata->regulator));
Kuirong Wang265f3592012-12-05 16:17:41 -0800552
553 goto err;
554 }
555
556 for (i = 0; i < num_of_supplies; i++) {
557 ret = msm8x10_wcd_dt_parse_vreg_info(dev, &pdata->regulator[i],
558 codec_supplies[i]);
559 if (ret)
560 goto err;
561 }
562
563 ret = msm8x10_wcd_dt_parse_micbias_info(dev, &pdata->micbias);
564 if (ret)
565 goto err;
566
567 pdata->reset_gpio = of_get_named_gpio(dev->of_node,
568 "qcom,cdc-reset-gpio", 0);
569 if (pdata->reset_gpio < 0) {
570 dev_err(dev, "Looking up %s property in node %s failed %d\n",
571 "qcom, cdc-reset-gpio", dev->of_node->full_name,
572 pdata->reset_gpio);
573 goto err;
574 }
575 dev_dbg(dev, "%s: reset gpio %d", __func__, pdata->reset_gpio);
576 return pdata;
577err:
578 devm_kfree(dev, pdata);
579 return NULL;
580}
581
582static int msm8x10_wcd_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
583 struct snd_kcontrol *kcontrol, int event)
584{
585 struct snd_soc_codec *codec = w->codec;
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800586 dev_dbg(codec->dev, "%s: event = %d\n", __func__, event);
Kuirong Wang265f3592012-12-05 16:17:41 -0800587
Kuirong Wang265f3592012-12-05 16:17:41 -0800588 switch (event) {
589 case SND_SOC_DAPM_POST_PMU:
590 /* Enable charge pump clock*/
591 snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_OTHR_CTL,
592 0x01, 0x01);
593 snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLSG_CTL,
594 0x08, 0x08);
595 usleep_range(200, 300);
596 snd_soc_update_bits(codec, MSM8X10_WCD_A_CP_STATIC,
597 0x10, 0x00);
598 break;
599 case SND_SOC_DAPM_PRE_PMD:
600 snd_soc_update_bits(codec,
601 MSM8X10_WCD_A_CDC_CLK_OTHR_RESET_B1_CTL,
602 0x01, 0x01);
603 usleep_range(20, 100);
604 snd_soc_update_bits(codec,
605 MSM8X10_WCD_A_CP_STATIC, 0x08, 0x08);
606 snd_soc_update_bits(codec,
607 MSM8X10_WCD_A_CP_STATIC, 0x10, 0x10);
608 snd_soc_update_bits(codec,
609 MSM8X10_WCD_A_CDC_CLSG_CTL, 0x08, 0x00);
610 snd_soc_update_bits(codec,
611 MSM8X10_WCD_A_CDC_CLK_OTHR_CTL, 0x01,
612 0x00);
613 snd_soc_update_bits(codec,
614 MSM8X10_WCD_A_CP_STATIC, 0x08, 0x00);
615 break;
616 }
617 return 0;
618}
619
620static int msm8x10_wcd_pa_gain_get(struct snd_kcontrol *kcontrol,
621 struct snd_ctl_elem_value *ucontrol)
622{
623 u8 ear_pa_gain;
624 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
625
626 ear_pa_gain = snd_soc_read(codec, MSM8X10_WCD_A_RX_EAR_GAIN);
627
628 ear_pa_gain = ear_pa_gain >> 5;
629
630 if (ear_pa_gain == 0x00) {
631 ucontrol->value.integer.value[0] = 0;
632 } else if (ear_pa_gain == 0x04) {
633 ucontrol->value.integer.value[0] = 1;
634 } else {
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800635 dev_err(codec->dev, "%s: ERROR: Unsupported Ear Gain = 0x%x\n",
636 __func__, ear_pa_gain);
Kuirong Wang265f3592012-12-05 16:17:41 -0800637 return -EINVAL;
638 }
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800639 dev_dbg(codec->dev, "%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
Kuirong Wang265f3592012-12-05 16:17:41 -0800640 return 0;
641}
642
643static int msm8x10_wcd_pa_gain_put(struct snd_kcontrol *kcontrol,
644 struct snd_ctl_elem_value *ucontrol)
645{
646 u8 ear_pa_gain;
647 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
648
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800649 dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
650 __func__, ucontrol->value.integer.value[0]);
Kuirong Wang265f3592012-12-05 16:17:41 -0800651
652 switch (ucontrol->value.integer.value[0]) {
653 case 0:
654 ear_pa_gain = 0x00;
655 break;
656 case 1:
657 ear_pa_gain = 0x80;
658 break;
659 default:
660 return -EINVAL;
661 }
662
663 snd_soc_update_bits(codec, MSM8X10_WCD_A_RX_EAR_GAIN,
664 0xE0, ear_pa_gain);
665 return 0;
666}
667
668static int msm8x10_wcd_get_iir_enable_audio_mixer(
669 struct snd_kcontrol *kcontrol,
670 struct snd_ctl_elem_value *ucontrol)
671{
672 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
673 int iir_idx = ((struct soc_multi_mixer_control *)
674 kcontrol->private_value)->reg;
675 int band_idx = ((struct soc_multi_mixer_control *)
676 kcontrol->private_value)->shift;
677
678 ucontrol->value.integer.value[0] =
679 snd_soc_read(codec,
680 (MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx)) &
681 (1 << band_idx);
682
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800683 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
Kuirong Wang265f3592012-12-05 16:17:41 -0800684 iir_idx, band_idx,
685 (uint32_t)ucontrol->value.integer.value[0]);
686 return 0;
687}
688
689static int msm8x10_wcd_put_iir_enable_audio_mixer(
690 struct snd_kcontrol *kcontrol,
691 struct snd_ctl_elem_value *ucontrol)
692{
693 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
694 int iir_idx = ((struct soc_multi_mixer_control *)
695 kcontrol->private_value)->reg;
696 int band_idx = ((struct soc_multi_mixer_control *)
697 kcontrol->private_value)->shift;
698 int value = ucontrol->value.integer.value[0];
699
700 /* Mask first 5 bits, 6-8 are reserved */
701 snd_soc_update_bits(codec, (MSM8X10_WCD_A_CDC_IIR1_CTL + 64 * iir_idx),
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800702 (1 << band_idx), (value << band_idx));
Kuirong Wang265f3592012-12-05 16:17:41 -0800703
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800704 dev_dbg(codec->dev, "%s: IIR #%d band #%d enable %d\n", __func__,
Kuirong Wang265f3592012-12-05 16:17:41 -0800705 iir_idx, band_idx, value);
706 return 0;
707}
708static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800709 int iir_idx, int band_idx,
710 int coeff_idx)
Kuirong Wang265f3592012-12-05 16:17:41 -0800711{
712 /* Address does not automatically update if reading */
713 snd_soc_write(codec,
714 (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
715 (band_idx * BAND_MAX + coeff_idx) & 0x1F);
716
717 /* Mask bits top 2 bits since they are reserved */
718 return ((snd_soc_read(codec,
719 (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx)) << 24)) &
720 0x3FFFFFFF;
721}
722
723static int msm8x10_wcd_get_iir_band_audio_mixer(
724 struct snd_kcontrol *kcontrol,
725 struct snd_ctl_elem_value *ucontrol)
726{
727 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
728 int iir_idx = ((struct soc_multi_mixer_control *)
729 kcontrol->private_value)->reg;
730 int band_idx = ((struct soc_multi_mixer_control *)
731 kcontrol->private_value)->shift;
732
733 ucontrol->value.integer.value[0] =
734 get_iir_band_coeff(codec, iir_idx, band_idx, 0);
735 ucontrol->value.integer.value[1] =
736 get_iir_band_coeff(codec, iir_idx, band_idx, 1);
737 ucontrol->value.integer.value[2] =
738 get_iir_band_coeff(codec, iir_idx, band_idx, 2);
739 ucontrol->value.integer.value[3] =
740 get_iir_band_coeff(codec, iir_idx, band_idx, 3);
741 ucontrol->value.integer.value[4] =
742 get_iir_band_coeff(codec, iir_idx, band_idx, 4);
743
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800744 dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
Kuirong Wang265f3592012-12-05 16:17:41 -0800745 "%s: IIR #%d band #%d b1 = 0x%x\n"
746 "%s: IIR #%d band #%d b2 = 0x%x\n"
747 "%s: IIR #%d band #%d a1 = 0x%x\n"
748 "%s: IIR #%d band #%d a2 = 0x%x\n",
749 __func__, iir_idx, band_idx,
750 (uint32_t)ucontrol->value.integer.value[0],
751 __func__, iir_idx, band_idx,
752 (uint32_t)ucontrol->value.integer.value[1],
753 __func__, iir_idx, band_idx,
754 (uint32_t)ucontrol->value.integer.value[2],
755 __func__, iir_idx, band_idx,
756 (uint32_t)ucontrol->value.integer.value[3],
757 __func__, iir_idx, band_idx,
758 (uint32_t)ucontrol->value.integer.value[4]);
759 return 0;
760}
761
762static void set_iir_band_coeff(struct snd_soc_codec *codec,
763 int iir_idx, int band_idx,
764 int coeff_idx, uint32_t value)
765{
766 /* Mask top 3 bits, 6-8 are reserved */
767 /* Update address manually each time */
768 snd_soc_write(codec,
769 (MSM8X10_WCD_A_CDC_IIR1_COEF_B1_CTL + 64 * iir_idx),
770 (band_idx * BAND_MAX + coeff_idx) & 0x1F);
771
772 /* Mask top 2 bits, 7-8 are reserved */
773 snd_soc_write(codec,
774 (MSM8X10_WCD_A_CDC_IIR1_COEF_B2_CTL + 64 * iir_idx),
775 (value >> 24) & 0x3F);
776
777}
778
779static int msm8x10_wcd_put_iir_band_audio_mixer(
780 struct snd_kcontrol *kcontrol,
781 struct snd_ctl_elem_value *ucontrol)
782{
783 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
784 int iir_idx = ((struct soc_multi_mixer_control *)
785 kcontrol->private_value)->reg;
786 int band_idx = ((struct soc_multi_mixer_control *)
787 kcontrol->private_value)->shift;
788
789 set_iir_band_coeff(codec, iir_idx, band_idx, 0,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800790 ucontrol->value.integer.value[0]);
Kuirong Wang265f3592012-12-05 16:17:41 -0800791 set_iir_band_coeff(codec, iir_idx, band_idx, 1,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800792 ucontrol->value.integer.value[1]);
Kuirong Wang265f3592012-12-05 16:17:41 -0800793 set_iir_band_coeff(codec, iir_idx, band_idx, 2,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800794 ucontrol->value.integer.value[2]);
Kuirong Wang265f3592012-12-05 16:17:41 -0800795 set_iir_band_coeff(codec, iir_idx, band_idx, 3,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800796 ucontrol->value.integer.value[3]);
Kuirong Wang265f3592012-12-05 16:17:41 -0800797 set_iir_band_coeff(codec, iir_idx, band_idx, 4,
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800798 ucontrol->value.integer.value[4]);
Kuirong Wang265f3592012-12-05 16:17:41 -0800799
Kuirong Wang3a6408d2013-02-20 17:46:46 -0800800 dev_dbg(codec->dev, "%s: IIR #%d band #%d b0 = 0x%x\n"
Kuirong Wang265f3592012-12-05 16:17:41 -0800801 "%s: IIR #%d band #%d b1 = 0x%x\n"
802 "%s: IIR #%d band #%d b2 = 0x%x\n"
803 "%s: IIR #%d band #%d a1 = 0x%x\n"
804 "%s: IIR #%d band #%d a2 = 0x%x\n",
805 __func__, iir_idx, band_idx,
806 get_iir_band_coeff(codec, iir_idx, band_idx, 0),
807 __func__, iir_idx, band_idx,
808 get_iir_band_coeff(codec, iir_idx, band_idx, 1),
809 __func__, iir_idx, band_idx,
810 get_iir_band_coeff(codec, iir_idx, band_idx, 2),
811 __func__, iir_idx, band_idx,
812 get_iir_band_coeff(codec, iir_idx, band_idx, 3),
813 __func__, iir_idx, band_idx,
814 get_iir_band_coeff(codec, iir_idx, band_idx, 4));
815 return 0;
816}
817
818static const char * const msm8x10_wcd_ear_pa_gain_text[] = {
819 "POS_6_DB", "POS_2_DB"};
820static const struct soc_enum msm8x10_wcd_ear_pa_gain_enum[] = {
821 SOC_ENUM_SINGLE_EXT(2, msm8x10_wcd_ear_pa_gain_text),
822};
823
824/*cut of frequency for high pass filter*/
825static const char * const cf_text[] = {
826 "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
827};
828
829static const struct soc_enum cf_dec1_enum =
830 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
831
832static const struct soc_enum cf_dec2_enum =
833 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
834
835static const struct soc_enum cf_rxmix1_enum =
836 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_RX1_B4_CTL, 0, 3, cf_text);
837
838static const struct soc_enum cf_rxmix2_enum =
839 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_RX2_B4_CTL, 0, 3, cf_text);
840
841static const struct soc_enum cf_rxmix3_enum =
842 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_RX3_B4_CTL, 0, 3, cf_text);
843
844static const struct snd_kcontrol_new msm8x10_wcd_snd_controls[] = {
845
846 SOC_ENUM_EXT("EAR PA Gain", msm8x10_wcd_ear_pa_gain_enum[0],
847 msm8x10_wcd_pa_gain_get, msm8x10_wcd_pa_gain_put),
848
849 SOC_SINGLE_TLV("LINEOUT1 Volume", MSM8X10_WCD_A_RX_LINE_1_GAIN,
850 0, 12, 1, line_gain),
851
852 SOC_SINGLE_TLV("HPHL Volume", MSM8X10_WCD_A_RX_HPH_L_GAIN,
853 0, 12, 1, line_gain),
854 SOC_SINGLE_TLV("HPHR Volume", MSM8X10_WCD_A_RX_HPH_R_GAIN,
855 0, 12, 1, line_gain),
856
857 SOC_SINGLE_S8_TLV("RX1 Digital Volume",
858 MSM8X10_WCD_A_CDC_RX1_VOL_CTL_B2_CTL,
859 -84, 40, digital_gain),
860 SOC_SINGLE_S8_TLV("RX2 Digital Volume",
861 MSM8X10_WCD_A_CDC_RX2_VOL_CTL_B2_CTL,
862 -84, 40, digital_gain),
863 SOC_SINGLE_S8_TLV("RX3 Digital Volume",
864 MSM8X10_WCD_A_CDC_RX3_VOL_CTL_B2_CTL,
865 -84, 40, digital_gain),
866
867 SOC_SINGLE_S8_TLV("DEC1 Volume",
868 MSM8X10_WCD_A_CDC_TX1_VOL_CTL_GAIN,
869 -84, 40, digital_gain),
870 SOC_SINGLE_S8_TLV("DEC2 Volume",
871 MSM8X10_WCD_A_CDC_TX2_VOL_CTL_GAIN,
872 -84, 40, digital_gain),
873
874 SOC_SINGLE_S8_TLV("IIR1 INP1 Volume",
875 MSM8X10_WCD_A_CDC_IIR1_GAIN_B1_CTL,
876 -84, 40, digital_gain),
877 SOC_SINGLE_S8_TLV("IIR1 INP2 Volume",
878 MSM8X10_WCD_A_CDC_IIR1_GAIN_B2_CTL,
879 -84, 40, digital_gain),
880 SOC_SINGLE_S8_TLV("IIR1 INP3 Volume",
881 MSM8X10_WCD_A_CDC_IIR1_GAIN_B3_CTL,
882 -84, 40, digital_gain),
883 SOC_SINGLE_S8_TLV("IIR1 INP4 Volume",
884 MSM8X10_WCD_A_CDC_IIR1_GAIN_B4_CTL,
885 -84, 40, digital_gain),
886
887 SOC_SINGLE("MICBIAS1 CAPLESS Switch",
888 MSM8X10_WCD_A_MICB_1_CTL, 4, 1, 1),
889
890 SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
891 SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
892
893 SOC_SINGLE("TX1 HPF Switch", MSM8X10_WCD_A_CDC_TX1_MUX_CTL, 3, 1, 0),
894 SOC_SINGLE("TX2 HPF Switch", MSM8X10_WCD_A_CDC_TX2_MUX_CTL, 3, 1, 0),
895
896 SOC_SINGLE("RX1 HPF Switch", MSM8X10_WCD_A_CDC_RX1_B5_CTL, 2, 1, 0),
897 SOC_SINGLE("RX2 HPF Switch", MSM8X10_WCD_A_CDC_RX2_B5_CTL, 2, 1, 0),
898 SOC_SINGLE("RX3 HPF Switch", MSM8X10_WCD_A_CDC_RX3_B5_CTL, 2, 1, 0),
899
900 SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
901 SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
902 SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
903
904 SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
905 msm8x10_wcd_get_iir_enable_audio_mixer,
906 msm8x10_wcd_put_iir_enable_audio_mixer),
907 SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
908 msm8x10_wcd_get_iir_enable_audio_mixer,
909 msm8x10_wcd_put_iir_enable_audio_mixer),
910 SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
911 msm8x10_wcd_get_iir_enable_audio_mixer,
912 msm8x10_wcd_put_iir_enable_audio_mixer),
913 SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
914 msm8x10_wcd_get_iir_enable_audio_mixer,
915 msm8x10_wcd_put_iir_enable_audio_mixer),
916 SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
917 msm8x10_wcd_get_iir_enable_audio_mixer,
918 msm8x10_wcd_put_iir_enable_audio_mixer),
919 SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
920 msm8x10_wcd_get_iir_enable_audio_mixer,
921 msm8x10_wcd_put_iir_enable_audio_mixer),
922 SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
923 msm8x10_wcd_get_iir_enable_audio_mixer,
924 msm8x10_wcd_put_iir_enable_audio_mixer),
925 SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
926 msm8x10_wcd_get_iir_enable_audio_mixer,
927 msm8x10_wcd_put_iir_enable_audio_mixer),
928 SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
929 msm8x10_wcd_get_iir_enable_audio_mixer,
930 msm8x10_wcd_put_iir_enable_audio_mixer),
931 SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
932 msm8x10_wcd_get_iir_enable_audio_mixer,
933 msm8x10_wcd_put_iir_enable_audio_mixer),
934
935 SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
936 msm8x10_wcd_get_iir_band_audio_mixer,
937 msm8x10_wcd_put_iir_band_audio_mixer),
938 SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
939 msm8x10_wcd_get_iir_band_audio_mixer,
940 msm8x10_wcd_put_iir_band_audio_mixer),
941 SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
942 msm8x10_wcd_get_iir_band_audio_mixer,
943 msm8x10_wcd_put_iir_band_audio_mixer),
944 SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
945 msm8x10_wcd_get_iir_band_audio_mixer,
946 msm8x10_wcd_put_iir_band_audio_mixer),
947 SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
948 msm8x10_wcd_get_iir_band_audio_mixer,
949 msm8x10_wcd_put_iir_band_audio_mixer),
950 SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
951 msm8x10_wcd_get_iir_band_audio_mixer,
952 msm8x10_wcd_put_iir_band_audio_mixer),
953 SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
954 msm8x10_wcd_get_iir_band_audio_mixer,
955 msm8x10_wcd_put_iir_band_audio_mixer),
956 SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
957 msm8x10_wcd_get_iir_band_audio_mixer,
958 msm8x10_wcd_put_iir_band_audio_mixer),
959 SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
960 msm8x10_wcd_get_iir_band_audio_mixer,
961 msm8x10_wcd_put_iir_band_audio_mixer),
962 SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
963 msm8x10_wcd_get_iir_band_audio_mixer,
964 msm8x10_wcd_put_iir_band_audio_mixer),
965
966};
967
968static const char * const rx_mix1_text[] = {
969 "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
970};
971
972static const char * const rx_mix2_text[] = {
973 "ZERO", "IIR1", "IIR2"
974};
975
976static const char * const dec_mux_text[] = {
977 "ZERO", "ADC1", "ADC2", "DMIC1", "DMIC2"
978};
979
Kuirong Wang265f3592012-12-05 16:17:41 -0800980static const char * const anc_mux_text[] = {
981 "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
982 "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
983};
984
985static const char * const anc1_fb_mux_text[] = {
986 "ZERO", "EAR_HPH_L", "EAR_LINE_1",
987};
988
989static const char * const iir1_inp1_text[] = {
990 "ZERO", "DEC1", "DEC2", "RX1", "RX2", "RX3"
991};
992
993static const struct soc_enum rx_mix1_inp1_chain_enum =
994 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text);
995
996static const struct soc_enum rx_mix1_inp2_chain_enum =
997 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL, 3, 6, rx_mix1_text);
998
999static const struct soc_enum rx_mix1_inp3_chain_enum =
1000 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B2_CTL, 0, 6, rx_mix1_text);
1001
1002static const struct soc_enum rx2_mix1_inp1_chain_enum =
1003 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text);
1004
1005static const struct soc_enum rx2_mix1_inp2_chain_enum =
1006 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX2_B1_CTL, 3, 6, rx_mix1_text);
1007
1008static const struct soc_enum rx3_mix1_inp1_chain_enum =
1009 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text);
1010
1011static const struct soc_enum rx3_mix1_inp2_chain_enum =
1012 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX3_B1_CTL, 3, 6, rx_mix1_text);
1013
1014static const struct soc_enum rx1_mix2_inp1_chain_enum =
1015 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B3_CTL, 0, 3, rx_mix2_text);
1016
1017static const struct soc_enum rx2_mix2_inp1_chain_enum =
1018 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX2_B3_CTL, 0, 3, rx_mix2_text);
1019
1020static const struct soc_enum dec1_mux_enum =
1021 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL, 0, 5, dec_mux_text);
1022
1023static const struct soc_enum dec2_mux_enum =
1024 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_TX_B1_CTL, 3, 5, dec_mux_text);
1025
1026static const struct soc_enum iir1_inp1_mux_enum =
1027 SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_EQ1_B1_CTL, 0, 6,
1028 iir1_inp1_text);
1029
1030static const struct snd_kcontrol_new rx_mix1_inp1_mux =
1031 SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
1032
1033static const struct snd_kcontrol_new rx_mix1_inp2_mux =
1034 SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
1035
1036static const struct snd_kcontrol_new rx_mix1_inp3_mux =
1037 SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
1038
1039static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
1040 SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
1041
1042static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
1043 SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
1044
1045static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
1046 SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
1047
1048static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
1049 SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
1050
1051static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
1052 SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
1053
1054static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
1055 SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
1056
1057static int msm8x10_wcd_put_dec_enum(struct snd_kcontrol *kcontrol,
1058 struct snd_ctl_elem_value *ucontrol)
1059{
1060 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1061 struct snd_soc_dapm_widget *w = wlist->widgets[0];
1062 struct snd_soc_codec *codec = w->codec;
1063 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1064 unsigned int dec_mux, decimator;
1065 char *dec_name = NULL;
1066 char *widget_name = NULL;
1067 char *temp;
1068 u16 tx_mux_ctl_reg;
1069 u8 adc_dmic_sel = 0x0;
1070 int ret = 0;
1071
1072 if (ucontrol->value.enumerated.item[0] > e->max - 1)
1073 return -EINVAL;
1074
1075 dec_mux = ucontrol->value.enumerated.item[0];
1076
1077 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
1078 if (!widget_name)
1079 return -ENOMEM;
1080 temp = widget_name;
1081
1082 dec_name = strsep(&widget_name, " ");
1083 widget_name = temp;
1084 if (!dec_name) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001085 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
1086 __func__, w->name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001087 ret = -EINVAL;
1088 goto out;
1089 }
1090
1091 ret = kstrtouint(strpbrk(dec_name, "12"), 10, &decimator);
1092 if (ret < 0) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001093 dev_err(codec->dev, "%s: Invalid decimator = %s\n",
1094 __func__, dec_name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001095 ret = -EINVAL;
1096 goto out;
1097 }
1098
1099 dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
1100 , __func__, w->name, decimator, dec_mux);
1101
1102 switch (decimator) {
1103 case 1:
1104 case 2:
1105 if (dec_mux == 1)
1106 adc_dmic_sel = 0x1;
1107 else
1108 adc_dmic_sel = 0x0;
1109 break;
1110 default:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001111 dev_err(codec->dev, "%s: Invalid Decimator = %u\n",
1112 __func__, decimator);
Kuirong Wang265f3592012-12-05 16:17:41 -08001113 ret = -EINVAL;
1114 goto out;
1115 }
1116
1117 tx_mux_ctl_reg = MSM8X10_WCD_A_CDC_TX1_MUX_CTL + 32 * (decimator - 1);
1118
1119 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
1120
1121 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
1122
1123out:
1124 kfree(widget_name);
1125 return ret;
1126}
1127
1128#define MSM8X10_WCD_DEC_ENUM(xname, xenum) \
1129{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1130 .info = snd_soc_info_enum_double, \
1131 .get = snd_soc_dapm_get_enum_double, \
1132 .put = msm8x10_wcd_put_dec_enum, \
1133 .private_value = (unsigned long)&xenum }
1134
1135static const struct snd_kcontrol_new dec1_mux =
1136 MSM8X10_WCD_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
1137
1138static const struct snd_kcontrol_new dec2_mux =
1139 MSM8X10_WCD_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
1140
1141static const struct snd_kcontrol_new iir1_inp1_mux =
1142 SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
1143
1144static const struct snd_kcontrol_new dac1_switch[] = {
1145 SOC_DAPM_SINGLE("Switch", MSM8X10_WCD_A_RX_EAR_EN, 5, 1, 0)
1146};
1147static const struct snd_kcontrol_new hphl_switch[] = {
1148 SOC_DAPM_SINGLE("Switch", MSM8X10_WCD_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
1149};
1150
1151/* virtual port entries */
1152static int slim_tx_mixer_get(struct snd_kcontrol *kcontrol,
1153 struct snd_ctl_elem_value *ucontrol)
1154{
1155 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1156 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1157
1158 ucontrol->value.integer.value[0] = widget->value;
1159 return 0;
1160}
1161
1162static int slim_tx_mixer_put(struct snd_kcontrol *kcontrol,
1163 struct snd_ctl_elem_value *ucontrol)
1164{
1165 return 0;
1166}
1167
1168static int slim_rx_mux_get(struct snd_kcontrol *kcontrol,
1169 struct snd_ctl_elem_value *ucontrol)
1170{
1171 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
1172 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
1173
1174 ucontrol->value.enumerated.item[0] = widget->value;
1175 return 0;
1176}
1177
1178static int slim_rx_mux_put(struct snd_kcontrol *kcontrol,
1179 struct snd_ctl_elem_value *ucontrol)
1180{
1181 return 0;
1182}
1183
1184
1185static const char *const slim_rx_mux_text[] = {
1186 "ZERO", "AIF1_PB"
1187};
1188
1189static const struct soc_enum slim_rx_mux_enum =
1190 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);
1191
1192static const struct snd_kcontrol_new slim_rx_mux[MSM8X10_WCD_RX_MAX] = {
1193 SOC_DAPM_ENUM_EXT("I2S RX1 Mux", slim_rx_mux_enum,
1194 slim_rx_mux_get, slim_rx_mux_put),
1195 SOC_DAPM_ENUM_EXT("I2S RX2 Mux", slim_rx_mux_enum,
1196 slim_rx_mux_get, slim_rx_mux_put),
1197 SOC_DAPM_ENUM_EXT("I2S RX3 Mux", slim_rx_mux_enum,
1198 slim_rx_mux_get, slim_rx_mux_put),
1199};
1200
1201static const struct snd_kcontrol_new aif_cap_mixer[] = {
1202 SOC_SINGLE_EXT("I2S TX1", SND_SOC_NOPM, MSM8X10_WCD_TX1, 1, 0,
1203 slim_tx_mixer_get, slim_tx_mixer_put),
1204 SOC_SINGLE_EXT("I2S TX2", SND_SOC_NOPM, MSM8X10_WCD_TX2, 1, 0,
1205 slim_tx_mixer_get, slim_tx_mixer_put),
1206 SOC_SINGLE_EXT("I2S TX3", SND_SOC_NOPM, MSM8X10_WCD_TX3, 1, 0,
1207 slim_tx_mixer_get, slim_tx_mixer_put),
1208 SOC_SINGLE_EXT("I2S TX4", SND_SOC_NOPM, MSM8X10_WCD_TX4, 1, 0,
1209 slim_tx_mixer_get, slim_tx_mixer_put),
1210};
1211
1212
1213static void msm8x10_wcd_codec_enable_adc_block(struct snd_soc_codec *codec,
1214 int enable)
1215{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001216 struct msm8x10_wcd_priv *wcd8x10 = snd_soc_codec_get_drvdata(codec);
Kuirong Wang265f3592012-12-05 16:17:41 -08001217
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001218 dev_dbg(codec->dev, "%s %d\n", __func__, enable);
Kuirong Wang265f3592012-12-05 16:17:41 -08001219
1220 if (enable) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001221 wcd8x10->adc_count++;
Kuirong Wang265f3592012-12-05 16:17:41 -08001222 snd_soc_update_bits(codec,
1223 MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
1224 0x20, 0x20);
1225 } else {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001226 wcd8x10->adc_count--;
1227 if (!wcd8x10->adc_count)
Kuirong Wang265f3592012-12-05 16:17:41 -08001228 snd_soc_update_bits(codec,
1229 MSM8X10_WCD_A_CDC_ANA_CLK_CTL,
1230 0x20, 0x0);
1231 }
1232}
1233
1234static int msm8x10_wcd_codec_enable_adc(struct snd_soc_dapm_widget *w,
1235 struct snd_kcontrol *kcontrol, int event)
1236{
1237 struct snd_soc_codec *codec = w->codec;
1238 u16 adc_reg;
1239 u8 init_bit_shift;
1240
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001241 dev_dbg(codec->dev, "%s %d\n", __func__, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001242 adc_reg = MSM8X10_WCD_A_TX_1_2_TEST_CTL;
1243
1244 if (w->reg == MSM8X10_WCD_A_TX_1_EN)
1245 init_bit_shift = 7;
1246 else if (adc_reg == MSM8X10_WCD_A_TX_2_EN)
1247 init_bit_shift = 6;
1248 else {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001249 dev_err(codec->dev, "%s: Error, invalid adc register\n",
1250 __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001251 return -EINVAL;
1252 }
1253
1254 switch (event) {
1255 case SND_SOC_DAPM_PRE_PMU:
1256 msm8x10_wcd_codec_enable_adc_block(codec, 1);
1257 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
1258 1 << init_bit_shift);
1259 break;
1260 case SND_SOC_DAPM_POST_PMU:
1261 snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
1262 break;
1263 case SND_SOC_DAPM_POST_PMD:
1264 msm8x10_wcd_codec_enable_adc_block(codec, 0);
1265 break;
1266 }
1267 return 0;
1268}
1269
1270static int msm8x10_wcd_codec_enable_lineout(struct snd_soc_dapm_widget *w,
1271 struct snd_kcontrol *kcontrol, int event)
1272{
1273 struct snd_soc_codec *codec = w->codec;
1274 u16 lineout_gain_reg;
1275
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001276 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001277
1278 switch (w->shift) {
1279 case 0:
1280 lineout_gain_reg = MSM8X10_WCD_A_RX_LINE_1_GAIN;
1281 break;
1282 default:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001283 dev_err(codec->dev,
1284 "%s: Error, incorrect lineout register value\n",
Kuirong Wang265f3592012-12-05 16:17:41 -08001285 __func__);
1286 return -EINVAL;
1287 }
1288
1289 switch (event) {
1290 case SND_SOC_DAPM_PRE_PMU:
1291 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
1292 break;
1293 case SND_SOC_DAPM_POST_PMU:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001294 dev_dbg(codec->dev, "%s: sleeping 16 ms after %s PA turn on\n",
1295 __func__, w->name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001296 usleep_range(16000, 16100);
1297 break;
1298 case SND_SOC_DAPM_POST_PMD:
1299 snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
1300 break;
1301 }
1302 return 0;
1303}
1304
1305static int msm8x10_wcd_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
1306 struct snd_kcontrol *kcontrol, int event)
1307{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001308 dev_dbg(w->codec->dev, "%s %d %s\n", __func__, event, w->name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001309 return 0;
1310}
1311
1312static int msm8x10_wcd_codec_enable_dmic(struct snd_soc_dapm_widget *w,
1313 struct snd_kcontrol *kcontrol, int event)
1314{
1315 struct snd_soc_codec *codec = w->codec;
1316 struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
1317 u8 dmic_clk_en;
1318 u16 dmic_clk_reg;
1319 s32 *dmic_clk_cnt;
1320 unsigned int dmic;
1321 int ret;
1322
1323 ret = kstrtouint(strpbrk(w->name, "12"), 10, &dmic);
1324 if (ret < 0) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001325 dev_err(codec->dev,
1326 "%s: Invalid DMIC line on the codec\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001327 return -EINVAL;
1328 }
1329
1330 switch (dmic) {
1331 case 1:
1332 case 2:
1333 dmic_clk_en = 0x01;
1334 dmic_clk_cnt = &(msm8x10_wcd->dmic_1_2_clk_cnt);
1335 dmic_clk_reg = MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL;
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001336 dev_dbg(codec->dev,
1337 "%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
Kuirong Wang265f3592012-12-05 16:17:41 -08001338 __func__, event, dmic, *dmic_clk_cnt);
1339 break;
1340 default:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001341 dev_err(codec->dev, "%s: Invalid DMIC Selection\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001342 return -EINVAL;
1343 }
1344
1345 switch (event) {
1346 case SND_SOC_DAPM_PRE_PMU:
1347
1348 (*dmic_clk_cnt)++;
1349 if (*dmic_clk_cnt == 1)
1350 snd_soc_update_bits(codec, dmic_clk_reg,
1351 dmic_clk_en, dmic_clk_en);
1352 break;
1353 case SND_SOC_DAPM_POST_PMD:
1354
1355 (*dmic_clk_cnt)--;
1356 if (*dmic_clk_cnt == 0)
1357 snd_soc_update_bits(codec, dmic_clk_reg,
1358 dmic_clk_en, 0);
1359 break;
1360 }
1361 return 0;
1362}
1363
1364static int msm8x10_wcd_codec_enable_micbias(struct snd_soc_dapm_widget *w,
1365 struct snd_kcontrol *kcontrol, int event)
1366{
1367 struct snd_soc_codec *codec = w->codec;
1368 struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
1369 u16 micb_int_reg;
1370 u8 cfilt_sel_val = 0;
1371 char *internal1_text = "Internal1";
1372 char *internal2_text = "Internal2";
1373 char *internal3_text = "Internal3";
1374 enum wcd9xxx_notify_event e_post_off, e_pre_on, e_post_on;
1375
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001376 dev_dbg(codec->dev, "%s %d\n", __func__, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001377 switch (w->reg) {
1378 case MSM8X10_WCD_A_MICB_1_CTL:
1379 micb_int_reg = MSM8X10_WCD_A_MICB_1_INT_RBIAS;
1380 cfilt_sel_val =
1381 msm8x10_wcd->resmgr.pdata->micbias.bias1_cfilt_sel;
1382 e_pre_on = WCD9XXX_EVENT_PRE_MICBIAS_1_ON;
1383 e_post_on = WCD9XXX_EVENT_POST_MICBIAS_1_ON;
1384 e_post_off = WCD9XXX_EVENT_POST_MICBIAS_1_OFF;
1385 break;
1386 default:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001387 dev_err(codec->dev,
1388 "%s: Error, invalid micbias register\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001389 return -EINVAL;
1390 }
1391
1392 switch (event) {
1393 case SND_SOC_DAPM_PRE_PMU:
1394 /* Let MBHC module know so micbias switch to be off */
1395 wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_pre_on);
1396
1397 /* Get cfilt */
1398 wcd9xxx_resmgr_cfilt_get(&msm8x10_wcd->resmgr, cfilt_sel_val);
1399
1400 if (strnstr(w->name, internal1_text, 30))
1401 snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
1402 else if (strnstr(w->name, internal2_text, 30))
1403 snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
1404 else if (strnstr(w->name, internal3_text, 30))
1405 snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
1406 break;
1407 case SND_SOC_DAPM_POST_PMU:
1408 usleep_range(20000, 20100);
1409 /* Let MBHC module know so micbias is on */
1410 wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_on);
1411 break;
1412 case SND_SOC_DAPM_POST_PMD:
1413 /* Let MBHC module know so micbias switch to be off */
1414 wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
1415
1416 if (strnstr(w->name, internal1_text, 30))
1417 snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
1418 else if (strnstr(w->name, internal2_text, 30))
1419 snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
1420 else if (strnstr(w->name, internal3_text, 30))
1421 snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
1422
1423 /* Put cfilt */
1424 wcd9xxx_resmgr_cfilt_put(&msm8x10_wcd->resmgr, cfilt_sel_val);
1425 break;
1426 }
1427
1428 return 0;
1429}
1430
1431#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
1432#define CF_MIN_3DB_4HZ 0x0
1433#define CF_MIN_3DB_75HZ 0x1
1434#define CF_MIN_3DB_150HZ 0x2
1435
1436static int msm8x10_wcd_codec_enable_dec(struct snd_soc_dapm_widget *w,
1437 struct snd_kcontrol *kcontrol, int event)
1438{
1439 struct snd_soc_codec *codec = w->codec;
1440 unsigned int decimator;
1441 char *dec_name = NULL;
1442 char *widget_name = NULL;
1443 char *temp;
1444 int ret = 0;
1445 u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
1446 u8 dec_hpf_cut_of_freq;
1447 int offset;
1448
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001449 dev_dbg(codec->dev, "%s %d\n", __func__, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001450
1451 widget_name = kstrndup(w->name, 15, GFP_KERNEL);
1452 if (!widget_name)
1453 return -ENOMEM;
1454 temp = widget_name;
1455
1456 dec_name = strsep(&widget_name, " ");
1457 widget_name = temp;
1458 if (!dec_name) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001459 dev_err(codec->dev,
1460 "%s: Invalid decimator = %s\n", __func__, w->name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001461 ret = -EINVAL;
1462 goto out;
1463 }
1464
1465 ret = kstrtouint(strpbrk(dec_name, "12"), 10, &decimator);
1466 if (ret < 0) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001467 dev_err(codec->dev,
1468 "%s: Invalid decimator = %s\n", __func__, dec_name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001469 ret = -EINVAL;
1470 goto out;
1471 }
1472
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001473 dev_dbg(codec->dev,
1474 "%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
1475 w->name, dec_name, decimator);
Kuirong Wang265f3592012-12-05 16:17:41 -08001476
1477 if (w->reg == MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
1478 dec_reset_reg = MSM8X10_WCD_A_CDC_CLK_TX_RESET_B1_CTL;
1479 offset = 0;
1480 } else {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001481 dev_err(codec->dev, "%s: Error, incorrect dec\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001482 ret = -EINVAL;
1483 goto out;
1484 }
1485
1486 tx_vol_ctl_reg = MSM8X10_WCD_A_CDC_TX1_VOL_CTL_CFG +
1487 32 * (decimator - 1);
1488 tx_mux_ctl_reg = MSM8X10_WCD_A_CDC_TX1_MUX_CTL +
1489 32 * (decimator - 1);
1490
1491 switch (event) {
1492 case SND_SOC_DAPM_PRE_PMU:
1493 /* Enableable TX digital mute */
1494 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
1495
1496 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1497 1 << w->shift);
1498 snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
1499
1500 dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
1501
1502 dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
1503
1504 tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
1505 dec_hpf_cut_of_freq;
1506
1507 if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
1508
1509 /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
1510 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
1511 CF_MIN_3DB_150HZ << 4);
1512 }
1513
1514 /* enable HPF */
1515 snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
1516 break;
1517 case SND_SOC_DAPM_POST_PMU:
1518 /* Disable TX digital mute */
1519 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
1520
1521 if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
1522 CF_MIN_3DB_150HZ) {
1523
1524 schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
1525 msecs_to_jiffies(300));
1526 }
1527 /* apply the digital gain after the decimator is enabled*/
1528 if ((w->shift) < ARRAY_SIZE(tx_digital_gain_reg))
1529 snd_soc_write(codec,
1530 tx_digital_gain_reg[w->shift + offset],
1531 snd_soc_read(codec,
1532 tx_digital_gain_reg[w->shift + offset])
1533 );
1534 break;
1535 case SND_SOC_DAPM_PRE_PMD:
1536 snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
1537 cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
1538 break;
1539 case SND_SOC_DAPM_POST_PMD:
1540 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
1541 snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
1542 (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
1543 break;
1544 }
1545out:
1546 kfree(widget_name);
1547 return ret;
1548}
1549
1550static int msm8x10_wcd_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001551 struct snd_kcontrol *kcontrol,
1552 int event)
Kuirong Wang265f3592012-12-05 16:17:41 -08001553{
1554 struct snd_soc_codec *codec = w->codec;
1555
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001556 dev_dbg(codec->dev, "%s %d %s\n", __func__, event, w->name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001557
1558 switch (event) {
1559 case SND_SOC_DAPM_PRE_PMU:
1560 snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL,
1561 1 << w->shift, 1 << w->shift);
1562 snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_CLK_RX_RESET_CTL,
1563 1 << w->shift, 0x0);
1564 break;
1565 case SND_SOC_DAPM_POST_PMU:
1566 /* apply the digital gain after the interpolator is enabled*/
1567 if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
1568 snd_soc_write(codec,
1569 rx_digital_gain_reg[w->shift],
1570 snd_soc_read(codec,
1571 rx_digital_gain_reg[w->shift])
1572 );
1573 break;
1574 }
1575 return 0;
1576}
1577
1578
1579/* The register address is the same as other codec so it can use resmgr */
1580static int msm8x10_wcd_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
1581 struct snd_kcontrol *kcontrol, int event)
1582{
1583 struct snd_soc_codec *codec = w->codec;
1584 struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
1585
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001586 dev_dbg(codec->dev, "%s %d\n", __func__, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001587
1588 switch (event) {
1589 case SND_SOC_DAPM_PRE_PMU:
1590 wcd9xxx_resmgr_enable_rx_bias(&msm8x10_wcd->resmgr, 1);
1591 break;
1592 case SND_SOC_DAPM_POST_PMD:
1593 wcd9xxx_resmgr_enable_rx_bias(&msm8x10_wcd->resmgr, 0);
1594 break;
1595 }
1596 return 0;
1597}
1598
1599static int msm8x10_wcd_hphr_dac_event(struct snd_soc_dapm_widget *w,
1600 struct snd_kcontrol *kcontrol, int event)
1601{
1602 struct snd_soc_codec *codec = w->codec;
1603
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001604 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001605
1606 switch (event) {
1607 case SND_SOC_DAPM_PRE_PMU:
1608 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1609 break;
1610 case SND_SOC_DAPM_POST_PMD:
1611 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1612 break;
1613 }
1614 return 0;
1615}
1616
1617static int msm8x10_wcd_hph_pa_event(struct snd_soc_dapm_widget *w,
1618 struct snd_kcontrol *kcontrol, int event)
1619{
1620 struct snd_soc_codec *codec = w->codec;
1621 struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
1622 enum wcd9xxx_notify_event e_pre_on, e_post_off;
1623
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001624 dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001625 if (w->shift == 5) {
1626 e_pre_on = WCD9XXX_EVENT_PRE_HPHR_PA_ON;
1627 e_post_off = WCD9XXX_EVENT_POST_HPHR_PA_OFF;
1628 } else if (w->shift == 4) {
1629 e_pre_on = WCD9XXX_EVENT_PRE_HPHL_PA_ON;
1630 e_post_off = WCD9XXX_EVENT_POST_HPHL_PA_OFF;
1631 } else {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001632 dev_err(codec->dev,
1633 "%s: Invalid w->shift %d\n", __func__, w->shift);
Kuirong Wang265f3592012-12-05 16:17:41 -08001634 return -EINVAL;
1635 }
1636
1637 switch (event) {
1638 case SND_SOC_DAPM_PRE_PMU:
1639 /* Let MBHC module know PA is turning on */
1640 wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_pre_on);
1641 break;
1642
1643 case SND_SOC_DAPM_POST_PMU:
1644 usleep_range(10000, 10100);
1645 break;
1646
1647 case SND_SOC_DAPM_POST_PMD:
1648 /* Let MBHC module know PA turned off */
1649 wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
1650
1651 /*
1652 * schedule work is required because at the time HPH PA DAPM
1653 * event callback is called by DAPM framework, CODEC dapm mutex
1654 * would have been locked while snd_soc_jack_report also
1655 * attempts to acquire same lock.
1656 */
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001657 dev_dbg(codec->dev,
1658 "%s: sleep 10 ms after %s PA disable.\n", __func__,
1659 w->name);
Kuirong Wang265f3592012-12-05 16:17:41 -08001660 usleep_range(10000, 10100);
1661 break;
1662 }
1663 return 0;
1664}
1665
1666static int msm8x10_wcd_lineout_dac_event(struct snd_soc_dapm_widget *w,
1667 struct snd_kcontrol *kcontrol, int event)
1668{
1669 struct snd_soc_codec *codec = w->codec;
1670
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001671 dev_dbg(codec->dev, "%s %s %d\n", __func__, w->name, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001672
1673 switch (event) {
1674 case SND_SOC_DAPM_PRE_PMU:
1675 snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
1676 break;
1677
1678 case SND_SOC_DAPM_POST_PMD:
1679 snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
1680 break;
1681 }
1682 return 0;
1683}
1684
1685static int msm8x10_wcd_spk_dac_event(struct snd_soc_dapm_widget *w,
1686 struct snd_kcontrol *kcontrol, int event)
1687{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001688 dev_dbg(w->codec->dev, "%s %s %d\n", __func__, w->name, event);
Kuirong Wang265f3592012-12-05 16:17:41 -08001689 return 0;
1690}
1691
1692static const struct snd_soc_dapm_route audio_map[] = {
1693 {"RX_I2S_CLK", NULL, "CDC_CONN"},
1694 {"I2S RX1", NULL, "RX_I2S_CLK"},
1695 {"I2S RX2", NULL, "RX_I2S_CLK"},
1696 {"I2S RX3", NULL, "RX_I2S_CLK"},
1697
1698 {"I2S TX1", NULL, "TX_I2S_CLK"},
1699 {"I2S TX2", NULL, "TX_I2S_CLK"},
1700 {"I2S TX3", NULL, "TX_I2S_CLK"},
1701 {"I2S TX4", NULL, "TX_I2S_CLK"},
1702
1703 {"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
1704
1705 {"AIF1_CAP Mixer", "I2S TX1", "I2S TX1 MUX"},
1706 {"AIF1_CAP Mixer", "I2S TX2", "I2S TX2 MUX"},
1707 {"AIF1_CAP Mixer", "I2S TX3", "I2S TX3 MUX"},
1708 {"AIF1_CAP Mixer", "I2S TX4", "I2S TX4 MUX"},
1709
1710 {"I2S TX1 MUX", NULL, "DEC1 MUX"},
1711 {"I2S TX2 MUX", NULL, "DEC2 MUX"},
1712 {"I2S TX3 MUX", NULL, "RX1 MIX1"},
1713 {"I2S TX4 MUX", "RMIX2", "RX1 MIX2"},
1714 {"I2S TX4 MUX", "RMIX3", "RX1 MIX3"},
1715
1716 /* Earpiece (RX MIX1) */
1717 {"EAR", NULL, "EAR PA"},
1718 {"EAR PA", NULL, "DAC1"},
1719 {"DAC1", NULL, "CP"},
1720
1721 /* Headset (RX MIX1 and RX MIX2) */
1722 {"HEADPHONE", NULL, "HPHL"},
1723 {"HEADPHONE", NULL, "HPHR"},
1724
1725 {"HPHL", NULL, "HPHL DAC"},
1726
1727 {"HPHR", NULL, "HPHR DAC"},
1728 {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
1729
1730 {"HPHL DAC", NULL, "CP"},
1731
1732 {"HPHR DAC", NULL, "CP"},
1733
1734 {"DAC1", "Switch", "RX1 CHAIN"},
1735 {"HPHL DAC", "Switch", "RX1 CHAIN"},
1736 {"HPHR DAC", NULL, "RX2 CHAIN"},
1737
1738 {"LINEOUT1", NULL, "LINEOUT1 PA"},
1739 {"SPK_OUT", NULL, "SPK PA"},
1740
1741 {"LINEOUT1 PA", NULL, "CP"},
1742 {"LINEOUT1 PA", NULL, "LINEOUT1 DAC"},
1743
1744 {"LINEOUT1 DAC", "RX2 INPUT", "RX2 MIX1"},
1745 {"LINEOUT1 DAC", "RX3 INPUT", "RX3 MIX1"},
1746
1747 {"SPK PA", NULL, "SPK DAC"},
1748 {"SPK DAC", NULL, "RX7 MIX2"},
1749
1750 {"RX1 CHAIN", NULL, "RX1 MIX2"},
1751 {"RX2 CHAIN", NULL, "RX2 MIX2"},
1752
1753 {"LINEOUT1 DAC", NULL, "RX_BIAS"},
1754 {"SPK DAC", NULL, "RX_BIAS"},
1755
1756 {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
1757 {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
1758 {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
1759 {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
1760 {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
1761 {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
1762 {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
1763 {"RX1 MIX2", NULL, "RX1 MIX1"},
1764 {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
1765 {"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
1766 {"RX2 MIX2", NULL, "RX2 MIX1"},
1767 {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
1768 {"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
1769
1770 {"I2S RX1 MUX", "AIF1_PB", "AIF1 PB"},
1771 {"I2S RX2 MUX", "AIF1_PB", "AIF1 PB"},
1772 {"I2S RX3 MUX", "AIF1_PB", "AIF1 PB"},
1773
1774 {"I2S RX1", NULL, "I2S RX1 MUX"},
1775 {"I2S RX2", NULL, "I2S RX2 MUX"},
1776 {"I2S RX3", NULL, "I2S RX3 MUX"},
1777
1778 {"RX1 MIX1 INP1", "RX1", "I2S RX1"},
1779 {"RX1 MIX1 INP1", "RX2", "I2S RX2"},
1780 {"RX1 MIX1 INP1", "RX3", "I2S RX3"},
1781 {"RX1 MIX1 INP1", "IIR1", "IIR1"},
1782 {"RX1 MIX1 INP2", "RX1", "I2S RX1"},
1783 {"RX1 MIX1 INP2", "RX2", "I2S RX2"},
1784 {"RX1 MIX1 INP2", "RX3", "I2S RX3"},
1785 {"RX1 MIX1 INP2", "IIR1", "IIR1"},
1786 {"RX1 MIX1 INP3", "RX1", "I2S RX1"},
1787 {"RX1 MIX1 INP3", "RX2", "I2S RX2"},
1788 {"RX1 MIX1 INP3", "RX3", "I2S RX3"},
1789
1790 {"RX2 MIX1 INP1", "RX1", "I2S RX1"},
1791 {"RX2 MIX1 INP1", "RX2", "I2S RX2"},
1792 {"RX2 MIX1 INP1", "RX3", "I2S RX3"},
1793 {"RX2 MIX1 INP1", "IIR1", "IIR1"},
1794 {"RX2 MIX1 INP2", "RX1", "I2S RX1"},
1795 {"RX2 MIX1 INP2", "RX2", "I2S RX2"},
1796 {"RX2 MIX1 INP2", "RX3", "I2S RX3"},
1797 {"RX2 MIX1 INP2", "IIR1", "IIR1"},
1798
1799 {"RX3 MIX1 INP1", "RX1", "I2S RX1"},
1800 {"RX3 MIX1 INP1", "RX2", "I2S RX2"},
1801 {"RX3 MIX1 INP1", "RX3", "I2S RX3"},
1802 {"RX3 MIX1 INP1", "IIR1", "IIR1"},
1803 {"RX3 MIX1 INP2", "RX1", "I2S RX1"},
1804 {"RX3 MIX1 INP2", "RX2", "I2S RX2"},
1805 {"RX3 MIX1 INP2", "RX3", "I2S RX3"},
1806 {"RX3 MIX1 INP2", "IIR1", "IIR1"},
1807
1808 /* Decimator Inputs */
1809 {"DEC1 MUX", "DMIC1", "DMIC1"},
1810 {"DEC1 MUX", "DMIC2", "DMIC2"},
1811 {"DEC1 MUX", "ADC1", "ADC1"},
1812 {"DEC1 MUX", "ADC2", "ADC2"},
1813 {"DEC1 MUX", NULL, "CDC_CONN"},
1814
1815 {"DEC2 MUX", "DMIC1", "DMIC1"},
1816 {"DEC2 MUX", "DMIC2", "DMIC2"},
1817 {"DEC2 MUX", "ADC1", "ADC1"},
1818 {"DEC2 MUX", "ADC2", "ADC2"},
1819 {"DEC2 MUX", NULL, "CDC_CONN"},
1820
1821 /* ADC Connections */
1822 {"ADC1", NULL, "AMIC1"},
1823 {"ADC2", NULL, "AMIC2"},
1824
1825 {"IIR1", NULL, "IIR1 INP1 MUX"},
1826 {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
1827 {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
1828
1829 /* There is no LDO_H in Helicon */
1830 {"MIC BIAS1 Internal1", NULL, "LDO_H"},
1831 {"MIC BIAS1 Internal2", NULL, "LDO_H"},
1832 {"MIC BIAS1 External", NULL, "LDO_H"},
1833};
1834
Kuirong Wang265f3592012-12-05 16:17:41 -08001835static int msm8x10_wcd_startup(struct snd_pcm_substream *substream,
1836 struct snd_soc_dai *dai)
1837{
1838 struct msm8x10_wcd *msm8x10_wcd_core =
1839 dev_get_drvdata(dai->codec->dev);
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001840 dev_dbg(dai->codec->dev, "%s(): substream = %s stream = %d\n",
1841 __func__,
1842 substream->name, substream->stream);
Kuirong Wang265f3592012-12-05 16:17:41 -08001843 if ((msm8x10_wcd_core != NULL) &&
1844 (msm8x10_wcd_core->dev != NULL))
1845 pm_runtime_get_sync(msm8x10_wcd_core->dev);
1846
1847 return 0;
1848}
1849
1850static void msm8x10_wcd_shutdown(struct snd_pcm_substream *substream,
1851 struct snd_soc_dai *dai)
1852{
1853 struct msm8x10_wcd *msm8x10_wcd_core =
1854 dev_get_drvdata(dai->codec->dev);
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001855 dev_dbg(dai->codec->dev,
1856 "%s(): substream = %s stream = %d\n" , __func__,
1857 substream->name, substream->stream);
Kuirong Wang265f3592012-12-05 16:17:41 -08001858 if ((msm8x10_wcd_core != NULL) &&
1859 (msm8x10_wcd_core->dev != NULL)) {
1860 pm_runtime_mark_last_busy(msm8x10_wcd_core->dev);
1861 pm_runtime_put(msm8x10_wcd_core->dev);
1862 }
1863}
1864
1865int msm8x10_wcd_mclk_enable(struct snd_soc_codec *codec,
1866 int mclk_enable, bool dapm)
1867{
1868 struct msm8x10_wcd_priv *msm8x10_wcd = snd_soc_codec_get_drvdata(codec);
1869
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001870 dev_dbg(codec->dev,
1871 "%s: mclk_enable = %u, dapm = %d\n", __func__,
1872 mclk_enable, dapm);
Kuirong Wang265f3592012-12-05 16:17:41 -08001873 WCD9XXX_BCL_LOCK(&msm8x10_wcd->resmgr);
1874 if (mclk_enable) {
1875 wcd9xxx_resmgr_get_bandgap(&msm8x10_wcd->resmgr,
1876 WCD9XXX_BANDGAP_AUDIO_MODE);
1877 wcd9xxx_resmgr_get_clk_block(&msm8x10_wcd->resmgr,
1878 WCD9XXX_CLK_MCLK);
1879 } else {
1880 /* Put clock and BG */
1881 wcd9xxx_resmgr_put_clk_block(&msm8x10_wcd->resmgr,
1882 WCD9XXX_CLK_MCLK);
1883 wcd9xxx_resmgr_put_bandgap(&msm8x10_wcd->resmgr,
1884 WCD9XXX_BANDGAP_AUDIO_MODE);
1885 }
1886 WCD9XXX_BCL_UNLOCK(&msm8x10_wcd->resmgr);
1887
1888 return 0;
1889}
1890
1891static int msm8x10_wcd_set_dai_sysclk(struct snd_soc_dai *dai,
1892 int clk_id, unsigned int freq, int dir)
1893{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001894 dev_dbg(dai->codec->dev, "%s\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001895 return 0;
1896}
1897
1898static int msm8x10_wcd_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1899{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001900 dev_dbg(dai->codec->dev, "%s\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001901 return 0;
1902}
1903
1904static int msm8x10_wcd_set_channel_map(struct snd_soc_dai *dai,
1905 unsigned int tx_num, unsigned int *tx_slot,
1906 unsigned int rx_num, unsigned int *rx_slot)
1907
1908{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001909 dev_dbg(dai->codec->dev, "%s\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001910 return 0;
1911}
1912
1913static int msm8x10_wcd_get_channel_map(struct snd_soc_dai *dai,
1914 unsigned int *tx_num, unsigned int *tx_slot,
1915 unsigned int *rx_num, unsigned int *rx_slot)
1916
1917{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001918 dev_dbg(dai->codec->dev, "%s\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08001919 return 0;
1920}
1921
1922static int msm8x10_wcd_set_interpolator_rate(struct snd_soc_dai *dai,
1923 u8 rx_fs_rate_reg_val, u32 sample_rate)
1924{
1925 return 0;
1926}
1927
1928static int msm8x10_wcd_set_decimator_rate(struct snd_soc_dai *dai,
1929 u8 tx_fs_rate_reg_val, u32 sample_rate)
1930{
1931 return 0;
1932}
1933
1934static int msm8x10_wcd_hw_params(struct snd_pcm_substream *substream,
1935 struct snd_pcm_hw_params *params,
1936 struct snd_soc_dai *dai)
1937{
1938 u8 tx_fs_rate, rx_fs_rate;
1939 int ret;
1940
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001941 dev_dbg(dai->codec->dev,
1942 "%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
Kuirong Wang265f3592012-12-05 16:17:41 -08001943 dai->name, dai->id, params_rate(params),
1944 params_channels(params));
1945
1946 switch (params_rate(params)) {
1947 case 8000:
1948 tx_fs_rate = 0x00;
1949 rx_fs_rate = 0x00;
1950 break;
1951 case 16000:
1952 tx_fs_rate = 0x01;
1953 rx_fs_rate = 0x20;
1954 break;
1955 case 32000:
1956 tx_fs_rate = 0x02;
1957 rx_fs_rate = 0x40;
1958 break;
1959 case 48000:
1960 tx_fs_rate = 0x03;
1961 rx_fs_rate = 0x60;
1962 break;
1963 case 96000:
1964 tx_fs_rate = 0x04;
1965 rx_fs_rate = 0x80;
1966 break;
1967 case 192000:
1968 tx_fs_rate = 0x05;
1969 rx_fs_rate = 0xA0;
1970 break;
1971 default:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001972 dev_err(dai->codec->dev,
1973 "%s: Invalid sampling rate %d\n", __func__,
Kuirong Wang265f3592012-12-05 16:17:41 -08001974 params_rate(params));
1975 return -EINVAL;
1976 }
1977
1978 switch (substream->stream) {
1979 case SNDRV_PCM_STREAM_CAPTURE:
1980 ret = msm8x10_wcd_set_decimator_rate(dai, tx_fs_rate,
1981 params_rate(params));
1982 if (ret < 0) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001983 dev_err(dai->codec->dev,
1984 "%s: set decimator rate failed %d\n", __func__,
Kuirong Wang265f3592012-12-05 16:17:41 -08001985 ret);
1986 return ret;
1987 }
1988 break;
1989 case SNDRV_PCM_STREAM_PLAYBACK:
1990 ret = msm8x10_wcd_set_interpolator_rate(dai, rx_fs_rate,
1991 params_rate(params));
1992 if (ret < 0) {
Kuirong Wang3a6408d2013-02-20 17:46:46 -08001993 dev_err(dai->codec->dev,
1994 "%s: set decimator rate failed %d\n", __func__,
Kuirong Wang265f3592012-12-05 16:17:41 -08001995 ret);
1996 return ret;
1997 }
1998 break;
1999 default:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002000 dev_err(dai->codec->dev,
2001 "%s: Invalid stream type %d\n", __func__,
Kuirong Wang265f3592012-12-05 16:17:41 -08002002 substream->stream);
2003 return -EINVAL;
2004 }
2005
2006 return 0;
2007}
2008
2009static struct snd_soc_dai_ops msm8x10_wcd_dai_ops = {
2010 .startup = msm8x10_wcd_startup,
2011 .shutdown = msm8x10_wcd_shutdown,
2012 .hw_params = msm8x10_wcd_hw_params,
2013 .set_sysclk = msm8x10_wcd_set_dai_sysclk,
2014 .set_fmt = msm8x10_wcd_set_dai_fmt,
2015 .set_channel_map = msm8x10_wcd_set_channel_map,
2016 .get_channel_map = msm8x10_wcd_get_channel_map,
2017};
2018
2019static struct snd_soc_dai_driver msm8x10_wcd_i2s_dai[] = {
2020 {
2021 .name = "msm8x10_wcd_i2s_rx1",
2022 .id = AIF1_PB,
2023 .playback = {
2024 .stream_name = "AIF1 Playback",
2025 .rates = MSM8X10_WCD_RATES,
2026 .formats = MSM8X10_WCD_FORMATS,
2027 .rate_max = 192000,
2028 .rate_min = 8000,
2029 .channels_min = 1,
2030 .channels_max = 4,
2031 },
2032 .ops = &msm8x10_wcd_dai_ops,
2033 },
2034 {
2035 .name = "msm8x10_wcd_i2s_tx1",
2036 .id = AIF1_CAP,
2037 .capture = {
2038 .stream_name = "AIF1 Capture",
2039 .rates = MSM8X10_WCD_RATES,
2040 .formats = MSM8X10_WCD_FORMATS,
2041 .rate_max = 192000,
2042 .rate_min = 8000,
2043 .channels_min = 1,
2044 .channels_max = 4,
2045 },
2046 .ops = &msm8x10_wcd_dai_ops,
2047 },
2048};
2049
2050static int msm8x10_wcd_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
2051 struct snd_kcontrol *kcontrol, int event)
2052{
2053 switch (event) {
2054 case SND_SOC_DAPM_POST_PMU:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002055 dev_dbg(w->codec->dev,
2056 "%s: Sleeping 20ms after enabling EAR PA\n",
2057 __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08002058 msleep(20);
2059 break;
2060 case SND_SOC_DAPM_POST_PMD:
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002061 dev_dbg(w->codec->dev,
2062 "%s: Sleeping 20ms after disabling EAR PA\n",
2063 __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08002064 msleep(20);
2065 break;
2066 }
2067 return 0;
2068}
2069
2070static const struct snd_soc_dapm_widget msm8x10_wcd_dapm_widgets[] = {
2071 /*RX stuff */
2072 SND_SOC_DAPM_OUTPUT("EAR"),
2073
2074 SND_SOC_DAPM_PGA_E("EAR PA", MSM8X10_WCD_A_RX_EAR_EN, 4, 0, NULL, 0,
2075 msm8x10_wcd_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
2076
2077 SND_SOC_DAPM_MIXER("DAC1", MSM8X10_WCD_A_RX_EAR_EN, 6, 0, dac1_switch,
2078 ARRAY_SIZE(dac1_switch)),
2079
2080 SND_SOC_DAPM_AIF_IN("AIF1 PB", "AIF1 Playback", 0, SND_SOC_NOPM,
2081 AIF1_PB, 0),
2082
2083 SND_SOC_DAPM_MUX("I2S RX1 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX1, 0,
2084 &slim_rx_mux[MSM8X10_WCD_RX1]),
2085 SND_SOC_DAPM_MUX("I2S RX2 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX2, 0,
2086 &slim_rx_mux[MSM8X10_WCD_RX2]),
2087 SND_SOC_DAPM_MUX("I2S RX3 MUX", SND_SOC_NOPM, MSM8X10_WCD_RX3, 0,
2088 &slim_rx_mux[MSM8X10_WCD_RX3]),
2089
2090 SND_SOC_DAPM_MIXER("I2S RX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2091 SND_SOC_DAPM_MIXER("I2S RX2", SND_SOC_NOPM, 0, 0, NULL, 0),
2092 SND_SOC_DAPM_MIXER("I2S RX3", SND_SOC_NOPM, 0, 0, NULL, 0),
2093 SND_SOC_DAPM_MIXER("I2S RX4", SND_SOC_NOPM, 0, 0, NULL, 0),
2094 SND_SOC_DAPM_MIXER("I2S RX5", SND_SOC_NOPM, 0, 0, NULL, 0),
2095
2096 /* Headphone */
2097 SND_SOC_DAPM_OUTPUT("HEADPHONE"),
2098 SND_SOC_DAPM_PGA_E("HPHL", MSM8X10_WCD_A_RX_HPH_CNP_EN,
2099 5, 0, NULL, 0,
2100 msm8x10_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
2101 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2102 SND_SOC_DAPM_MIXER("HPHL DAC", MSM8X10_WCD_A_RX_HPH_L_DAC_CTL,
2103 7, 0,
2104 hphl_switch, ARRAY_SIZE(hphl_switch)),
2105
2106 SND_SOC_DAPM_PGA_E("HPHR", MSM8X10_WCD_A_RX_HPH_CNP_EN,
2107 4, 0, NULL, 0,
2108 msm8x10_wcd_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
2109 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2110
2111 SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, MSM8X10_WCD_A_RX_HPH_R_DAC_CTL,
2112 7, 0,
2113 msm8x10_wcd_hphr_dac_event,
2114 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2115
2116 /* Speaker */
2117 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
2118 SND_SOC_DAPM_OUTPUT("SPK_OUT"),
2119
2120 SND_SOC_DAPM_PGA_E("LINEOUT1 PA", MSM8X10_WCD_A_RX_LINE_CNP_EN,
2121 0, 0, NULL, 0, msm8x10_wcd_codec_enable_lineout,
2122 SND_SOC_DAPM_PRE_PMU |
2123 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2124
2125 SND_SOC_DAPM_PGA_E("SPK PA", MSM8X10_WCD_A_SPKR_DRV_EN,
2126 7, 0 , NULL, 0, msm8x10_wcd_codec_enable_spk_pa,
2127 SND_SOC_DAPM_PRE_PMU |
2128 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2129
2130 SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL,
2131 MSM8X10_WCD_A_RX_LINE_1_DAC_CTL, 7, 0,
2132 msm8x10_wcd_lineout_dac_event,
2133 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2134
2135 SND_SOC_DAPM_DAC_E("SPK DAC", NULL, SND_SOC_NOPM, 0, 0,
2136 msm8x10_wcd_spk_dac_event,
2137 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2138
2139 SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2140 SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
2141
2142 SND_SOC_DAPM_MIXER_E("RX1 MIX2",
2143 MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
2144 0, msm8x10_wcd_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
2145 SND_SOC_DAPM_POST_PMU),
2146 SND_SOC_DAPM_MIXER_E("RX2 MIX2",
2147 MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
2148 0, msm8x10_wcd_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
2149 SND_SOC_DAPM_POST_PMU),
2150 SND_SOC_DAPM_MIXER_E("RX3 MIX1",
2151 MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
2152 0, msm8x10_wcd_codec_enable_interpolator, SND_SOC_DAPM_PRE_PMU |
2153 SND_SOC_DAPM_POST_PMU),
2154
2155 SND_SOC_DAPM_MIXER("RX1 CHAIN", MSM8X10_WCD_A_CDC_RX1_B6_CTL,
2156 5, 0, NULL, 0),
2157 SND_SOC_DAPM_MIXER("RX2 CHAIN", MSM8X10_WCD_A_CDC_RX2_B6_CTL,
2158 5, 0, NULL, 0),
2159
2160 SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2161 &rx_mix1_inp1_mux),
2162 SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2163 &rx_mix1_inp2_mux),
2164 SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
2165 &rx_mix1_inp3_mux),
2166 SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2167 &rx2_mix1_inp1_mux),
2168 SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2169 &rx2_mix1_inp2_mux),
2170 SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
2171 &rx3_mix1_inp1_mux),
2172 SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
2173 &rx3_mix1_inp2_mux),
2174 SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
2175 &rx1_mix2_inp1_mux),
2176 SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
2177 &rx2_mix2_inp1_mux),
2178
2179 SND_SOC_DAPM_SUPPLY("CP", MSM8X10_WCD_A_CP_EN, 0, 0,
2180 msm8x10_wcd_codec_enable_charge_pump, SND_SOC_DAPM_PRE_PMU |
2181 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
2182
2183 SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
2184 msm8x10_wcd_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
2185 SND_SOC_DAPM_POST_PMD),
2186
2187 /* TX */
2188
2189 SND_SOC_DAPM_SUPPLY("CDC_CONN", MSM8X10_WCD_A_CDC_CLK_OTHR_CTL,
2190 2, 0, NULL, 0),
2191
2192
2193 SND_SOC_DAPM_INPUT("AMIC1"),
2194 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External",
2195 MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
2196 msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
2197 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2198 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1",
2199 MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
2200 msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
2201 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2202 SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2",
2203 MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
2204 msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
2205 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2206 SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
2207 msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2208 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2209
2210 SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_2_EN, 7, 0,
2211 msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
2212 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
2213
2214 SND_SOC_DAPM_INPUT("AMIC3"),
2215
2216 SND_SOC_DAPM_MUX_E("DEC1 MUX",
2217 MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
2218 &dec1_mux, msm8x10_wcd_codec_enable_dec,
2219 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2220 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
2221
2222 SND_SOC_DAPM_MUX_E("DEC2 MUX",
2223 MSM8X10_WCD_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
2224 &dec2_mux, msm8x10_wcd_codec_enable_dec,
2225 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
2226 SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
2227
2228 SND_SOC_DAPM_INPUT("AMIC2"),
2229 SND_SOC_DAPM_AIF_OUT("AIF1 CAP", "AIF1 Capture", 0, SND_SOC_NOPM,
2230 AIF1_CAP, 0),
2231
2232 SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
2233 aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
2234
2235 /* Digital Mic Inputs */
2236 SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
2237 msm8x10_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2238 SND_SOC_DAPM_POST_PMD),
2239
2240 SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
2241 msm8x10_wcd_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
2242 SND_SOC_DAPM_POST_PMD),
2243
2244 /* Sidetone */
2245 SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
2246 SND_SOC_DAPM_PGA("IIR1", MSM8X10_WCD_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
2247
2248 SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", MSM8X10_WCD_A_CDC_CLK_RX_I2S_CTL,
2249 4, 0, NULL, 0),
2250 SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", MSM8X10_WCD_A_CDC_CLK_TX_I2S_CTL, 4,
2251 0, NULL, 0),
2252};
2253
2254static const struct msm8x10_wcd_reg_mask_val msm8x10_wcd_reg_defaults[] = {
2255
2256 /* set MCLk to 9.6 */
2257 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CHIP_CTL, 0x0A),
2258
2259 /* EAR PA deafults */
2260 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_EAR_CMBUFF, 0x05),
2261
2262 /* RX deafults */
2263 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX1_B5_CTL, 0x78),
2264 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX2_B5_CTL, 0x78),
2265 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX3_B5_CTL, 0x78),
2266
2267 /* RX1 and RX2 defaults */
2268 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX1_B6_CTL, 0xA0),
2269 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX2_B6_CTL, 0xA0),
2270
2271 /* RX3 to RX7 defaults */
2272 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_RX3_B6_CTL, 0x80),
2273
2274 /* Reduce HPH DAC bias to 70% */
2275 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_HPH_BIAS_PA, 0x7A),
2276 /*Reduce EAR DAC bias to 70% */
2277 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_EAR_BIAS_PA, 0x76),
2278 /* Reduce LINE DAC bias to 70% */
2279 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_RX_LINE_BIAS_PA, 0x78),
2280
2281
2282 /* Disable TX7 internal biasing path which can cause leakage */
2283 MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
2284};
2285
2286static void msm8x10_wcd_update_reg_defaults(struct snd_soc_codec *codec)
2287{
2288 u32 i;
2289
2290 for (i = 0; i < ARRAY_SIZE(msm8x10_wcd_reg_defaults); i++)
2291 snd_soc_write(codec, msm8x10_wcd_reg_defaults[i].reg,
2292 msm8x10_wcd_reg_defaults[i].val);
2293}
2294
2295static const struct msm8x10_wcd_reg_mask_val
2296 msm8x10_wcd_codec_reg_init_val[] = {
2297 /* Initialize current threshold to 350MA
2298 * number of wait and run cycles to 4096
2299 */
2300 {MSM8X10_WCD_A_RX_HPH_OCP_CTL, 0xE1, 0x61},
2301 {MSM8X10_WCD_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
2302
2303 /* Initialize gain registers to use register gain */
2304 {MSM8X10_WCD_A_RX_HPH_L_GAIN, 0x20, 0x20},
2305 {MSM8X10_WCD_A_RX_HPH_R_GAIN, 0x20, 0x20},
2306 {MSM8X10_WCD_A_RX_LINE_1_GAIN, 0x20, 0x20},
2307
2308 /*enable HPF filter for TX paths */
2309 {MSM8X10_WCD_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
2310 {MSM8X10_WCD_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
2311
2312 /* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
2313 {MSM8X10_WCD_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
2314 {MSM8X10_WCD_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
2315
2316 /* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
2317 {MSM8X10_WCD_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
2318
2319};
2320
2321static void msm8x10_wcd_codec_init_reg(struct snd_soc_codec *codec)
2322{
2323 u32 i;
2324
2325 for (i = 0; i < ARRAY_SIZE(msm8x10_wcd_codec_reg_init_val); i++)
2326 snd_soc_update_bits(codec,
2327 msm8x10_wcd_codec_reg_init_val[i].reg,
2328 msm8x10_wcd_codec_reg_init_val[i].mask,
2329 msm8x10_wcd_codec_reg_init_val[i].val);
2330}
2331
2332int msm8x10_wcd_hs_detect(struct snd_soc_codec *codec,
2333 struct msm8x10_wcd_mbhc_config *mbhc_cfg)
2334{
2335 return 0;
2336}
2337EXPORT_SYMBOL_GPL(msm8x10_wcd_hs_detect);
2338
2339static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
2340{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002341 dev_dbg(codec->dev, "%s()\n", __func__);
Kuirong Wang265f3592012-12-05 16:17:41 -08002342
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002343 codec->control_data = dev_get_drvdata(codec->dev);
2344 msm8x10_wcd_codec_init_reg(codec);
Kuirong Wang265f3592012-12-05 16:17:41 -08002345 msm8x10_wcd_update_reg_defaults(codec);
2346
Kuirong Wang265f3592012-12-05 16:17:41 -08002347
2348 return 0;
2349}
2350
2351static int msm8x10_wcd_codec_remove(struct snd_soc_codec *codec)
2352{
2353 return 0;
2354}
2355
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002356static int msm8x10_wcd_device_init(struct msm8x10_wcd *msm8x10)
2357{
2358
2359 mutex_init(&msm8x10->io_lock);
2360 mutex_init(&msm8x10->xfer_lock);
2361 mutex_init(&msm8x10->pm_lock);
2362 msm8x10->wlock_holders = 0;
2363
2364 return 0;
2365}
2366
2367
Kuirong Wang265f3592012-12-05 16:17:41 -08002368static struct snd_soc_codec_driver soc_codec_dev_msm8x10_wcd = {
2369 .probe = msm8x10_wcd_codec_probe,
2370 .remove = msm8x10_wcd_codec_remove,
2371
2372 .read = msm8x10_wcd_read,
2373 .write = msm8x10_wcd_write,
2374
2375 .readable_register = msm8x10_wcd_readable,
2376 .volatile_register = msm8x10_wcd_volatile,
2377
2378 .reg_cache_size = MSM8X10_WCD_CACHE_SIZE,
2379 .reg_cache_default = msm8x10_wcd_reset_reg_defaults,
2380 .reg_word_size = 1,
2381
2382 .controls = msm8x10_wcd_snd_controls,
2383 .num_controls = ARRAY_SIZE(msm8x10_wcd_snd_controls),
2384 .dapm_widgets = msm8x10_wcd_dapm_widgets,
2385 .num_dapm_widgets = ARRAY_SIZE(msm8x10_wcd_dapm_widgets),
2386 .dapm_routes = audio_map,
2387 .num_dapm_routes = ARRAY_SIZE(audio_map),
2388};
2389
2390static int __devinit msm8x10_wcd_i2c_probe(struct i2c_client *client,
2391 const struct i2c_device_id *id)
2392{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002393 int ret = 0;
2394 struct msm8x10_wcd *msm8x10 = NULL;
Kuirong Wang265f3592012-12-05 16:17:41 -08002395 struct msm8x10_wcd_pdata *pdata;
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002396 static int device_id;
2397 struct device *dev;
2398
2399 dev_dbg(&client->dev, "%s:slave addr = 0x%x device_id = %d\n",
2400 __func__, client->addr, device_id);
2401
2402 if (device_id > 0) {
2403 msm8x10_wcd_modules[device_id++].client = client;
2404 return ret;
2405 }
2406
2407 dev = &client->dev;
Kuirong Wang265f3592012-12-05 16:17:41 -08002408 if (client->dev.of_node) {
2409 dev_dbg(&client->dev, "%s:Platform data from device tree\n",
2410 __func__);
2411 pdata = msm8x10_wcd_populate_dt_pdata(&client->dev);
2412 client->dev.platform_data = pdata;
2413 } else {
2414 dev_dbg(&client->dev, "%s:Platform data from board file\n",
2415 __func__);
2416 pdata = client->dev.platform_data;
2417 }
2418
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002419 msm8x10 = kzalloc(sizeof(struct msm8x10_wcd), GFP_KERNEL);
2420 if (msm8x10 == NULL) {
2421 dev_err(&client->dev,
2422 "%s: error, allocation failed\n", __func__);
2423 ret = -ENOMEM;
2424 goto fail;
2425 }
Kuirong Wang265f3592012-12-05 16:17:41 -08002426
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002427 msm8x10->dev = &client->dev;
2428 msm8x10_wcd_modules[device_id++].client = client;
2429 msm8x10->read_dev = msm8x10_wcd_reg_read;
2430 msm8x10->write_dev = msm8x10_wcd_reg_write;
2431 ret = msm8x10_wcd_device_init(msm8x10);
2432 if (ret) {
2433 dev_err(&client->dev,
2434 "%s:msm8x10_wcd_device_init failed with error %d\n",
2435 __func__, ret);
2436 goto fail;
2437 }
2438 dev_set_drvdata(&client->dev, msm8x10);
2439 ret = snd_soc_register_codec(&client->dev, &soc_codec_dev_msm8x10_wcd,
2440 msm8x10_wcd_i2s_dai,
2441 ARRAY_SIZE(msm8x10_wcd_i2s_dai));
2442 if (ret)
2443 dev_err(&client->dev,
2444 "%s:snd_soc_register_codec failed with error %d\n",
2445 __func__, ret);
2446fail:
Kuirong Wang265f3592012-12-05 16:17:41 -08002447 return ret;
2448}
2449
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002450static void msm8x10_wcd_device_exit(struct msm8x10_wcd *msm8x10)
2451{
2452 mutex_destroy(&msm8x10->pm_lock);
2453 mutex_destroy(&msm8x10->io_lock);
2454 mutex_destroy(&msm8x10->xfer_lock);
2455 kfree(msm8x10);
2456}
2457
Kuirong Wang265f3592012-12-05 16:17:41 -08002458static int __devexit msm8x10_wcd_i2c_remove(struct i2c_client *client)
2459{
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002460 struct msm8x10_wcd *msm8x10 = dev_get_drvdata(&client->dev);
2461
2462 msm8x10_wcd_device_exit(msm8x10);
Kuirong Wang265f3592012-12-05 16:17:41 -08002463 return 0;
2464}
2465
2466static struct i2c_device_id msm8x10_wcd_id_table[] = {
2467 {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_TOP_LEVEL},
2468 {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_ANALOG},
2469 {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_DIGITAL_1},
2470 {"msm8x10-wcd-i2c", MSM8X10_WCD_I2C_DIGITAL_2},
2471 {}
2472};
2473
2474static struct of_device_id msm8x10_wcd_of_match[] = {
2475 { .compatible = "qcom,msm8x10-wcd-i2c",},
2476 { },
2477};
2478
2479
2480static struct i2c_driver msm8x10_wcd_i2c_driver = {
2481 .driver = {
2482 .owner = THIS_MODULE,
2483 .name = "msm8x10-wcd-i2c-core",
2484 .of_match_table = msm8x10_wcd_of_match
2485 },
2486 .id_table = msm8x10_wcd_id_table,
2487 .probe = msm8x10_wcd_i2c_probe,
2488 .remove = __devexit_p(msm8x10_wcd_i2c_remove),
2489};
2490
2491static int __init msm8x10_wcd_codec_init(void)
2492{
2493 int ret;
2494
2495 pr_debug("%s:\n", __func__);
2496 ret = i2c_add_driver(&msm8x10_wcd_i2c_driver);
2497 if (ret != 0)
Kuirong Wang3a6408d2013-02-20 17:46:46 -08002498 pr_err("%s: Failed to add msm8x10 wcd I2C driver - error %d\n",
2499 __func__, ret);
Kuirong Wang265f3592012-12-05 16:17:41 -08002500 return ret;
2501}
2502
2503static void __exit msm8x10_wcd_codec_exit(void)
2504{
2505 i2c_del_driver(&msm8x10_wcd_i2c_driver);
2506}
2507
2508
2509module_init(msm8x10_wcd_codec_init);
2510module_exit(msm8x10_wcd_codec_exit);
2511
2512MODULE_DESCRIPTION("MSM8x10 Audio codec driver");
2513MODULE_LICENSE("GPL v2");
2514MODULE_DEVICE_TABLE(i2c, msm8x10_wcd_id_table);
2515