diff options
| -rw-r--r-- | include/sound/soc-dapm.h | 2 | ||||
| -rw-r--r-- | include/sound/soc-dpcm.h | 2 | ||||
| -rw-r--r-- | sound/soc/codecs/wm8350.c | 25 | ||||
| -rw-r--r-- | sound/soc/codecs/wm8753.c | 73 | ||||
| -rw-r--r-- | sound/soc/codecs/wm8971.c | 99 | ||||
| -rw-r--r-- | sound/soc/soc-core.c | 104 | ||||
| -rw-r--r-- | sound/soc/soc-dapm.c | 3 | ||||
| -rw-r--r-- | sound/soc/soc-pcm.c | 16 |
8 files changed, 135 insertions, 189 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 8d7416e46861..485fc9d1a7bc 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
| @@ -586,8 +586,6 @@ struct snd_soc_dapm_update { | |||
| 586 | /* DAPM context */ | 586 | /* DAPM context */ |
| 587 | struct snd_soc_dapm_context { | 587 | struct snd_soc_dapm_context { |
| 588 | enum snd_soc_bias_level bias_level; | 588 | enum snd_soc_bias_level bias_level; |
| 589 | enum snd_soc_bias_level suspend_bias_level; | ||
| 590 | struct delayed_work delayed_work; | ||
| 591 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ | 589 | unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ |
| 592 | /* Go to BIAS_OFF in suspend if the DAPM context is idle */ | 590 | /* Go to BIAS_OFF in suspend if the DAPM context is idle */ |
| 593 | unsigned int suspend_bias_off:1; | 591 | unsigned int suspend_bias_off:1; |
diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 98f2ade0266e..806059052bfc 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h | |||
| @@ -135,7 +135,7 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, | |||
| 135 | 135 | ||
| 136 | /* internal use only */ | 136 | /* internal use only */ |
| 137 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); | 137 | int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); |
| 138 | int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); | 138 | void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); |
| 139 | int soc_dpcm_runtime_update(struct snd_soc_card *); | 139 | int soc_dpcm_runtime_update(struct snd_soc_card *); |
| 140 | 140 | ||
| 141 | int dpcm_path_get(struct snd_soc_pcm_runtime *fe, | 141 | int dpcm_path_get(struct snd_soc_pcm_runtime *fe, |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index c81a9eab3e3e..c65e5a75fc1a 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
| @@ -69,14 +69,14 @@ struct wm8350_data { | |||
| 69 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | 69 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; |
| 70 | int fll_freq_out; | 70 | int fll_freq_out; |
| 71 | int fll_freq_in; | 71 | int fll_freq_in; |
| 72 | struct delayed_work pga_work; | ||
| 72 | }; | 73 | }; |
| 73 | 74 | ||
| 74 | /* | 75 | /* |
| 75 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. | 76 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. |
| 76 | */ | 77 | */ |
| 77 | static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec) | 78 | static inline int wm8350_out1_ramp_step(struct wm8350_data *wm8350_data) |
| 78 | { | 79 | { |
| 79 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | ||
| 80 | struct wm8350_output *out1 = &wm8350_data->out1; | 80 | struct wm8350_output *out1 = &wm8350_data->out1; |
| 81 | struct wm8350 *wm8350 = wm8350_data->wm8350; | 81 | struct wm8350 *wm8350 = wm8350_data->wm8350; |
| 82 | int left_complete = 0, right_complete = 0; | 82 | int left_complete = 0, right_complete = 0; |
| @@ -140,9 +140,8 @@ static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec) | |||
| 140 | /* | 140 | /* |
| 141 | * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown. | 141 | * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown. |
| 142 | */ | 142 | */ |
| 143 | static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec) | 143 | static inline int wm8350_out2_ramp_step(struct wm8350_data *wm8350_data) |
| 144 | { | 144 | { |
| 145 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | ||
| 146 | struct wm8350_output *out2 = &wm8350_data->out2; | 145 | struct wm8350_output *out2 = &wm8350_data->out2; |
| 147 | struct wm8350 *wm8350 = wm8350_data->wm8350; | 146 | struct wm8350 *wm8350 = wm8350_data->wm8350; |
| 148 | int left_complete = 0, right_complete = 0; | 147 | int left_complete = 0, right_complete = 0; |
| @@ -210,10 +209,8 @@ static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec) | |||
| 210 | */ | 209 | */ |
| 211 | static void wm8350_pga_work(struct work_struct *work) | 210 | static void wm8350_pga_work(struct work_struct *work) |
| 212 | { | 211 | { |
| 213 | struct snd_soc_dapm_context *dapm = | 212 | struct wm8350_data *wm8350_data = |
| 214 | container_of(work, struct snd_soc_dapm_context, delayed_work.work); | 213 | container_of(work, struct wm8350_data, pga_work.work); |
| 215 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
| 216 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | ||
| 217 | struct wm8350_output *out1 = &wm8350_data->out1, | 214 | struct wm8350_output *out1 = &wm8350_data->out1, |
| 218 | *out2 = &wm8350_data->out2; | 215 | *out2 = &wm8350_data->out2; |
| 219 | int i, out1_complete, out2_complete; | 216 | int i, out1_complete, out2_complete; |
| @@ -226,9 +223,9 @@ static void wm8350_pga_work(struct work_struct *work) | |||
| 226 | for (i = 0; i <= 63; i++) { | 223 | for (i = 0; i <= 63; i++) { |
| 227 | out1_complete = 1, out2_complete = 1; | 224 | out1_complete = 1, out2_complete = 1; |
| 228 | if (out1->ramp != WM8350_RAMP_NONE) | 225 | if (out1->ramp != WM8350_RAMP_NONE) |
| 229 | out1_complete = wm8350_out1_ramp_step(codec); | 226 | out1_complete = wm8350_out1_ramp_step(wm8350_data); |
| 230 | if (out2->ramp != WM8350_RAMP_NONE) | 227 | if (out2->ramp != WM8350_RAMP_NONE) |
| 231 | out2_complete = wm8350_out2_ramp_step(codec); | 228 | out2_complete = wm8350_out2_ramp_step(wm8350_data); |
| 232 | 229 | ||
| 233 | /* ramp finished ? */ | 230 | /* ramp finished ? */ |
| 234 | if (out1_complete && out2_complete) | 231 | if (out1_complete && out2_complete) |
| @@ -283,7 +280,7 @@ static int pga_event(struct snd_soc_dapm_widget *w, | |||
| 283 | out->ramp = WM8350_RAMP_UP; | 280 | out->ramp = WM8350_RAMP_UP; |
| 284 | out->active = 1; | 281 | out->active = 1; |
| 285 | 282 | ||
| 286 | schedule_delayed_work(&codec->dapm.delayed_work, | 283 | schedule_delayed_work(&wm8350_data->pga_work, |
| 287 | msecs_to_jiffies(1)); | 284 | msecs_to_jiffies(1)); |
| 288 | break; | 285 | break; |
| 289 | 286 | ||
| @@ -291,7 +288,7 @@ static int pga_event(struct snd_soc_dapm_widget *w, | |||
| 291 | out->ramp = WM8350_RAMP_DOWN; | 288 | out->ramp = WM8350_RAMP_DOWN; |
| 292 | out->active = 0; | 289 | out->active = 0; |
| 293 | 290 | ||
| 294 | schedule_delayed_work(&codec->dapm.delayed_work, | 291 | schedule_delayed_work(&wm8350_data->pga_work, |
| 295 | msecs_to_jiffies(1)); | 292 | msecs_to_jiffies(1)); |
| 296 | break; | 293 | break; |
| 297 | } | 294 | } |
| @@ -1492,7 +1489,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) | |||
| 1492 | /* Put the codec into reset if it wasn't already */ | 1489 | /* Put the codec into reset if it wasn't already */ |
| 1493 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1490 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
| 1494 | 1491 | ||
| 1495 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work); | 1492 | INIT_DELAYED_WORK(&priv->pga_work, wm8350_pga_work); |
| 1496 | INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work); | 1493 | INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work); |
| 1497 | INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work); | 1494 | INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work); |
| 1498 | 1495 | ||
| @@ -1578,7 +1575,7 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec) | |||
| 1578 | 1575 | ||
| 1579 | /* if there was any work waiting then we run it now and | 1576 | /* if there was any work waiting then we run it now and |
| 1580 | * wait for its completion */ | 1577 | * wait for its completion */ |
| 1581 | flush_delayed_work(&codec->dapm.delayed_work); | 1578 | flush_delayed_work(&priv->pga_work); |
| 1582 | 1579 | ||
| 1583 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1580 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
| 1584 | 1581 | ||
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 21ca3a94fc96..c50a5959345f 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
| @@ -153,6 +153,7 @@ struct wm8753_priv { | |||
| 153 | unsigned int hifi_fmt; | 153 | unsigned int hifi_fmt; |
| 154 | 154 | ||
| 155 | int dai_func; | 155 | int dai_func; |
| 156 | struct delayed_work charge_work; | ||
| 156 | }; | 157 | }; |
| 157 | 158 | ||
| 158 | #define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0) | 159 | #define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0) |
| @@ -1326,9 +1327,19 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) | |||
| 1326 | return 0; | 1327 | return 0; |
| 1327 | } | 1328 | } |
| 1328 | 1329 | ||
| 1330 | static void wm8753_charge_work(struct work_struct *work) | ||
| 1331 | { | ||
| 1332 | struct wm8753_priv *wm8753 = | ||
| 1333 | container_of(work, struct wm8753_priv, charge_work.work); | ||
| 1334 | |||
| 1335 | /* Set to 500k */ | ||
| 1336 | regmap_update_bits(wm8753->regmap, WM8753_PWR1, 0x0180, 0x0100); | ||
| 1337 | } | ||
| 1338 | |||
| 1329 | static int wm8753_set_bias_level(struct snd_soc_codec *codec, | 1339 | static int wm8753_set_bias_level(struct snd_soc_codec *codec, |
| 1330 | enum snd_soc_bias_level level) | 1340 | enum snd_soc_bias_level level) |
| 1331 | { | 1341 | { |
| 1342 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
| 1332 | u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e; | 1343 | u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e; |
| 1333 | 1344 | ||
| 1334 | switch (level) { | 1345 | switch (level) { |
| @@ -1337,14 +1348,22 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
| 1337 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); | 1348 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); |
| 1338 | break; | 1349 | break; |
| 1339 | case SND_SOC_BIAS_PREPARE: | 1350 | case SND_SOC_BIAS_PREPARE: |
| 1340 | /* set vmid to 5k for quick power up */ | 1351 | /* Wait until fully charged */ |
| 1341 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); | 1352 | flush_delayed_work(&wm8753->charge_work); |
| 1342 | break; | 1353 | break; |
| 1343 | case SND_SOC_BIAS_STANDBY: | 1354 | case SND_SOC_BIAS_STANDBY: |
| 1344 | /* mute dac and set vmid to 500k, enable VREF */ | 1355 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 1345 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141); | 1356 | /* set vmid to 5k for quick power up */ |
| 1357 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); | ||
| 1358 | schedule_delayed_work(&wm8753->charge_work, | ||
| 1359 | msecs_to_jiffies(caps_charge)); | ||
| 1360 | } else { | ||
| 1361 | /* mute dac and set vmid to 500k, enable VREF */ | ||
| 1362 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141); | ||
| 1363 | } | ||
| 1346 | break; | 1364 | break; |
| 1347 | case SND_SOC_BIAS_OFF: | 1365 | case SND_SOC_BIAS_OFF: |
| 1366 | cancel_delayed_work_sync(&wm8753->charge_work); | ||
| 1348 | snd_soc_write(codec, WM8753_PWR1, 0x0001); | 1367 | snd_soc_write(codec, WM8753_PWR1, 0x0001); |
| 1349 | break; | 1368 | break; |
| 1350 | } | 1369 | } |
| @@ -1428,38 +1447,12 @@ static struct snd_soc_dai_driver wm8753_dai[] = { | |||
| 1428 | }, | 1447 | }, |
| 1429 | }; | 1448 | }; |
| 1430 | 1449 | ||
| 1431 | static void wm8753_work(struct work_struct *work) | ||
| 1432 | { | ||
| 1433 | struct snd_soc_dapm_context *dapm = | ||
| 1434 | container_of(work, struct snd_soc_dapm_context, | ||
| 1435 | delayed_work.work); | ||
| 1436 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
| 1437 | wm8753_set_bias_level(codec, dapm->bias_level); | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | static int wm8753_suspend(struct snd_soc_codec *codec) | ||
| 1441 | { | ||
| 1442 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
| 1443 | return 0; | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | static int wm8753_resume(struct snd_soc_codec *codec) | 1450 | static int wm8753_resume(struct snd_soc_codec *codec) |
| 1447 | { | 1451 | { |
| 1448 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 1452 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
| 1449 | 1453 | ||
| 1450 | regcache_sync(wm8753->regmap); | 1454 | regcache_sync(wm8753->regmap); |
| 1451 | 1455 | ||
| 1452 | wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
| 1453 | |||
| 1454 | /* charge wm8753 caps */ | ||
| 1455 | if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { | ||
| 1456 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
| 1457 | codec->dapm.bias_level = SND_SOC_BIAS_ON; | ||
| 1458 | queue_delayed_work(system_power_efficient_wq, | ||
| 1459 | &codec->dapm.delayed_work, | ||
| 1460 | msecs_to_jiffies(caps_charge)); | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | return 0; | 1456 | return 0; |
| 1464 | } | 1457 | } |
| 1465 | 1458 | ||
| @@ -1468,7 +1461,7 @@ static int wm8753_probe(struct snd_soc_codec *codec) | |||
| 1468 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 1461 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
| 1469 | int ret; | 1462 | int ret; |
| 1470 | 1463 | ||
| 1471 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); | 1464 | INIT_DELAYED_WORK(&wm8753->charge_work, wm8753_charge_work); |
| 1472 | 1465 | ||
| 1473 | ret = wm8753_reset(codec); | 1466 | ret = wm8753_reset(codec); |
| 1474 | if (ret < 0) { | 1467 | if (ret < 0) { |
| @@ -1476,14 +1469,8 @@ static int wm8753_probe(struct snd_soc_codec *codec) | |||
| 1476 | return ret; | 1469 | return ret; |
| 1477 | } | 1470 | } |
| 1478 | 1471 | ||
| 1479 | wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
| 1480 | wm8753->dai_func = 0; | 1472 | wm8753->dai_func = 0; |
| 1481 | 1473 | ||
| 1482 | /* charge output caps */ | ||
| 1483 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
| 1484 | schedule_delayed_work(&codec->dapm.delayed_work, | ||
| 1485 | msecs_to_jiffies(caps_charge)); | ||
| 1486 | |||
| 1487 | /* set the update bits */ | 1474 | /* set the update bits */ |
| 1488 | snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); | 1475 | snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); |
| 1489 | snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); | 1476 | snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); |
| @@ -1499,21 +1486,11 @@ static int wm8753_probe(struct snd_soc_codec *codec) | |||
| 1499 | return 0; | 1486 | return 0; |
| 1500 | } | 1487 | } |
| 1501 | 1488 | ||
| 1502 | /* power down chip */ | ||
| 1503 | static int wm8753_remove(struct snd_soc_codec *codec) | ||
| 1504 | { | ||
| 1505 | flush_delayed_work(&codec->dapm.delayed_work); | ||
| 1506 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
| 1507 | |||
| 1508 | return 0; | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { | 1489 | static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { |
| 1512 | .probe = wm8753_probe, | 1490 | .probe = wm8753_probe, |
| 1513 | .remove = wm8753_remove, | ||
| 1514 | .suspend = wm8753_suspend, | ||
| 1515 | .resume = wm8753_resume, | 1491 | .resume = wm8753_resume, |
| 1516 | .set_bias_level = wm8753_set_bias_level, | 1492 | .set_bias_level = wm8753_set_bias_level, |
| 1493 | .suspend_bias_off = true, | ||
| 1517 | 1494 | ||
| 1518 | .controls = wm8753_snd_controls, | 1495 | .controls = wm8753_snd_controls, |
| 1519 | .num_controls = ARRAY_SIZE(wm8753_snd_controls), | 1496 | .num_controls = ARRAY_SIZE(wm8753_snd_controls), |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 39ddb9b8834c..f9cbabdc6238 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
| @@ -31,11 +31,11 @@ | |||
| 31 | 31 | ||
| 32 | #define WM8971_REG_COUNT 43 | 32 | #define WM8971_REG_COUNT 43 |
| 33 | 33 | ||
| 34 | static struct workqueue_struct *wm8971_workq = NULL; | ||
| 35 | |||
| 36 | /* codec private data */ | 34 | /* codec private data */ |
| 37 | struct wm8971_priv { | 35 | struct wm8971_priv { |
| 38 | unsigned int sysclk; | 36 | unsigned int sysclk; |
| 37 | struct delayed_work charge_work; | ||
| 38 | struct regmap *regmap; | ||
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | /* | 41 | /* |
| @@ -552,9 +552,19 @@ static int wm8971_mute(struct snd_soc_dai *dai, int mute) | |||
| 552 | return 0; | 552 | return 0; |
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | static void wm8971_charge_work(struct work_struct *work) | ||
| 556 | { | ||
| 557 | struct wm8971_priv *wm8971 = | ||
| 558 | container_of(work, struct wm8971_priv, charge_work.work); | ||
| 559 | |||
| 560 | /* Set to 500k */ | ||
| 561 | regmap_update_bits(wm8971->regmap, WM8971_PWR1, 0x0180, 0x0100); | ||
| 562 | } | ||
| 563 | |||
| 555 | static int wm8971_set_bias_level(struct snd_soc_codec *codec, | 564 | static int wm8971_set_bias_level(struct snd_soc_codec *codec, |
| 556 | enum snd_soc_bias_level level) | 565 | enum snd_soc_bias_level level) |
| 557 | { | 566 | { |
| 567 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); | ||
| 558 | u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | 568 | u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; |
| 559 | 569 | ||
| 560 | switch (level) { | 570 | switch (level) { |
| @@ -563,15 +573,24 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, | |||
| 563 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); | 573 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); |
| 564 | break; | 574 | break; |
| 565 | case SND_SOC_BIAS_PREPARE: | 575 | case SND_SOC_BIAS_PREPARE: |
| 576 | /* Wait until fully charged */ | ||
| 577 | flush_delayed_work(&wm8971->charge_work); | ||
| 566 | break; | 578 | break; |
| 567 | case SND_SOC_BIAS_STANDBY: | 579 | case SND_SOC_BIAS_STANDBY: |
| 568 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 580 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 569 | snd_soc_cache_sync(codec); | 581 | snd_soc_cache_sync(codec); |
| 582 | /* charge output caps - set vmid to 5k for quick power up */ | ||
| 583 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x01c0); | ||
| 584 | queue_delayed_work(system_power_efficient_wq, | ||
| 585 | &wm8971->charge_work, msecs_to_jiffies(1000)); | ||
| 586 | } else { | ||
| 587 | /* mute dac and set vmid to 500k, enable VREF */ | ||
| 588 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); | ||
| 589 | } | ||
| 570 | 590 | ||
| 571 | /* mute dac and set vmid to 500k, enable VREF */ | ||
| 572 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); | ||
| 573 | break; | 591 | break; |
| 574 | case SND_SOC_BIAS_OFF: | 592 | case SND_SOC_BIAS_OFF: |
| 593 | cancel_delayed_work_sync(&wm8971->charge_work); | ||
| 575 | snd_soc_write(codec, WM8971_PWR1, 0x0001); | 594 | snd_soc_write(codec, WM8971_PWR1, 0x0001); |
| 576 | break; | 595 | break; |
| 577 | } | 596 | } |
| @@ -610,58 +629,14 @@ static struct snd_soc_dai_driver wm8971_dai = { | |||
| 610 | .ops = &wm8971_dai_ops, | 629 | .ops = &wm8971_dai_ops, |
| 611 | }; | 630 | }; |
| 612 | 631 | ||
| 613 | static void wm8971_work(struct work_struct *work) | ||
| 614 | { | ||
| 615 | struct snd_soc_dapm_context *dapm = | ||
| 616 | container_of(work, struct snd_soc_dapm_context, | ||
| 617 | delayed_work.work); | ||
| 618 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
| 619 | wm8971_set_bias_level(codec, codec->dapm.bias_level); | ||
| 620 | } | ||
| 621 | |||
| 622 | static int wm8971_suspend(struct snd_soc_codec *codec) | ||
| 623 | { | ||
| 624 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
| 625 | return 0; | ||
| 626 | } | ||
| 627 | |||
| 628 | static int wm8971_resume(struct snd_soc_codec *codec) | ||
| 629 | { | ||
| 630 | u16 reg; | ||
| 631 | |||
| 632 | wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
| 633 | |||
| 634 | /* charge wm8971 caps */ | ||
| 635 | if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { | ||
| 636 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | ||
| 637 | snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); | ||
| 638 | codec->dapm.bias_level = SND_SOC_BIAS_ON; | ||
| 639 | queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work, | ||
| 640 | msecs_to_jiffies(1000)); | ||
| 641 | } | ||
| 642 | |||
| 643 | return 0; | ||
| 644 | } | ||
| 645 | |||
| 646 | static int wm8971_probe(struct snd_soc_codec *codec) | 632 | static int wm8971_probe(struct snd_soc_codec *codec) |
| 647 | { | 633 | { |
| 648 | int ret = 0; | 634 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); |
| 649 | u16 reg; | ||
| 650 | 635 | ||
| 651 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); | 636 | INIT_DELAYED_WORK(&wm8971->charge_work, wm8971_charge_work); |
| 652 | wm8971_workq = create_workqueue("wm8971"); | ||
| 653 | if (wm8971_workq == NULL) | ||
| 654 | return -ENOMEM; | ||
| 655 | 637 | ||
| 656 | wm8971_reset(codec); | 638 | wm8971_reset(codec); |
| 657 | 639 | ||
| 658 | /* charge output caps - set vmid to 5k for quick power up */ | ||
| 659 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | ||
| 660 | snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); | ||
| 661 | codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; | ||
| 662 | queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work, | ||
| 663 | msecs_to_jiffies(1000)); | ||
| 664 | |||
| 665 | /* set the update bits */ | 640 | /* set the update bits */ |
| 666 | snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100); | 641 | snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100); |
| 667 | snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100); | 642 | snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100); |
| @@ -672,26 +647,13 @@ static int wm8971_probe(struct snd_soc_codec *codec) | |||
| 672 | snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100); | 647 | snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100); |
| 673 | snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100); | 648 | snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100); |
| 674 | 649 | ||
| 675 | return ret; | ||
| 676 | } | ||
| 677 | |||
| 678 | |||
| 679 | /* power down chip */ | ||
| 680 | static int wm8971_remove(struct snd_soc_codec *codec) | ||
| 681 | { | ||
| 682 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
| 683 | |||
| 684 | if (wm8971_workq) | ||
| 685 | destroy_workqueue(wm8971_workq); | ||
| 686 | return 0; | 650 | return 0; |
| 687 | } | 651 | } |
| 688 | 652 | ||
| 689 | static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { | 653 | static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { |
| 690 | .probe = wm8971_probe, | 654 | .probe = wm8971_probe, |
| 691 | .remove = wm8971_remove, | ||
| 692 | .suspend = wm8971_suspend, | ||
| 693 | .resume = wm8971_resume, | ||
| 694 | .set_bias_level = wm8971_set_bias_level, | 655 | .set_bias_level = wm8971_set_bias_level, |
| 656 | .suspend_bias_off = true, | ||
| 695 | 657 | ||
| 696 | .controls = wm8971_snd_controls, | 658 | .controls = wm8971_snd_controls, |
| 697 | .num_controls = ARRAY_SIZE(wm8971_snd_controls), | 659 | .num_controls = ARRAY_SIZE(wm8971_snd_controls), |
| @@ -715,7 +677,6 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, | |||
| 715 | const struct i2c_device_id *id) | 677 | const struct i2c_device_id *id) |
| 716 | { | 678 | { |
| 717 | struct wm8971_priv *wm8971; | 679 | struct wm8971_priv *wm8971; |
| 718 | struct regmap *regmap; | ||
| 719 | int ret; | 680 | int ret; |
| 720 | 681 | ||
| 721 | wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv), | 682 | wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv), |
| @@ -723,9 +684,9 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, | |||
| 723 | if (wm8971 == NULL) | 684 | if (wm8971 == NULL) |
| 724 | return -ENOMEM; | 685 | return -ENOMEM; |
| 725 | 686 | ||
| 726 | regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap); | 687 | wm8971->regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap); |
| 727 | if (IS_ERR(regmap)) | 688 | if (IS_ERR(wm8971->regmap)) |
| 728 | return PTR_ERR(regmap); | 689 | return PTR_ERR(wm8971->regmap); |
| 729 | 690 | ||
| 730 | i2c_set_clientdata(i2c, wm8971); | 691 | i2c_set_clientdata(i2c, wm8971); |
| 731 | 692 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 07aa54385ae0..2fb3bf738b5b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -292,6 +292,9 @@ static const struct file_operations codec_reg_fops = { | |||
| 292 | 292 | ||
| 293 | static void soc_init_component_debugfs(struct snd_soc_component *component) | 293 | static void soc_init_component_debugfs(struct snd_soc_component *component) |
| 294 | { | 294 | { |
| 295 | if (!component->card->debugfs_card_root) | ||
| 296 | return; | ||
| 297 | |||
| 295 | if (component->debugfs_prefix) { | 298 | if (component->debugfs_prefix) { |
| 296 | char *name; | 299 | char *name; |
| 297 | 300 | ||
| @@ -455,6 +458,9 @@ static const struct file_operations platform_list_fops = { | |||
| 455 | 458 | ||
| 456 | static void soc_init_card_debugfs(struct snd_soc_card *card) | 459 | static void soc_init_card_debugfs(struct snd_soc_card *card) |
| 457 | { | 460 | { |
| 461 | if (!snd_soc_debugfs_root) | ||
| 462 | return; | ||
| 463 | |||
| 458 | card->debugfs_card_root = debugfs_create_dir(card->name, | 464 | card->debugfs_card_root = debugfs_create_dir(card->name, |
| 459 | snd_soc_debugfs_root); | 465 | snd_soc_debugfs_root); |
| 460 | if (!card->debugfs_card_root) { | 466 | if (!card->debugfs_card_root) { |
| @@ -476,6 +482,34 @@ static void soc_cleanup_card_debugfs(struct snd_soc_card *card) | |||
| 476 | debugfs_remove_recursive(card->debugfs_card_root); | 482 | debugfs_remove_recursive(card->debugfs_card_root); |
| 477 | } | 483 | } |
| 478 | 484 | ||
| 485 | |||
| 486 | static void snd_soc_debugfs_init(void) | ||
| 487 | { | ||
| 488 | snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL); | ||
| 489 | if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) { | ||
| 490 | pr_warn("ASoC: Failed to create debugfs directory\n"); | ||
| 491 | snd_soc_debugfs_root = NULL; | ||
| 492 | return; | ||
| 493 | } | ||
| 494 | |||
| 495 | if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL, | ||
| 496 | &codec_list_fops)) | ||
| 497 | pr_warn("ASoC: Failed to create CODEC list debugfs file\n"); | ||
| 498 | |||
| 499 | if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, | ||
| 500 | &dai_list_fops)) | ||
| 501 | pr_warn("ASoC: Failed to create DAI list debugfs file\n"); | ||
| 502 | |||
| 503 | if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL, | ||
| 504 | &platform_list_fops)) | ||
| 505 | pr_warn("ASoC: Failed to create platform list debugfs file\n"); | ||
| 506 | } | ||
| 507 | |||
| 508 | static void snd_soc_debugfs_exit(void) | ||
| 509 | { | ||
| 510 | debugfs_remove_recursive(snd_soc_debugfs_root); | ||
| 511 | } | ||
| 512 | |||
| 479 | #else | 513 | #else |
| 480 | 514 | ||
| 481 | #define soc_init_codec_debugfs NULL | 515 | #define soc_init_codec_debugfs NULL |
| @@ -497,6 +531,15 @@ static inline void soc_init_card_debugfs(struct snd_soc_card *card) | |||
| 497 | static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card) | 531 | static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card) |
| 498 | { | 532 | { |
| 499 | } | 533 | } |
| 534 | |||
| 535 | static inline void snd_soc_debugfs_init(void) | ||
| 536 | { | ||
| 537 | } | ||
| 538 | |||
| 539 | static inline void snd_soc_debugfs_exit(void) | ||
| 540 | { | ||
| 541 | } | ||
| 542 | |||
| 500 | #endif | 543 | #endif |
| 501 | 544 | ||
| 502 | struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, | 545 | struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, |
| @@ -595,15 +638,9 @@ int snd_soc_suspend(struct device *dev) | |||
| 595 | cpu_dai->driver->suspend(cpu_dai); | 638 | cpu_dai->driver->suspend(cpu_dai); |
| 596 | } | 639 | } |
| 597 | 640 | ||
| 598 | /* close any waiting streams and save state */ | 641 | /* close any waiting streams */ |
| 599 | for (i = 0; i < card->num_rtd; i++) { | 642 | for (i = 0; i < card->num_rtd; i++) |
| 600 | struct snd_soc_dai **codec_dais = card->rtd[i].codec_dais; | ||
| 601 | flush_delayed_work(&card->rtd[i].delayed_work); | 643 | flush_delayed_work(&card->rtd[i].delayed_work); |
| 602 | for (j = 0; j < card->rtd[i].num_codecs; j++) { | ||
| 603 | codec_dais[j]->codec->dapm.suspend_bias_level = | ||
| 604 | codec_dais[j]->codec->dapm.bias_level; | ||
| 605 | } | ||
| 606 | } | ||
| 607 | 644 | ||
| 608 | for (i = 0; i < card->num_rtd; i++) { | 645 | for (i = 0; i < card->num_rtd; i++) { |
| 609 | 646 | ||
| @@ -1322,21 +1359,17 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
| 1322 | } | 1359 | } |
| 1323 | } | 1360 | } |
| 1324 | 1361 | ||
| 1362 | if (dai_link->dai_fmt) | ||
| 1363 | snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); | ||
| 1364 | |||
| 1325 | ret = soc_post_component_init(rtd, dai_link->name); | 1365 | ret = soc_post_component_init(rtd, dai_link->name); |
| 1326 | if (ret) | 1366 | if (ret) |
| 1327 | return ret; | 1367 | return ret; |
| 1328 | 1368 | ||
| 1329 | #ifdef CONFIG_DEBUG_FS | 1369 | #ifdef CONFIG_DEBUG_FS |
| 1330 | /* add DPCM sysfs entries */ | 1370 | /* add DPCM sysfs entries */ |
| 1331 | if (dai_link->dynamic) { | 1371 | if (dai_link->dynamic) |
| 1332 | ret = soc_dpcm_debugfs_add(rtd); | 1372 | soc_dpcm_debugfs_add(rtd); |
| 1333 | if (ret < 0) { | ||
| 1334 | dev_err(rtd->dev, | ||
| 1335 | "ASoC: failed to add dpcm sysfs entries: %d\n", | ||
| 1336 | ret); | ||
| 1337 | return ret; | ||
| 1338 | } | ||
| 1339 | } | ||
| 1340 | #endif | 1373 | #endif |
| 1341 | 1374 | ||
| 1342 | if (cpu_dai->driver->compress_dai) { | 1375 | if (cpu_dai->driver->compress_dai) { |
| @@ -1426,7 +1459,6 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | |||
| 1426 | 1459 | ||
| 1427 | /* unregister the rtd device */ | 1460 | /* unregister the rtd device */ |
| 1428 | if (rtd->dev_registered) { | 1461 | if (rtd->dev_registered) { |
| 1429 | device_remove_file(rtd->dev, &dev_attr_codec_reg); | ||
| 1430 | device_unregister(rtd->dev); | 1462 | device_unregister(rtd->dev); |
| 1431 | rtd->dev_registered = 0; | 1463 | rtd->dev_registered = 0; |
| 1432 | } | 1464 | } |
| @@ -1560,6 +1592,8 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
| 1560 | goto base_error; | 1592 | goto base_error; |
| 1561 | } | 1593 | } |
| 1562 | 1594 | ||
| 1595 | soc_init_card_debugfs(card); | ||
| 1596 | |||
| 1563 | card->dapm.bias_level = SND_SOC_BIAS_OFF; | 1597 | card->dapm.bias_level = SND_SOC_BIAS_OFF; |
| 1564 | card->dapm.dev = card->dev; | 1598 | card->dapm.dev = card->dev; |
| 1565 | card->dapm.card = card; | 1599 | card->dapm.card = card; |
| @@ -1641,12 +1675,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
| 1641 | snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, | 1675 | snd_soc_dapm_add_routes(&card->dapm, card->of_dapm_routes, |
| 1642 | card->num_of_dapm_routes); | 1676 | card->num_of_dapm_routes); |
| 1643 | 1677 | ||
| 1644 | for (i = 0; i < card->num_links; i++) { | ||
| 1645 | if (card->dai_link[i].dai_fmt) | ||
| 1646 | snd_soc_runtime_set_dai_fmt(&card->rtd[i], | ||
| 1647 | card->dai_link[i].dai_fmt); | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), | 1678 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), |
| 1651 | "%s", card->name); | 1679 | "%s", card->name); |
| 1652 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), | 1680 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), |
| @@ -1702,6 +1730,7 @@ card_probe_error: | |||
| 1702 | if (card->remove) | 1730 | if (card->remove) |
| 1703 | card->remove(card); | 1731 | card->remove(card); |
| 1704 | 1732 | ||
| 1733 | soc_cleanup_card_debugfs(card); | ||
| 1705 | snd_card_free(card->snd_card); | 1734 | snd_card_free(card->snd_card); |
| 1706 | 1735 | ||
| 1707 | base_error: | 1736 | base_error: |
| @@ -2380,8 +2409,6 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
| 2380 | 2409 | ||
| 2381 | snd_soc_initialize_card_lists(card); | 2410 | snd_soc_initialize_card_lists(card); |
| 2382 | 2411 | ||
| 2383 | soc_init_card_debugfs(card); | ||
| 2384 | |||
| 2385 | card->rtd = devm_kzalloc(card->dev, | 2412 | card->rtd = devm_kzalloc(card->dev, |
| 2386 | sizeof(struct snd_soc_pcm_runtime) * | 2413 | sizeof(struct snd_soc_pcm_runtime) * |
| 2387 | (card->num_links + card->num_aux_devs), | 2414 | (card->num_links + card->num_aux_devs), |
| @@ -2412,7 +2439,7 @@ int snd_soc_register_card(struct snd_soc_card *card) | |||
| 2412 | 2439 | ||
| 2413 | ret = snd_soc_instantiate_card(card); | 2440 | ret = snd_soc_instantiate_card(card); |
| 2414 | if (ret != 0) | 2441 | if (ret != 0) |
| 2415 | soc_cleanup_card_debugfs(card); | 2442 | return ret; |
| 2416 | 2443 | ||
| 2417 | /* deactivate pins to sleep state */ | 2444 | /* deactivate pins to sleep state */ |
| 2418 | for (i = 0; i < card->num_rtd; i++) { | 2445 | for (i = 0; i < card->num_rtd; i++) { |
| @@ -3595,26 +3622,7 @@ EXPORT_SYMBOL_GPL(snd_soc_of_get_dai_link_codecs); | |||
| 3595 | 3622 | ||
| 3596 | static int __init snd_soc_init(void) | 3623 | static int __init snd_soc_init(void) |
| 3597 | { | 3624 | { |
| 3598 | #ifdef CONFIG_DEBUG_FS | 3625 | snd_soc_debugfs_init(); |
| 3599 | snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL); | ||
| 3600 | if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) { | ||
| 3601 | pr_warn("ASoC: Failed to create debugfs directory\n"); | ||
| 3602 | snd_soc_debugfs_root = NULL; | ||
| 3603 | } | ||
| 3604 | |||
| 3605 | if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL, | ||
| 3606 | &codec_list_fops)) | ||
| 3607 | pr_warn("ASoC: Failed to create CODEC list debugfs file\n"); | ||
| 3608 | |||
| 3609 | if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL, | ||
| 3610 | &dai_list_fops)) | ||
| 3611 | pr_warn("ASoC: Failed to create DAI list debugfs file\n"); | ||
| 3612 | |||
| 3613 | if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL, | ||
| 3614 | &platform_list_fops)) | ||
| 3615 | pr_warn("ASoC: Failed to create platform list debugfs file\n"); | ||
| 3616 | #endif | ||
| 3617 | |||
| 3618 | snd_soc_util_init(); | 3626 | snd_soc_util_init(); |
| 3619 | 3627 | ||
| 3620 | return platform_driver_register(&soc_driver); | 3628 | return platform_driver_register(&soc_driver); |
| @@ -3624,9 +3632,9 @@ module_init(snd_soc_init); | |||
| 3624 | static void __exit snd_soc_exit(void) | 3632 | static void __exit snd_soc_exit(void) |
| 3625 | { | 3633 | { |
| 3626 | snd_soc_util_exit(); | 3634 | snd_soc_util_exit(); |
| 3635 | snd_soc_debugfs_exit(); | ||
| 3627 | 3636 | ||
| 3628 | #ifdef CONFIG_DEBUG_FS | 3637 | #ifdef CONFIG_DEBUG_FS |
| 3629 | debugfs_remove_recursive(snd_soc_debugfs_root); | ||
| 3630 | #endif | 3638 | #endif |
| 3631 | platform_driver_unregister(&soc_driver); | 3639 | platform_driver_unregister(&soc_driver); |
| 3632 | } | 3640 | } |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b6f88202b8c9..1fd2d458824e 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
| @@ -1898,6 +1898,9 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, | |||
| 1898 | { | 1898 | { |
| 1899 | struct dentry *d; | 1899 | struct dentry *d; |
| 1900 | 1900 | ||
| 1901 | if (!parent) | ||
| 1902 | return; | ||
| 1903 | |||
| 1901 | dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); | 1904 | dapm->debugfs_dapm = debugfs_create_dir("dapm", parent); |
| 1902 | 1905 | ||
| 1903 | if (!dapm->debugfs_dapm) { | 1906 | if (!dapm->debugfs_dapm) { |
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6e3781e88f9a..35fe58f4fa86 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c | |||
| @@ -1097,8 +1097,9 @@ static int dpcm_be_connect(struct snd_soc_pcm_runtime *fe, | |||
| 1097 | stream ? "<-" : "->", be->dai_link->name); | 1097 | stream ? "<-" : "->", be->dai_link->name); |
| 1098 | 1098 | ||
| 1099 | #ifdef CONFIG_DEBUG_FS | 1099 | #ifdef CONFIG_DEBUG_FS |
| 1100 | dpcm->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644, | 1100 | if (fe->debugfs_dpcm_root) |
| 1101 | fe->debugfs_dpcm_root, &dpcm->state); | 1101 | dpcm->debugfs_state = debugfs_create_u32(be->dai_link->name, 0644, |
| 1102 | fe->debugfs_dpcm_root, &dpcm->state); | ||
| 1102 | #endif | 1103 | #endif |
| 1103 | return 1; | 1104 | return 1; |
| 1104 | } | 1105 | } |
| @@ -2803,10 +2804,13 @@ static const struct file_operations dpcm_state_fops = { | |||
| 2803 | .llseek = default_llseek, | 2804 | .llseek = default_llseek, |
| 2804 | }; | 2805 | }; |
| 2805 | 2806 | ||
| 2806 | int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) | 2807 | void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) |
| 2807 | { | 2808 | { |
| 2808 | if (!rtd->dai_link) | 2809 | if (!rtd->dai_link) |
| 2809 | return 0; | 2810 | return; |
| 2811 | |||
| 2812 | if (!rtd->card->debugfs_card_root) | ||
| 2813 | return; | ||
| 2810 | 2814 | ||
| 2811 | rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name, | 2815 | rtd->debugfs_dpcm_root = debugfs_create_dir(rtd->dai_link->name, |
| 2812 | rtd->card->debugfs_card_root); | 2816 | rtd->card->debugfs_card_root); |
| @@ -2814,13 +2818,11 @@ int soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) | |||
| 2814 | dev_dbg(rtd->dev, | 2818 | dev_dbg(rtd->dev, |
| 2815 | "ASoC: Failed to create dpcm debugfs directory %s\n", | 2819 | "ASoC: Failed to create dpcm debugfs directory %s\n", |
| 2816 | rtd->dai_link->name); | 2820 | rtd->dai_link->name); |
| 2817 | return -EINVAL; | 2821 | return; |
| 2818 | } | 2822 | } |
| 2819 | 2823 | ||
| 2820 | rtd->debugfs_dpcm_state = debugfs_create_file("state", 0444, | 2824 | rtd->debugfs_dpcm_state = debugfs_create_file("state", 0444, |
| 2821 | rtd->debugfs_dpcm_root, | 2825 | rtd->debugfs_dpcm_root, |
| 2822 | rtd, &dpcm_state_fops); | 2826 | rtd, &dpcm_state_fops); |
| 2823 | |||
| 2824 | return 0; | ||
| 2825 | } | 2827 | } |
| 2826 | #endif | 2828 | #endif |
