| OLD | NEW |
| 1 /* | 1 /* |
| 2 * wm8350.c -- WM8350 ALSA SoC audio driver | 2 * wm8350.c -- WM8350 ALSA SoC audio driver |
| 3 * | 3 * |
| 4 * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. | 4 * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. |
| 5 * | 5 * |
| 6 * Author: Liam Girdwood <lrg@slimlogic.co.uk> | 6 * Author: Liam Girdwood <lrg@slimlogic.co.uk> |
| 7 * | 7 * |
| 8 * This program is free software; you can redistribute it and/or modify | 8 * This program is free software; you can redistribute it and/or modify |
| 9 * it under the terms of the GNU General Public License version 2 as | 9 * it under the terms of the GNU General Public License version 2 as |
| 10 * published by the Free Software Foundation. | 10 * published by the Free Software Foundation. |
| 11 */ | 11 */ |
| 12 | 12 |
| 13 #include <linux/module.h> | 13 #include <linux/module.h> |
| 14 #include <linux/moduleparam.h> | 14 #include <linux/moduleparam.h> |
| 15 #include <linux/init.h> | 15 #include <linux/init.h> |
| 16 #include <linux/slab.h> | 16 #include <linux/slab.h> |
| 17 #include <linux/delay.h> | 17 #include <linux/delay.h> |
| 18 #include <linux/pm.h> | 18 #include <linux/pm.h> |
| 19 #include <linux/platform_device.h> | 19 #include <linux/platform_device.h> |
| 20 #include <linux/mfd/wm8350/audio.h> | 20 #include <linux/mfd/wm8350/audio.h> |
| 21 #include <linux/mfd/wm8350/core.h> | 21 #include <linux/mfd/wm8350/core.h> |
| 22 #include <linux/regulator/consumer.h> | 22 #include <linux/regulator/consumer.h> |
| 23 #include <sound/core.h> | 23 #include <sound/core.h> |
| 24 #include <sound/pcm.h> | 24 #include <sound/pcm.h> |
| 25 #include <sound/pcm_params.h> | 25 #include <sound/pcm_params.h> |
| 26 #include <sound/soc.h> | 26 #include <sound/soc.h> |
| 27 #include <sound/soc-dapm.h> | |
| 28 #include <sound/initval.h> | 27 #include <sound/initval.h> |
| 29 #include <sound/tlv.h> | 28 #include <sound/tlv.h> |
| 29 #include <trace/events/asoc.h> |
| 30 | 30 |
| 31 #include "wm8350.h" | 31 #include "wm8350.h" |
| 32 | 32 |
| 33 #define WM8350_OUTn_0dB 0x39 | 33 #define WM8350_OUTn_0dB 0x39 |
| 34 | 34 |
| 35 #define WM8350_RAMP_NONE 0 | 35 #define WM8350_RAMP_NONE 0 |
| 36 #define WM8350_RAMP_UP 1 | 36 #define WM8350_RAMP_UP 1 |
| 37 #define WM8350_RAMP_DOWN 2 | 37 #define WM8350_RAMP_DOWN 2 |
| 38 | 38 |
| 39 /* We only include the analogue supplies here; the digital supplies | 39 /* We only include the analogue supplies here; the digital supplies |
| 40 * need to be available well before this driver can be probed. | 40 * need to be available well before this driver can be probed. |
| 41 */ | 41 */ |
| 42 static const char *supply_names[] = { | 42 static const char *supply_names[] = { |
| 43 "AVDD", | 43 "AVDD", |
| 44 "HPVDD", | 44 "HPVDD", |
| 45 }; | 45 }; |
| 46 | 46 |
| 47 struct wm8350_output { | 47 struct wm8350_output { |
| 48 u16 active; | 48 u16 active; |
| 49 u16 left_vol; | 49 u16 left_vol; |
| 50 u16 right_vol; | 50 u16 right_vol; |
| 51 u16 ramp; | 51 u16 ramp; |
| 52 u16 mute; | 52 u16 mute; |
| 53 }; | 53 }; |
| 54 | 54 |
| 55 struct wm8350_jack_data { | 55 struct wm8350_jack_data { |
| 56 struct snd_soc_jack *jack; | 56 struct snd_soc_jack *jack; |
| 57 struct delayed_work work; |
| 57 int report; | 58 int report; |
| 58 int short_report; | 59 int short_report; |
| 59 }; | 60 }; |
| 60 | 61 |
| 61 struct wm8350_data { | 62 struct wm8350_data { |
| 62 struct snd_soc_codec codec; | 63 struct snd_soc_codec codec; |
| 63 struct wm8350_output out1; | 64 struct wm8350_output out1; |
| 64 struct wm8350_output out2; | 65 struct wm8350_output out2; |
| 65 struct wm8350_jack_data hpl; | 66 struct wm8350_jack_data hpl; |
| 66 struct wm8350_jack_data hpr; | 67 struct wm8350_jack_data hpr; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 } | 224 } |
| 224 | 225 |
| 225 /* | 226 /* |
| 226 * This work ramps both output PGAs at stream start/stop time to | 227 * This work ramps both output PGAs at stream start/stop time to |
| 227 * minimise pop associated with DAPM power switching. | 228 * minimise pop associated with DAPM power switching. |
| 228 * It's best to enable Zero Cross when ramping occurs to minimise any | 229 * It's best to enable Zero Cross when ramping occurs to minimise any |
| 229 * zipper noises. | 230 * zipper noises. |
| 230 */ | 231 */ |
| 231 static void wm8350_pga_work(struct work_struct *work) | 232 static void wm8350_pga_work(struct work_struct *work) |
| 232 { | 233 { |
| 233 » struct snd_soc_codec *codec = | 234 » struct snd_soc_dapm_context *dapm = |
| 234 » container_of(work, struct snd_soc_codec, delayed_work.work); | 235 » container_of(work, struct snd_soc_dapm_context, delayed_work.work); |
| 236 » struct snd_soc_codec *codec = dapm->codec; |
| 235 struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | 237 struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); |
| 236 struct wm8350_output *out1 = &wm8350_data->out1, | 238 struct wm8350_output *out1 = &wm8350_data->out1, |
| 237 *out2 = &wm8350_data->out2; | 239 *out2 = &wm8350_data->out2; |
| 238 int i, out1_complete, out2_complete; | 240 int i, out1_complete, out2_complete; |
| 239 | 241 |
| 240 /* do we need to ramp at all ? */ | 242 /* do we need to ramp at all ? */ |
| 241 if (out1->ramp == WM8350_RAMP_NONE && out2->ramp == WM8350_RAMP_NONE) | 243 if (out1->ramp == WM8350_RAMP_NONE && out2->ramp == WM8350_RAMP_NONE) |
| 242 return; | 244 return; |
| 243 | 245 |
| 244 /* PGA volumes have 6 bits of resolution to ramp */ | 246 /* PGA volumes have 6 bits of resolution to ramp */ |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 default: | 297 default: |
| 296 BUG(); | 298 BUG(); |
| 297 return -1; | 299 return -1; |
| 298 } | 300 } |
| 299 | 301 |
| 300 switch (event) { | 302 switch (event) { |
| 301 case SND_SOC_DAPM_POST_PMU: | 303 case SND_SOC_DAPM_POST_PMU: |
| 302 out->ramp = WM8350_RAMP_UP; | 304 out->ramp = WM8350_RAMP_UP; |
| 303 out->active = 1; | 305 out->active = 1; |
| 304 | 306 |
| 305 » » if (!delayed_work_pending(&codec->delayed_work)) | 307 » » if (!delayed_work_pending(&codec->dapm.delayed_work)) |
| 306 » » » schedule_delayed_work(&codec->delayed_work, | 308 » » » schedule_delayed_work(&codec->dapm.delayed_work, |
| 307 msecs_to_jiffies(1)); | 309 msecs_to_jiffies(1)); |
| 308 break; | 310 break; |
| 309 | 311 |
| 310 case SND_SOC_DAPM_PRE_PMD: | 312 case SND_SOC_DAPM_PRE_PMD: |
| 311 out->ramp = WM8350_RAMP_DOWN; | 313 out->ramp = WM8350_RAMP_DOWN; |
| 312 out->active = 0; | 314 out->active = 0; |
| 313 | 315 |
| 314 » » if (!delayed_work_pending(&codec->delayed_work)) | 316 » » if (!delayed_work_pending(&codec->dapm.delayed_work)) |
| 315 » » » schedule_delayed_work(&codec->delayed_work, | 317 » » » schedule_delayed_work(&codec->dapm.delayed_work, |
| 316 msecs_to_jiffies(1)); | 318 msecs_to_jiffies(1)); |
| 317 break; | 319 break; |
| 318 } | 320 } |
| 319 | 321 |
| 320 return 0; | 322 return 0; |
| 321 } | 323 } |
| 322 | 324 |
| 323 static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, | 325 static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, |
| 324 struct snd_ctl_elem_value *ucontrol) | 326 struct snd_ctl_elem_value *ucontrol) |
| 325 { | 327 { |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 | 781 |
| 780 /* out 4 capture */ | 782 /* out 4 capture */ |
| 781 {"Out4 Capture Channel", NULL, "Out4 Mixer"}, | 783 {"Out4 Capture Channel", NULL, "Out4 Mixer"}, |
| 782 | 784 |
| 783 /* Beep */ | 785 /* Beep */ |
| 784 {"Beep", NULL, "IN3R PGA"}, | 786 {"Beep", NULL, "IN3R PGA"}, |
| 785 }; | 787 }; |
| 786 | 788 |
| 787 static int wm8350_add_widgets(struct snd_soc_codec *codec) | 789 static int wm8350_add_widgets(struct snd_soc_codec *codec) |
| 788 { | 790 { |
| 791 struct snd_soc_dapm_context *dapm = &codec->dapm; |
| 789 int ret; | 792 int ret; |
| 790 | 793 |
| 791 » ret = snd_soc_dapm_new_controls(codec, | 794 » ret = snd_soc_dapm_new_controls(dapm, |
| 792 wm8350_dapm_widgets, | 795 wm8350_dapm_widgets, |
| 793 ARRAY_SIZE(wm8350_dapm_widgets)); | 796 ARRAY_SIZE(wm8350_dapm_widgets)); |
| 794 if (ret != 0) { | 797 if (ret != 0) { |
| 795 dev_err(codec->dev, "dapm control register failed\n"); | 798 dev_err(codec->dev, "dapm control register failed\n"); |
| 796 return ret; | 799 return ret; |
| 797 } | 800 } |
| 798 | 801 |
| 799 /* set up audio paths */ | 802 /* set up audio paths */ |
| 800 » ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 803 » ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); |
| 801 if (ret != 0) { | 804 if (ret != 0) { |
| 802 dev_err(codec->dev, "DAPM route register failed\n"); | 805 dev_err(codec->dev, "DAPM route register failed\n"); |
| 803 return ret; | 806 return ret; |
| 804 } | 807 } |
| 805 | 808 |
| 806 return 0; | 809 return 0; |
| 807 } | 810 } |
| 808 | 811 |
| 809 static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, | 812 static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, |
| 810 int clk_id, unsigned int freq, int dir) | 813 int clk_id, unsigned int freq, int dir) |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1177 break; | 1180 break; |
| 1178 | 1181 |
| 1179 case SND_SOC_BIAS_PREPARE: | 1182 case SND_SOC_BIAS_PREPARE: |
| 1180 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1); | 1183 pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1); |
| 1181 pm1 &= ~WM8350_VMID_MASK; | 1184 pm1 &= ~WM8350_VMID_MASK; |
| 1182 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, | 1185 wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, |
| 1183 pm1 | WM8350_VMID_50K); | 1186 pm1 | WM8350_VMID_50K); |
| 1184 break; | 1187 break; |
| 1185 | 1188 |
| 1186 case SND_SOC_BIAS_STANDBY: | 1189 case SND_SOC_BIAS_STANDBY: |
| 1187 » » if (codec->bias_level == SND_SOC_BIAS_OFF) { | 1190 » » if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 1188 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), | 1191 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), |
| 1189 priv->supplies); | 1192 priv->supplies); |
| 1190 if (ret != 0) | 1193 if (ret != 0) |
| 1191 return ret; | 1194 return ret; |
| 1192 | 1195 |
| 1193 /* Enable the system clock */ | 1196 /* Enable the system clock */ |
| 1194 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, | 1197 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, |
| 1195 WM8350_SYSCLK_ENA); | 1198 WM8350_SYSCLK_ENA); |
| 1196 | 1199 |
| 1197 /* mute DAC & outputs */ | 1200 /* mute DAC & outputs */ |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1310 WM8350_OUT2R_ENA); | 1313 WM8350_OUT2R_ENA); |
| 1311 | 1314 |
| 1312 /* disable clock gen */ | 1315 /* disable clock gen */ |
| 1313 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, | 1316 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, |
| 1314 WM8350_SYSCLK_ENA); | 1317 WM8350_SYSCLK_ENA); |
| 1315 | 1318 |
| 1316 regulator_bulk_disable(ARRAY_SIZE(priv->supplies), | 1319 regulator_bulk_disable(ARRAY_SIZE(priv->supplies), |
| 1317 priv->supplies); | 1320 priv->supplies); |
| 1318 break; | 1321 break; |
| 1319 } | 1322 } |
| 1320 » codec->bias_level = level; | 1323 » codec->dapm.bias_level = level; |
| 1321 return 0; | 1324 return 0; |
| 1322 } | 1325 } |
| 1323 | 1326 |
| 1324 static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state) | 1327 static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state) |
| 1325 { | 1328 { |
| 1326 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1329 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 1327 return 0; | 1330 return 0; |
| 1328 } | 1331 } |
| 1329 | 1332 |
| 1330 static int wm8350_resume(struct snd_soc_codec *codec) | 1333 static int wm8350_resume(struct snd_soc_codec *codec) |
| 1331 { | 1334 { |
| 1332 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1335 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
| 1333 | 1336 |
| 1334 return 0; | 1337 return 0; |
| 1335 } | 1338 } |
| 1336 | 1339 |
| 1337 static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) | 1340 static void wm8350_hp_work(struct wm8350_data *priv, |
| 1341 » » » struct wm8350_jack_data *jack, |
| 1342 » » » u16 mask) |
| 1338 { | 1343 { |
| 1339 struct wm8350_data *priv = data; | |
| 1340 struct wm8350 *wm8350 = priv->codec.control_data; | 1344 struct wm8350 *wm8350 = priv->codec.control_data; |
| 1341 u16 reg; | 1345 u16 reg; |
| 1342 int report; | 1346 int report; |
| 1343 int mask; | |
| 1344 struct wm8350_jack_data *jack = NULL; | |
| 1345 | |
| 1346 switch (irq - wm8350->irq_base) { | |
| 1347 case WM8350_IRQ_CODEC_JCK_DET_L: | |
| 1348 jack = &priv->hpl; | |
| 1349 mask = WM8350_JACK_L_LVL; | |
| 1350 break; | |
| 1351 | |
| 1352 case WM8350_IRQ_CODEC_JCK_DET_R: | |
| 1353 jack = &priv->hpr; | |
| 1354 mask = WM8350_JACK_R_LVL; | |
| 1355 break; | |
| 1356 | |
| 1357 default: | |
| 1358 BUG(); | |
| 1359 } | |
| 1360 | |
| 1361 if (!jack->jack) { | |
| 1362 dev_warn(wm8350->dev, "Jack interrupt called with no jack\n"); | |
| 1363 return IRQ_NONE; | |
| 1364 } | |
| 1365 | |
| 1366 /* Debounce */ | |
| 1367 msleep(200); | |
| 1368 | 1347 |
| 1369 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); | 1348 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); |
| 1370 if (reg & mask) | 1349 if (reg & mask) |
| 1371 report = jack->report; | 1350 report = jack->report; |
| 1372 else | 1351 else |
| 1373 report = 0; | 1352 report = 0; |
| 1374 | 1353 |
| 1375 snd_soc_jack_report(jack->jack, report, jack->report); | 1354 snd_soc_jack_report(jack->jack, report, jack->report); |
| 1376 | 1355 |
| 1356 } |
| 1357 |
| 1358 static void wm8350_hpl_work(struct work_struct *work) |
| 1359 { |
| 1360 struct wm8350_data *priv = |
| 1361 container_of(work, struct wm8350_data, hpl.work.work); |
| 1362 |
| 1363 wm8350_hp_work(priv, &priv->hpl, WM8350_JACK_L_LVL); |
| 1364 } |
| 1365 |
| 1366 static void wm8350_hpr_work(struct work_struct *work) |
| 1367 { |
| 1368 struct wm8350_data *priv = |
| 1369 container_of(work, struct wm8350_data, hpr.work.work); |
| 1370 |
| 1371 wm8350_hp_work(priv, &priv->hpr, WM8350_JACK_R_LVL); |
| 1372 } |
| 1373 |
| 1374 static irqreturn_t wm8350_hp_jack_handler(int irq, void *data) |
| 1375 { |
| 1376 struct wm8350_data *priv = data; |
| 1377 struct wm8350 *wm8350 = priv->codec.control_data; |
| 1378 struct wm8350_jack_data *jack = NULL; |
| 1379 |
| 1380 switch (irq - wm8350->irq_base) { |
| 1381 case WM8350_IRQ_CODEC_JCK_DET_L: |
| 1382 #ifndef CONFIG_SND_SOC_WM8350_MODULE |
| 1383 trace_snd_soc_jack_irq("WM8350 HPL"); |
| 1384 #endif |
| 1385 jack = &priv->hpl; |
| 1386 break; |
| 1387 |
| 1388 case WM8350_IRQ_CODEC_JCK_DET_R: |
| 1389 #ifndef CONFIG_SND_SOC_WM8350_MODULE |
| 1390 trace_snd_soc_jack_irq("WM8350 HPR"); |
| 1391 #endif |
| 1392 jack = &priv->hpr; |
| 1393 break; |
| 1394 |
| 1395 default: |
| 1396 BUG(); |
| 1397 } |
| 1398 |
| 1399 if (device_may_wakeup(wm8350->dev)) |
| 1400 pm_wakeup_event(wm8350->dev, 250); |
| 1401 |
| 1402 schedule_delayed_work(&jack->work, 200); |
| 1403 |
| 1377 return IRQ_HANDLED; | 1404 return IRQ_HANDLED; |
| 1378 } | 1405 } |
| 1379 | 1406 |
| 1380 /** | 1407 /** |
| 1381 * wm8350_hp_jack_detect - Enable headphone jack detection. | 1408 * wm8350_hp_jack_detect - Enable headphone jack detection. |
| 1382 * | 1409 * |
| 1383 * @codec: WM8350 codec | 1410 * @codec: WM8350 codec |
| 1384 * @which: left or right jack detect signal | 1411 * @which: left or right jack detect signal |
| 1385 * @jack: jack to report detection events on | 1412 * @jack: jack to report detection events on |
| 1386 * @report: value to report | 1413 * @report: value to report |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1429 } | 1456 } |
| 1430 EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); | 1457 EXPORT_SYMBOL_GPL(wm8350_hp_jack_detect); |
| 1431 | 1458 |
| 1432 static irqreturn_t wm8350_mic_handler(int irq, void *data) | 1459 static irqreturn_t wm8350_mic_handler(int irq, void *data) |
| 1433 { | 1460 { |
| 1434 struct wm8350_data *priv = data; | 1461 struct wm8350_data *priv = data; |
| 1435 struct wm8350 *wm8350 = priv->codec.control_data; | 1462 struct wm8350 *wm8350 = priv->codec.control_data; |
| 1436 u16 reg; | 1463 u16 reg; |
| 1437 int report = 0; | 1464 int report = 0; |
| 1438 | 1465 |
| 1466 #ifndef CONFIG_SND_SOC_WM8350_MODULE |
| 1467 trace_snd_soc_jack_irq("WM8350 mic"); |
| 1468 #endif |
| 1469 |
| 1439 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); | 1470 reg = wm8350_reg_read(wm8350, WM8350_JACK_PIN_STATUS); |
| 1440 if (reg & WM8350_JACK_MICSCD_LVL) | 1471 if (reg & WM8350_JACK_MICSCD_LVL) |
| 1441 report |= priv->mic.short_report; | 1472 report |= priv->mic.short_report; |
| 1442 if (reg & WM8350_JACK_MICSD_LVL) | 1473 if (reg & WM8350_JACK_MICSD_LVL) |
| 1443 report |= priv->mic.report; | 1474 report |= priv->mic.report; |
| 1444 | 1475 |
| 1445 snd_soc_jack_report(priv->mic.jack, report, | 1476 snd_soc_jack_report(priv->mic.jack, report, |
| 1446 priv->mic.report | priv->mic.short_report); | 1477 priv->mic.report | priv->mic.short_report); |
| 1447 | 1478 |
| 1448 return IRQ_HANDLED; | 1479 return IRQ_HANDLED; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1543 priv->supplies); | 1574 priv->supplies); |
| 1544 if (ret != 0) | 1575 if (ret != 0) |
| 1545 goto err_priv; | 1576 goto err_priv; |
| 1546 | 1577 |
| 1547 wm8350->codec.codec = codec; | 1578 wm8350->codec.codec = codec; |
| 1548 codec->control_data = wm8350; | 1579 codec->control_data = wm8350; |
| 1549 | 1580 |
| 1550 /* Put the codec into reset if it wasn't already */ | 1581 /* Put the codec into reset if it wasn't already */ |
| 1551 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1582 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
| 1552 | 1583 |
| 1553 » INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); | 1584 » INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work); |
| 1585 » INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work); |
| 1586 » INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work); |
| 1554 | 1587 |
| 1555 /* Enable the codec */ | 1588 /* Enable the codec */ |
| 1556 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1589 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
| 1557 | 1590 |
| 1558 /* Enable robust clocking mode in ADC */ | 1591 /* Enable robust clocking mode in ADC */ |
| 1559 wm8350_codec_write(codec, WM8350_SECURITY, 0xa7); | 1592 wm8350_codec_write(codec, WM8350_SECURITY, 0xa7); |
| 1560 wm8350_codec_write(codec, 0xde, 0x13); | 1593 wm8350_codec_write(codec, 0xde, 0x13); |
| 1561 wm8350_codec_write(codec, WM8350_SECURITY, 0); | 1594 wm8350_codec_write(codec, WM8350_SECURITY, 0); |
| 1562 | 1595 |
| 1563 /* read OUT1 & OUT2 volumes */ | 1596 /* read OUT1 & OUT2 volumes */ |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 | 1652 |
| 1620 err_priv: | 1653 err_priv: |
| 1621 kfree(priv); | 1654 kfree(priv); |
| 1622 return ret; | 1655 return ret; |
| 1623 } | 1656 } |
| 1624 | 1657 |
| 1625 static int wm8350_codec_remove(struct snd_soc_codec *codec) | 1658 static int wm8350_codec_remove(struct snd_soc_codec *codec) |
| 1626 { | 1659 { |
| 1627 struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); | 1660 struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); |
| 1628 struct wm8350 *wm8350 = dev_get_platdata(codec->dev); | 1661 struct wm8350 *wm8350 = dev_get_platdata(codec->dev); |
| 1629 int ret; | |
| 1630 | 1662 |
| 1631 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, | 1663 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, |
| 1632 WM8350_JDL_ENA | WM8350_JDR_ENA); | 1664 WM8350_JDL_ENA | WM8350_JDR_ENA); |
| 1633 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); | 1665 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); |
| 1634 | 1666 |
| 1635 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICD, priv); | 1667 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICD, priv); |
| 1636 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv); | 1668 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_MICSCD, priv); |
| 1637 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); | 1669 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv); |
| 1638 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); | 1670 wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv); |
| 1639 | 1671 |
| 1640 priv->hpl.jack = NULL; | 1672 priv->hpl.jack = NULL; |
| 1641 priv->hpr.jack = NULL; | 1673 priv->hpr.jack = NULL; |
| 1642 priv->mic.jack = NULL; | 1674 priv->mic.jack = NULL; |
| 1643 | 1675 |
| 1644 » /* cancel any work waiting to be queued. */ | 1676 » cancel_delayed_work_sync(&priv->hpl.work); |
| 1645 » ret = cancel_delayed_work(&codec->delayed_work); | 1677 » cancel_delayed_work_sync(&priv->hpr.work); |
| 1646 | 1678 |
| 1647 /* if there was any work waiting then we run it now and | 1679 /* if there was any work waiting then we run it now and |
| 1648 * wait for its completion */ | 1680 * wait for its completion */ |
| 1649 » if (ret) { | 1681 » flush_delayed_work_sync(&codec->dapm.delayed_work); |
| 1650 » » schedule_delayed_work(&codec->delayed_work, 0); | |
| 1651 » » flush_scheduled_work(); | |
| 1652 » } | |
| 1653 | 1682 |
| 1654 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1683 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 1655 | 1684 |
| 1656 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1685 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
| 1657 | 1686 |
| 1658 regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | 1687 regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); |
| 1659 kfree(priv); | 1688 kfree(priv); |
| 1660 return 0; | 1689 return 0; |
| 1661 } | 1690 } |
| 1662 | 1691 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1700 static __exit void wm8350_exit(void) | 1729 static __exit void wm8350_exit(void) |
| 1701 { | 1730 { |
| 1702 platform_driver_unregister(&wm8350_codec_driver); | 1731 platform_driver_unregister(&wm8350_codec_driver); |
| 1703 } | 1732 } |
| 1704 module_exit(wm8350_exit); | 1733 module_exit(wm8350_exit); |
| 1705 | 1734 |
| 1706 MODULE_DESCRIPTION("ASoC WM8350 driver"); | 1735 MODULE_DESCRIPTION("ASoC WM8350 driver"); |
| 1707 MODULE_AUTHOR("Liam Girdwood"); | 1736 MODULE_AUTHOR("Liam Girdwood"); |
| 1708 MODULE_LICENSE("GPL"); | 1737 MODULE_LICENSE("GPL"); |
| 1709 MODULE_ALIAS("platform:wm8350-codec"); | 1738 MODULE_ALIAS("platform:wm8350-codec"); |
| OLD | NEW |