aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8753.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8753.c')
-rw-r--r--sound/soc/codecs/wm8753.c107
1 files changed, 104 insertions, 3 deletions
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index ffa2ffe5ec1..d4b822d2d47 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -48,6 +48,7 @@
48#include <sound/initval.h> 48#include <sound/initval.h>
49#include <sound/tlv.h> 49#include <sound/tlv.h>
50#include <asm/div64.h> 50#include <asm/div64.h>
51#include <sound/jack.h>
51 52
52#include "wm8753.h" 53#include "wm8753.h"
53 54
@@ -94,6 +95,9 @@ struct wm8753_priv {
94 unsigned int hifi_fmt; 95 unsigned int hifi_fmt;
95 96
96 int dai_func; 97 int dai_func;
98 int irq;
99 struct snd_soc_jack *headset_jack;
100 unsigned int debounce_time_hp;
97}; 101};
98 102
99#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0) 103#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
@@ -189,8 +193,12 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
189 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); 193 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
190 u16 ioctl; 194 u16 ioctl;
191 195
196 if (wm8753->dai_func == ucontrol->value.integer.value[0])
197 return 0;
198
192 if (codec->active) 199 if (codec->active)
193 return -EBUSY; 200 printk(KERN_WARNING
201 "Trying to Change the Dai Mode when codec is active\n");
194 202
195 ioctl = snd_soc_read(codec, WM8753_IOCTL); 203 ioctl = snd_soc_read(codec, WM8753_IOCTL);
196 204
@@ -904,6 +912,10 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
904 /* sample rate */ 912 /* sample rate */
905 if (params_rate(params) * 384 == wm8753->pcmclk) 913 if (params_rate(params) * 384 == wm8753->pcmclk)
906 srate |= 0x80; 914 srate |= 0x80;
915
916 /* ADC and V-DAC at same sample rate */
917 srate |= 1<<8;
918
907 snd_soc_write(codec, WM8753_SRATE1, srate); 919 snd_soc_write(codec, WM8753_SRATE1, srate);
908 920
909 snd_soc_write(codec, WM8753_PCM, voice); 921 snd_soc_write(codec, WM8753_PCM, voice);
@@ -1123,6 +1135,10 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
1123 printk(KERN_ERR "wm8753 invalid MCLK or rate\n"); 1135 printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
1124 return coeff; 1136 return coeff;
1125 } 1137 }
1138
1139 /* ADC and HiFi-DAC at same sample rate */
1140 srate &= ~(1<<8);
1141
1126 snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) | 1142 snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
1127 coeff_div[coeff].usb); 1143 coeff_div[coeff].usb);
1128 1144
@@ -1390,13 +1406,18 @@ static void wm8753_work(struct work_struct *work)
1390 1406
1391static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state) 1407static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
1392{ 1408{
1409 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1410
1393 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); 1411 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
1412 disable_irq(wm8753->irq);
1413
1394 return 0; 1414 return 0;
1395} 1415}
1396 1416
1397static int wm8753_resume(struct snd_soc_codec *codec) 1417static int wm8753_resume(struct snd_soc_codec *codec)
1398{ 1418{
1399 u16 *reg_cache = codec->reg_cache; 1419 u16 *reg_cache = codec->reg_cache;
1420 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1400 int i; 1421 int i;
1401 1422
1402 /* Sync reg_cache with the hardware */ 1423 /* Sync reg_cache with the hardware */
@@ -1413,6 +1434,8 @@ static int wm8753_resume(struct snd_soc_codec *codec)
1413 1434
1414 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1435 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1415 1436
1437 enable_irq(wm8753->irq);
1438
1416 /* charge wm8753 caps */ 1439 /* charge wm8753 caps */
1417 if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { 1440 if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) {
1418 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); 1441 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
@@ -1424,6 +1447,70 @@ static int wm8753_resume(struct snd_soc_codec *codec)
1424 return 0; 1447 return 0;
1425} 1448}
1426 1449
1450static irqreturn_t wm8753_jack_handler(int irq, void *data)
1451{
1452 struct snd_soc_codec *codec = data;
1453 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1454 unsigned int value;
1455
1456 /* GPIO4 interrupt disable */
1457 snd_soc_update_bits(codec, WM8753_INTEN, WM8753_GPIO4IEN_MASK,
1458 WM8753_GPIO4IEN_DIS);
1459
1460 /* sleep for debounce time */
1461 msleep(wm8753->debounce_time_hp);
1462
1463 /* Invert GPIO4 interrupt polarity */
1464 value = snd_soc_read(codec, WM8753_INTPOL);
1465 if (value & WM8753_GPIO4IPOL_LOW) {
1466 snd_soc_jack_report(wm8753->headset_jack, SND_JACK_HEADPHONE,
1467 SND_JACK_HEADPHONE);
1468 /* interupt when high i.e Headphone disconnected */
1469 snd_soc_update_bits(codec, WM8753_INTPOL, WM8753_GPIO4IPOL_MASK,
1470 WM8753_GPIO4IPOL_HIGH);
1471 } else {
1472 snd_soc_jack_report(wm8753->headset_jack, 0,
1473 SND_JACK_HEADPHONE);
1474 /* interupt when low i.e Headphone connected */
1475 snd_soc_update_bits(codec, WM8753_INTPOL, WM8753_GPIO4IPOL_MASK,
1476 WM8753_GPIO4IPOL_LOW);
1477 }
1478
1479 /* GPIO4 interrupt enable */
1480 snd_soc_update_bits(codec, WM8753_INTEN, WM8753_GPIO4IEN_MASK,
1481 WM8753_GPIO4IEN_EN);
1482
1483 return IRQ_HANDLED;
1484}
1485
1486int wm8753_headphone_detect(struct snd_soc_codec *codec,
1487 struct snd_soc_jack *jack, enum snd_jack_types type,
1488 unsigned int debounce_time_hp)
1489{
1490 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1491
1492 wm8753->headset_jack = jack;
1493 wm8753->debounce_time_hp = debounce_time_hp;
1494
1495 if (wm8753->irq && (type & SND_JACK_HEADPHONE)) {
1496 /* Configure GPIO2 pin to generate the interrupt */
1497 snd_soc_update_bits(codec, WM8753_GPIO2, WM8753_GP2M_MASK,
1498 WM8753_GP2M_INT);
1499 /* Active low Interrupt */
1500 snd_soc_update_bits(codec, WM8753_GPIO1, WM8753_INTCON_MASK,
1501 WM8753_INTCON_AL);
1502 /* interupt when low i.e Headphone connected */
1503 snd_soc_update_bits(codec, WM8753_INTPOL, WM8753_GPIO4IPOL_MASK,
1504 WM8753_GPIO4IPOL_LOW);
1505 /* GPIO4 interrupt enable */
1506 snd_soc_update_bits(codec, WM8753_INTEN, WM8753_GPIO4IEN_MASK,
1507 WM8753_GPIO4IEN_EN);
1508 }
1509
1510 return 0;
1511}
1512EXPORT_SYMBOL_GPL(wm8753_headphone_detect);
1513
1427static int wm8753_probe(struct snd_soc_codec *codec) 1514static int wm8753_probe(struct snd_soc_codec *codec)
1428{ 1515{
1429 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); 1516 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
@@ -1443,6 +1530,19 @@ static int wm8753_probe(struct snd_soc_codec *codec)
1443 return ret; 1530 return ret;
1444 } 1531 }
1445 1532
1533 if (wm8753->irq) {
1534 /* register an audio interrupt */
1535 ret = request_threaded_irq(wm8753->irq, NULL,
1536 wm8753_jack_handler,
1537 IRQF_TRIGGER_FALLING,
1538 "wm8753", codec);
1539
1540 if (ret) {
1541 dev_err(codec->dev, "Failed to request IRQ: %d\n", ret);
1542 return ret;
1543 }
1544 }
1545
1446 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1546 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1447 wm8753->dai_func = 0; 1547 wm8753->dai_func = 0;
1448 1548
@@ -1454,8 +1554,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
1454 /* set the update bits */ 1554 /* set the update bits */
1455 snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); 1555 snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
1456 snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); 1556 snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
1457 snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); 1557 snd_soc_update_bits(codec, WM8753_LADC, 0x0100, 0x0100);
1458 snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); 1558 snd_soc_update_bits(codec, WM8753_RADC, 0x0100, 0x0100);
1459 snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100); 1559 snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
1460 snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100); 1560 snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
1461 snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100); 1561 snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
@@ -1540,6 +1640,7 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
1540 1640
1541 i2c_set_clientdata(i2c, wm8753); 1641 i2c_set_clientdata(i2c, wm8753);
1542 wm8753->control_type = SND_SOC_I2C; 1642 wm8753->control_type = SND_SOC_I2C;
1643 wm8753->irq = i2c->irq;
1543 1644
1544 ret = snd_soc_register_codec(&i2c->dev, 1645 ret = snd_soc_register_codec(&i2c->dev,
1545 &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai)); 1646 &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));