diff options
author | Takashi Iwai <tiwai@suse.de> | 2010-05-20 06:00:43 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-05-20 06:00:43 -0400 |
commit | d71f4cece4bd97d05592836202fc04ff2e7817e3 (patch) | |
tree | 6c877c7a938758b1323d9c97d46b9c536e618c69 /sound/soc/codecs/wm8903.c | |
parent | 19008bdacb9f7841166ebafe0aef361ee582ffbf (diff) | |
parent | ad8332c1302bcb4f80d593fd3eb477be9d7f5604 (diff) |
Merge branch 'topic/asoc' into for-linus
Conflicts:
sound/soc/codecs/ad1938.c
Diffstat (limited to 'sound/soc/codecs/wm8903.c')
-rw-r--r-- | sound/soc/codecs/wm8903.c | 217 |
1 files changed, 196 insertions, 21 deletions
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index fa5f99fde68b..bf08282d5ee5 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -11,26 +11,27 @@ | |||
11 | * | 11 | * |
12 | * TODO: | 12 | * TODO: |
13 | * - TDM mode configuration. | 13 | * - TDM mode configuration. |
14 | * - Mic detect. | ||
15 | * - Digital microphone support. | 14 | * - Digital microphone support. |
16 | * - Interrupt support (mic detect and sequencer). | ||
17 | */ | 15 | */ |
18 | 16 | ||
19 | #include <linux/module.h> | 17 | #include <linux/module.h> |
20 | #include <linux/moduleparam.h> | 18 | #include <linux/moduleparam.h> |
21 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/completion.h> | ||
22 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
23 | #include <linux/pm.h> | 22 | #include <linux/pm.h> |
24 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
25 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
27 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | #include <sound/jack.h> | ||
28 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
30 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
31 | #include <sound/soc.h> | 31 | #include <sound/soc.h> |
32 | #include <sound/soc-dapm.h> | 32 | #include <sound/soc-dapm.h> |
33 | #include <sound/initval.h> | 33 | #include <sound/initval.h> |
34 | #include <sound/wm8903.h> | ||
34 | 35 | ||
35 | #include "wm8903.h" | 36 | #include "wm8903.h" |
36 | 37 | ||
@@ -222,6 +223,14 @@ struct wm8903_priv { | |||
222 | int playback_active; | 223 | int playback_active; |
223 | int capture_active; | 224 | int capture_active; |
224 | 225 | ||
226 | struct completion wseq; | ||
227 | |||
228 | struct snd_soc_jack *mic_jack; | ||
229 | int mic_det; | ||
230 | int mic_short; | ||
231 | int mic_last_report; | ||
232 | int mic_delay; | ||
233 | |||
225 | struct snd_pcm_substream *master_substream; | 234 | struct snd_pcm_substream *master_substream; |
226 | struct snd_pcm_substream *slave_substream; | 235 | struct snd_pcm_substream *slave_substream; |
227 | }; | 236 | }; |
@@ -244,13 +253,14 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | |||
244 | { | 253 | { |
245 | u16 reg[5]; | 254 | u16 reg[5]; |
246 | struct i2c_client *i2c = codec->control_data; | 255 | struct i2c_client *i2c = codec->control_data; |
256 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
247 | 257 | ||
248 | BUG_ON(start > 48); | 258 | BUG_ON(start > 48); |
249 | 259 | ||
250 | /* Enable the sequencer */ | 260 | /* Enable the sequencer if it's not already on */ |
251 | reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0); | 261 | reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0); |
252 | reg[0] |= WM8903_WSEQ_ENA; | 262 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, |
253 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); | 263 | reg[0] | WM8903_WSEQ_ENA); |
254 | 264 | ||
255 | dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); | 265 | dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); |
256 | 266 | ||
@@ -258,20 +268,19 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) | |||
258 | start | WM8903_WSEQ_START); | 268 | start | WM8903_WSEQ_START); |
259 | 269 | ||
260 | /* Wait for it to complete. If we have the interrupt wired up then | 270 | /* Wait for it to complete. If we have the interrupt wired up then |
261 | * we could block waiting for an interrupt, though polling may still | 271 | * that will break us out of the poll early. |
262 | * be desirable for diagnostic purposes. | ||
263 | */ | 272 | */ |
264 | do { | 273 | do { |
265 | msleep(10); | 274 | wait_for_completion_timeout(&wm8903->wseq, |
275 | msecs_to_jiffies(10)); | ||
266 | 276 | ||
267 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); | 277 | reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); |
268 | } while (reg[4] & WM8903_WSEQ_BUSY); | 278 | } while (reg[4] & WM8903_WSEQ_BUSY); |
269 | 279 | ||
270 | dev_dbg(&i2c->dev, "Sequence complete\n"); | 280 | dev_dbg(&i2c->dev, "Sequence complete\n"); |
271 | 281 | ||
272 | /* Disable the sequencer again */ | 282 | /* Disable the sequencer again if we enabled it */ |
273 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, | 283 | snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); |
274 | reg[0] & ~WM8903_WSEQ_ENA); | ||
275 | 284 | ||
276 | return 0; | 285 | return 0; |
277 | } | 286 | } |
@@ -412,7 +421,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
412 | { | 421 | { |
413 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); | 422 | struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); |
414 | struct snd_soc_codec *codec = widget->codec; | 423 | struct snd_soc_codec *codec = widget->codec; |
415 | struct wm8903_priv *wm8903 = codec->private_data; | 424 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
416 | struct i2c_client *i2c = codec->control_data; | 425 | struct i2c_client *i2c = codec->control_data; |
417 | u16 reg; | 426 | u16 reg; |
418 | int ret; | 427 | int ret; |
@@ -993,7 +1002,7 @@ static int wm8903_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
993 | int clk_id, unsigned int freq, int dir) | 1002 | int clk_id, unsigned int freq, int dir) |
994 | { | 1003 | { |
995 | struct snd_soc_codec *codec = codec_dai->codec; | 1004 | struct snd_soc_codec *codec = codec_dai->codec; |
996 | struct wm8903_priv *wm8903 = codec->private_data; | 1005 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
997 | 1006 | ||
998 | wm8903->sysclk = freq; | 1007 | wm8903->sysclk = freq; |
999 | 1008 | ||
@@ -1221,7 +1230,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream, | |||
1221 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1230 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1222 | struct snd_soc_device *socdev = rtd->socdev; | 1231 | struct snd_soc_device *socdev = rtd->socdev; |
1223 | struct snd_soc_codec *codec = socdev->card->codec; | 1232 | struct snd_soc_codec *codec = socdev->card->codec; |
1224 | struct wm8903_priv *wm8903 = codec->private_data; | 1233 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1225 | struct i2c_client *i2c = codec->control_data; | 1234 | struct i2c_client *i2c = codec->control_data; |
1226 | struct snd_pcm_runtime *master_runtime; | 1235 | struct snd_pcm_runtime *master_runtime; |
1227 | 1236 | ||
@@ -1257,7 +1266,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream, | |||
1257 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1266 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1258 | struct snd_soc_device *socdev = rtd->socdev; | 1267 | struct snd_soc_device *socdev = rtd->socdev; |
1259 | struct snd_soc_codec *codec = socdev->card->codec; | 1268 | struct snd_soc_codec *codec = socdev->card->codec; |
1260 | struct wm8903_priv *wm8903 = codec->private_data; | 1269 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1261 | 1270 | ||
1262 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 1271 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
1263 | wm8903->playback_active--; | 1272 | wm8903->playback_active--; |
@@ -1277,7 +1286,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1286 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1278 | struct snd_soc_device *socdev = rtd->socdev; | 1287 | struct snd_soc_device *socdev = rtd->socdev; |
1279 | struct snd_soc_codec *codec = socdev->card->codec; | 1288 | struct snd_soc_codec *codec = socdev->card->codec; |
1280 | struct wm8903_priv *wm8903 = codec->private_data; | 1289 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); |
1281 | struct i2c_client *i2c = codec->control_data; | 1290 | struct i2c_client *i2c = codec->control_data; |
1282 | int fs = params_rate(params); | 1291 | int fs = params_rate(params); |
1283 | int bclk; | 1292 | int bclk; |
@@ -1436,6 +1445,116 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, | |||
1436 | return 0; | 1445 | return 0; |
1437 | } | 1446 | } |
1438 | 1447 | ||
1448 | /** | ||
1449 | * wm8903_mic_detect - Enable microphone detection via the WM8903 IRQ | ||
1450 | * | ||
1451 | * @codec: WM8903 codec | ||
1452 | * @jack: jack to report detection events on | ||
1453 | * @det: value to report for presence detection | ||
1454 | * @shrt: value to report for short detection | ||
1455 | * | ||
1456 | * Enable microphone detection via IRQ on the WM8903. If GPIOs are | ||
1457 | * being used to bring out signals to the processor then only platform | ||
1458 | * data configuration is needed for WM8903 and processor GPIOs should | ||
1459 | * be configured using snd_soc_jack_add_gpios() instead. | ||
1460 | * | ||
1461 | * The current threasholds for detection should be configured using | ||
1462 | * micdet_cfg in the platform data. Using this function will force on | ||
1463 | * the microphone bias for the device. | ||
1464 | */ | ||
1465 | int wm8903_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | ||
1466 | int det, int shrt) | ||
1467 | { | ||
1468 | struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); | ||
1469 | int irq_mask = WM8903_MICDET_EINT | WM8903_MICSHRT_EINT; | ||
1470 | |||
1471 | dev_dbg(codec->dev, "Enabling microphone detection: %x %x\n", | ||
1472 | det, shrt); | ||
1473 | |||
1474 | /* Store the configuration */ | ||
1475 | wm8903->mic_jack = jack; | ||
1476 | wm8903->mic_det = det; | ||
1477 | wm8903->mic_short = shrt; | ||
1478 | |||
1479 | /* Enable interrupts we've got a report configured for */ | ||
1480 | if (det) | ||
1481 | irq_mask &= ~WM8903_MICDET_EINT; | ||
1482 | if (shrt) | ||
1483 | irq_mask &= ~WM8903_MICSHRT_EINT; | ||
1484 | |||
1485 | snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, | ||
1486 | WM8903_MICDET_EINT | WM8903_MICSHRT_EINT, | ||
1487 | irq_mask); | ||
1488 | |||
1489 | if (det && shrt) { | ||
1490 | /* Enable mic detection, this may not have been set through | ||
1491 | * platform data (eg, if the defaults are OK). */ | ||
1492 | snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, | ||
1493 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | ||
1494 | snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0, | ||
1495 | WM8903_MICDET_ENA, WM8903_MICDET_ENA); | ||
1496 | } else { | ||
1497 | snd_soc_update_bits(codec, WM8903_MIC_BIAS_CONTROL_0, | ||
1498 | WM8903_MICDET_ENA, 0); | ||
1499 | } | ||
1500 | |||
1501 | return 0; | ||
1502 | } | ||
1503 | EXPORT_SYMBOL_GPL(wm8903_mic_detect); | ||
1504 | |||
1505 | static irqreturn_t wm8903_irq(int irq, void *data) | ||
1506 | { | ||
1507 | struct wm8903_priv *wm8903 = data; | ||
1508 | struct snd_soc_codec *codec = &wm8903->codec; | ||
1509 | int mic_report; | ||
1510 | int int_pol; | ||
1511 | int int_val = 0; | ||
1512 | int mask = ~snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1_MASK); | ||
1513 | |||
1514 | int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask; | ||
1515 | |||
1516 | if (int_val & WM8903_WSEQ_BUSY_EINT) { | ||
1517 | dev_dbg(codec->dev, "Write sequencer done\n"); | ||
1518 | complete(&wm8903->wseq); | ||
1519 | } | ||
1520 | |||
1521 | /* | ||
1522 | * The rest is microphone jack detection. We need to manually | ||
1523 | * invert the polarity of the interrupt after each event - to | ||
1524 | * simplify the code keep track of the last state we reported | ||
1525 | * and just invert the relevant bits in both the report and | ||
1526 | * the polarity register. | ||
1527 | */ | ||
1528 | mic_report = wm8903->mic_last_report; | ||
1529 | int_pol = snd_soc_read(codec, WM8903_INTERRUPT_POLARITY_1); | ||
1530 | |||
1531 | if (int_val & WM8903_MICSHRT_EINT) { | ||
1532 | dev_dbg(codec->dev, "Microphone short (pol=%x)\n", int_pol); | ||
1533 | |||
1534 | mic_report ^= wm8903->mic_short; | ||
1535 | int_pol ^= WM8903_MICSHRT_INV; | ||
1536 | } | ||
1537 | |||
1538 | if (int_val & WM8903_MICDET_EINT) { | ||
1539 | dev_dbg(codec->dev, "Microphone detect (pol=%x)\n", int_pol); | ||
1540 | |||
1541 | mic_report ^= wm8903->mic_det; | ||
1542 | int_pol ^= WM8903_MICDET_INV; | ||
1543 | |||
1544 | msleep(wm8903->mic_delay); | ||
1545 | } | ||
1546 | |||
1547 | snd_soc_update_bits(codec, WM8903_INTERRUPT_POLARITY_1, | ||
1548 | WM8903_MICSHRT_INV | WM8903_MICDET_INV, int_pol); | ||
1549 | |||
1550 | snd_soc_jack_report(wm8903->mic_jack, mic_report, | ||
1551 | wm8903->mic_short | wm8903->mic_det); | ||
1552 | |||
1553 | wm8903->mic_last_report = mic_report; | ||
1554 | |||
1555 | return IRQ_HANDLED; | ||
1556 | } | ||
1557 | |||
1439 | #define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ | 1558 | #define WM8903_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\ |
1440 | SNDRV_PCM_RATE_11025 | \ | 1559 | SNDRV_PCM_RATE_11025 | \ |
1441 | SNDRV_PCM_RATE_16000 | \ | 1560 | SNDRV_PCM_RATE_16000 | \ |
@@ -1510,7 +1629,6 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1510 | 1629 | ||
1511 | /* Bring the codec back up to standby first to minimise pop/clicks */ | 1630 | /* Bring the codec back up to standby first to minimise pop/clicks */ |
1512 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1631 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1513 | wm8903_set_bias_level(codec, codec->suspend_bias_level); | ||
1514 | 1632 | ||
1515 | /* Sync back everything else */ | 1633 | /* Sync back everything else */ |
1516 | if (tmp_cache) { | 1634 | if (tmp_cache) { |
@@ -1530,9 +1648,11 @@ static struct snd_soc_codec *wm8903_codec; | |||
1530 | static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | 1648 | static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, |
1531 | const struct i2c_device_id *id) | 1649 | const struct i2c_device_id *id) |
1532 | { | 1650 | { |
1651 | struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
1533 | struct wm8903_priv *wm8903; | 1652 | struct wm8903_priv *wm8903; |
1534 | struct snd_soc_codec *codec; | 1653 | struct snd_soc_codec *codec; |
1535 | int ret; | 1654 | int ret, i; |
1655 | int trigger, irq_pol; | ||
1536 | u16 val; | 1656 | u16 val; |
1537 | 1657 | ||
1538 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); | 1658 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); |
@@ -1554,8 +1674,9 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1554 | codec->num_dai = 1; | 1674 | codec->num_dai = 1; |
1555 | codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); | 1675 | codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); |
1556 | codec->reg_cache = &wm8903->reg_cache[0]; | 1676 | codec->reg_cache = &wm8903->reg_cache[0]; |
1557 | codec->private_data = wm8903; | 1677 | snd_soc_codec_set_drvdata(codec, wm8903); |
1558 | codec->volatile_register = wm8903_volatile_register; | 1678 | codec->volatile_register = wm8903_volatile_register; |
1679 | init_completion(&wm8903->wseq); | ||
1559 | 1680 | ||
1560 | i2c_set_clientdata(i2c, codec); | 1681 | i2c_set_clientdata(i2c, codec); |
1561 | codec->control_data = i2c; | 1682 | codec->control_data = i2c; |
@@ -1579,6 +1700,53 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1579 | 1700 | ||
1580 | wm8903_reset(codec); | 1701 | wm8903_reset(codec); |
1581 | 1702 | ||
1703 | /* Set up GPIOs and microphone detection */ | ||
1704 | if (pdata) { | ||
1705 | for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) { | ||
1706 | if (!pdata->gpio_cfg[i]) | ||
1707 | continue; | ||
1708 | |||
1709 | snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i, | ||
1710 | pdata->gpio_cfg[i] & 0xffff); | ||
1711 | } | ||
1712 | |||
1713 | snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0, | ||
1714 | pdata->micdet_cfg); | ||
1715 | |||
1716 | /* Microphone detection needs the WSEQ clock */ | ||
1717 | if (pdata->micdet_cfg) | ||
1718 | snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0, | ||
1719 | WM8903_WSEQ_ENA, WM8903_WSEQ_ENA); | ||
1720 | |||
1721 | wm8903->mic_delay = pdata->micdet_delay; | ||
1722 | } | ||
1723 | |||
1724 | if (i2c->irq) { | ||
1725 | if (pdata && pdata->irq_active_low) { | ||
1726 | trigger = IRQF_TRIGGER_LOW; | ||
1727 | irq_pol = WM8903_IRQ_POL; | ||
1728 | } else { | ||
1729 | trigger = IRQF_TRIGGER_HIGH; | ||
1730 | irq_pol = 0; | ||
1731 | } | ||
1732 | |||
1733 | snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, | ||
1734 | WM8903_IRQ_POL, irq_pol); | ||
1735 | |||
1736 | ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, | ||
1737 | trigger | IRQF_ONESHOT, | ||
1738 | "wm8903", wm8903); | ||
1739 | if (ret != 0) { | ||
1740 | dev_err(&i2c->dev, "Failed to request IRQ: %d\n", | ||
1741 | ret); | ||
1742 | goto err; | ||
1743 | } | ||
1744 | |||
1745 | /* Enable write sequencer interrupts */ | ||
1746 | snd_soc_update_bits(codec, WM8903_INTERRUPT_STATUS_1_MASK, | ||
1747 | WM8903_IM_WSEQ_BUSY_EINT, 0); | ||
1748 | } | ||
1749 | |||
1582 | /* power on device */ | 1750 | /* power on device */ |
1583 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1751 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1584 | 1752 | ||
@@ -1619,7 +1787,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1619 | ret = snd_soc_register_codec(codec); | 1787 | ret = snd_soc_register_codec(codec); |
1620 | if (ret != 0) { | 1788 | if (ret != 0) { |
1621 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | 1789 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); |
1622 | goto err; | 1790 | goto err_irq; |
1623 | } | 1791 | } |
1624 | 1792 | ||
1625 | ret = snd_soc_register_dai(&wm8903_dai); | 1793 | ret = snd_soc_register_dai(&wm8903_dai); |
@@ -1632,6 +1800,9 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, | |||
1632 | 1800 | ||
1633 | err_codec: | 1801 | err_codec: |
1634 | snd_soc_unregister_codec(codec); | 1802 | snd_soc_unregister_codec(codec); |
1803 | err_irq: | ||
1804 | if (i2c->irq) | ||
1805 | free_irq(i2c->irq, wm8903); | ||
1635 | err: | 1806 | err: |
1636 | wm8903_codec = NULL; | 1807 | wm8903_codec = NULL; |
1637 | kfree(wm8903); | 1808 | kfree(wm8903); |
@@ -1641,13 +1812,17 @@ err: | |||
1641 | static __devexit int wm8903_i2c_remove(struct i2c_client *client) | 1812 | static __devexit int wm8903_i2c_remove(struct i2c_client *client) |
1642 | { | 1813 | { |
1643 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1814 | struct snd_soc_codec *codec = i2c_get_clientdata(client); |
1815 | struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1644 | 1816 | ||
1645 | snd_soc_unregister_dai(&wm8903_dai); | 1817 | snd_soc_unregister_dai(&wm8903_dai); |
1646 | snd_soc_unregister_codec(codec); | 1818 | snd_soc_unregister_codec(codec); |
1647 | 1819 | ||
1648 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1820 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1649 | 1821 | ||
1650 | kfree(codec->private_data); | 1822 | if (client->irq) |
1823 | free_irq(client->irq, priv); | ||
1824 | |||
1825 | kfree(priv); | ||
1651 | 1826 | ||
1652 | wm8903_codec = NULL; | 1827 | wm8903_codec = NULL; |
1653 | wm8903_dai.dev = NULL; | 1828 | wm8903_dai.dev = NULL; |