From ed5c2f5fd10dda07263f79f338a512c0f49f76f5 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Mon, 15 Aug 2022 10:02:30 +0200 Subject: i2c: Make remove callback return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The value returned by an i2c driver's remove function is mostly ignored. (Only an error message is printed if the value is non-zero that the error is ignored.) So change the prototype of the remove function to return no value. This way driver authors are not tempted to assume that passing an error to the upper layer is a good idea. All drivers are adapted accordingly. There is no intended change of behaviour, all callbacks were prepared to return 0 before. Reviewed-by: Peter Senna Tschudin Reviewed-by: Jeremy Kerr Reviewed-by: Benjamin Mugnier Reviewed-by: Javier Martinez Canillas Reviewed-by: Crt Mori Reviewed-by: Heikki Krogerus Acked-by: Greg Kroah-Hartman Acked-by: Marek Behún # for leds-turris-omnia Acked-by: Andy Shevchenko Reviewed-by: Petr Machata # for mlxsw Reviewed-by: Maximilian Luz # for surface3_power Acked-by: Srinivas Pandruvada # for bmc150-accel-i2c + kxcjk-1013 Reviewed-by: Hans Verkuil # for media/* + staging/media/* Acked-by: Miguel Ojeda # for auxdisplay/ht16k33 + auxdisplay/lcd2s Reviewed-by: Luca Ceresoli # for versaclock5 Reviewed-by: Ajay Gupta # for ucsi_ccg Acked-by: Jonathan Cameron # for iio Acked-by: Peter Rosin # for i2c-mux-*, max9860 Acked-by: Adrien Grassein # for lontium-lt8912b Reviewed-by: Jean Delvare # for hwmon, i2c-core and i2c/muxes Acked-by: Corey Minyard # for IPMI Reviewed-by: Vladimir Oltean Acked-by: Dmitry Torokhov Acked-by: Sebastian Reichel # for drivers/power Acked-by: Krzysztof Hałasa Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfram Sang --- sound/aoa/codecs/onyx.c | 3 +-- sound/aoa/codecs/tas.c | 3 +-- sound/pci/hda/cs35l41_hda_i2c.c | 4 +--- sound/ppc/keywest.c | 6 ++---- sound/soc/codecs/adau1761-i2c.c | 3 +-- sound/soc/codecs/adau1781-i2c.c | 3 +-- sound/soc/codecs/ak4375.c | 4 +--- sound/soc/codecs/ak4458.c | 4 +--- sound/soc/codecs/ak4641.c | 4 +--- sound/soc/codecs/ak5558.c | 4 +--- sound/soc/codecs/cs35l32.c | 4 +--- sound/soc/codecs/cs35l33.c | 4 +--- sound/soc/codecs/cs35l34.c | 4 +--- sound/soc/codecs/cs35l35.c | 4 +--- sound/soc/codecs/cs35l36.c | 4 +--- sound/soc/codecs/cs35l41-i2c.c | 4 +--- sound/soc/codecs/cs35l45-i2c.c | 4 +--- sound/soc/codecs/cs4234.c | 4 +--- sound/soc/codecs/cs4265.c | 4 +--- sound/soc/codecs/cs4270.c | 4 +--- sound/soc/codecs/cs42l42.c | 4 +--- sound/soc/codecs/cs42l51-i2c.c | 4 +--- sound/soc/codecs/cs42l56.c | 3 +-- sound/soc/codecs/cs42xx8-i2c.c | 4 +--- sound/soc/codecs/cs43130.c | 4 +--- sound/soc/codecs/cs4349.c | 4 +--- sound/soc/codecs/cs53l30.c | 4 +--- sound/soc/codecs/cx2072x.c | 3 +-- sound/soc/codecs/max98090.c | 4 +--- sound/soc/codecs/max9860.c | 3 +-- sound/soc/codecs/max98927.c | 4 +--- sound/soc/codecs/mt6660.c | 3 +-- sound/soc/codecs/nau8825.c | 6 ++---- sound/soc/codecs/pcm1789-i2c.c | 4 +--- sound/soc/codecs/pcm3168a-i2c.c | 4 +--- sound/soc/codecs/pcm512x-i2c.c | 3 +-- sound/soc/codecs/rt274.c | 4 +--- sound/soc/codecs/rt286.c | 4 +--- sound/soc/codecs/rt298.c | 4 +--- sound/soc/codecs/rt5616.c | 6 ++---- sound/soc/codecs/rt5631.c | 6 ++---- sound/soc/codecs/rt5645.c | 4 +--- sound/soc/codecs/rt5663.c | 4 +--- sound/soc/codecs/rt5670.c | 4 +--- sound/soc/codecs/rt5677.c | 4 +--- sound/soc/codecs/rt5682-i2c.c | 4 +--- sound/soc/codecs/rt5682s.c | 4 +--- sound/soc/codecs/rt9120.c | 3 +-- sound/soc/codecs/sgtl5000.c | 4 +--- sound/soc/codecs/sta350.c | 6 ++---- sound/soc/codecs/tas2552.c | 3 +-- sound/soc/codecs/tas5086.c | 6 ++---- sound/soc/codecs/tas571x.c | 4 +--- sound/soc/codecs/tas5805m.c | 3 +-- sound/soc/codecs/tas6424.c | 4 +--- sound/soc/codecs/tlv320adc3xxx.c | 3 +-- sound/soc/codecs/tlv320aic32x4-i2c.c | 4 +--- sound/soc/codecs/tlv320aic3x-i2c.c | 4 +--- sound/soc/codecs/tlv320dac33.c | 4 +--- sound/soc/codecs/wm1250-ev1.c | 4 +--- sound/soc/codecs/wm2200.c | 4 +--- sound/soc/codecs/wm5100.c | 4 +--- sound/soc/codecs/wm8804-i2c.c | 3 +-- sound/soc/codecs/wm8900.c | 6 ++---- sound/soc/codecs/wm8903.c | 4 +--- sound/soc/codecs/wm8960.c | 6 ++---- sound/soc/codecs/wm8962.c | 3 +-- sound/soc/codecs/wm8993.c | 4 +--- sound/soc/codecs/wm8996.c | 4 +--- sound/soc/codecs/wm9081.c | 6 ++---- 70 files changed, 79 insertions(+), 204 deletions(-) (limited to 'sound') diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 1abee841cc45..2d0f904aba00 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -1029,7 +1029,7 @@ static int onyx_i2c_probe(struct i2c_client *client, return -ENODEV; } -static int onyx_i2c_remove(struct i2c_client *client) +static void onyx_i2c_remove(struct i2c_client *client) { struct onyx *onyx = i2c_get_clientdata(client); @@ -1037,7 +1037,6 @@ static int onyx_i2c_remove(struct i2c_client *client) of_node_put(onyx->codec.node); kfree(onyx->codec_info); kfree(onyx); - return 0; } static const struct i2c_device_id onyx_i2c_id[] = { diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index ab19a37e2a68..ab89475b7715 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -912,7 +912,7 @@ static int tas_i2c_probe(struct i2c_client *client, return -EINVAL; } -static int tas_i2c_remove(struct i2c_client *client) +static void tas_i2c_remove(struct i2c_client *client) { struct tas *tas = i2c_get_clientdata(client); u8 tmp = TAS_ACR_ANALOG_PDOWN; @@ -925,7 +925,6 @@ static int tas_i2c_remove(struct i2c_client *client) mutex_destroy(&tas->mtx); kfree(tas); - return 0; } static const struct i2c_device_id tas_i2c_id[] = { diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c index 5baacfde4f16..5a6252d9b9e1 100644 --- a/sound/pci/hda/cs35l41_hda_i2c.c +++ b/sound/pci/hda/cs35l41_hda_i2c.c @@ -33,11 +33,9 @@ static int cs35l41_hda_i2c_probe(struct i2c_client *clt, const struct i2c_device devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c)); } -static int cs35l41_hda_i2c_remove(struct i2c_client *clt) +static void cs35l41_hda_i2c_remove(struct i2c_client *clt) { cs35l41_hda_remove(&clt->dev); - - return 0; } static const struct i2c_device_id cs35l41_hda_i2c_id[] = { diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 6e5daae18f9d..80e5108157ef 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -71,14 +71,12 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) return 0; } -static int keywest_remove(struct i2c_client *client) +static void keywest_remove(struct i2c_client *client) { if (! keywest_ctx) - return 0; + return; if (client == keywest_ctx->client) keywest_ctx->client = NULL; - - return 0; } diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c index 0683caf86aea..0cefff49569c 100644 --- a/sound/soc/codecs/adau1761-i2c.c +++ b/sound/soc/codecs/adau1761-i2c.c @@ -30,10 +30,9 @@ static int adau1761_i2c_probe(struct i2c_client *client) id->driver_data, NULL); } -static int adau1761_i2c_remove(struct i2c_client *client) +static void adau1761_i2c_remove(struct i2c_client *client) { adau17x1_remove(&client->dev); - return 0; } static const struct i2c_device_id adau1761_i2c_ids[] = { diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c index e046de0ebcc7..39021b8cfb62 100644 --- a/sound/soc/codecs/adau1781-i2c.c +++ b/sound/soc/codecs/adau1781-i2c.c @@ -30,10 +30,9 @@ static int adau1781_i2c_probe(struct i2c_client *client) id->driver_data, NULL); } -static int adau1781_i2c_remove(struct i2c_client *client) +static void adau1781_i2c_remove(struct i2c_client *client) { adau17x1_remove(&client->dev); - return 0; } static const struct i2c_device_id adau1781_i2c_ids[] = { diff --git a/sound/soc/codecs/ak4375.c b/sound/soc/codecs/ak4375.c index 1ed004ba7cd2..573389e402f8 100644 --- a/sound/soc/codecs/ak4375.c +++ b/sound/soc/codecs/ak4375.c @@ -580,11 +580,9 @@ static int ak4375_i2c_probe(struct i2c_client *i2c) return 0; } -static int ak4375_i2c_remove(struct i2c_client *i2c) +static void ak4375_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static const struct of_device_id ak4375_of_match[] = { diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index ea33cc83c86c..f2d519eb1eec 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -824,11 +824,9 @@ static int ak4458_i2c_probe(struct i2c_client *i2c) return 0; } -static int ak4458_i2c_remove(struct i2c_client *i2c) +static void ak4458_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static const struct of_device_id ak4458_of_match[] = { diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 88851e94b045..0d3ee195b3cc 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -604,7 +604,7 @@ err_out: return ret; } -static int ak4641_i2c_remove(struct i2c_client *i2c) +static void ak4641_i2c_remove(struct i2c_client *i2c) { struct ak4641_platform_data *pdata = i2c->dev.platform_data; @@ -616,8 +616,6 @@ static int ak4641_i2c_remove(struct i2c_client *i2c) if (gpio_is_valid(pdata->gpio_npdn)) gpio_free(pdata->gpio_npdn); } - - return 0; } static const struct i2c_device_id ak4641_i2c_id[] = { diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 887d2c04d647..60abcffe6a0c 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -479,11 +479,9 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) return 0; } -static int ak5558_i2c_remove(struct i2c_client *i2c) +static void ak5558_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static const struct of_device_id ak5558_i2c_dt_ids[] __maybe_unused = { diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 8ff6f66be86f..dc7a58d68076 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -497,14 +497,12 @@ err_supplies: return ret; } -static int cs35l32_i2c_remove(struct i2c_client *i2c_client) +static void cs35l32_i2c_remove(struct i2c_client *i2c_client) { struct cs35l32_private *cs35l32 = i2c_get_clientdata(i2c_client); /* Hold down reset */ gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index 082025fa0370..15e79168d256 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -1250,7 +1250,7 @@ err_enable: return ret; } -static int cs35l33_i2c_remove(struct i2c_client *client) +static void cs35l33_i2c_remove(struct i2c_client *client) { struct cs35l33_private *cs35l33 = i2c_get_clientdata(client); @@ -1259,8 +1259,6 @@ static int cs35l33_i2c_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); regulator_bulk_disable(cs35l33->num_core_supplies, cs35l33->core_supplies); - - return 0; } static const struct of_device_id cs35l33_of_match[] = { diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index 472ac982779b..b3f98023e6a7 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -1128,7 +1128,7 @@ err_regulator: return ret; } -static int cs35l34_i2c_remove(struct i2c_client *client) +static void cs35l34_i2c_remove(struct i2c_client *client) { struct cs35l34_private *cs35l34 = i2c_get_clientdata(client); @@ -1137,8 +1137,6 @@ static int cs35l34_i2c_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); regulator_bulk_disable(cs35l34->num_core_supplies, cs35l34->core_supplies); - - return 0; } static int __maybe_unused cs35l34_runtime_resume(struct device *dev) diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index 714a759dca21..947a440a3a47 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -1627,14 +1627,12 @@ err: return ret; } -static int cs35l35_i2c_remove(struct i2c_client *i2c_client) +static void cs35l35_i2c_remove(struct i2c_client *i2c_client) { struct cs35l35_private *cs35l35 = i2c_get_clientdata(i2c_client); regulator_bulk_disable(cs35l35->num_supplies, cs35l35->supplies); gpiod_set_value_cansleep(cs35l35->reset_gpio, 0); - - return 0; } static const struct of_device_id cs35l35_of_match[] = { diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index 4dc13e6f4874..31ae752e242f 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -1910,7 +1910,7 @@ err_disable_regs: return ret; } -static int cs35l36_i2c_remove(struct i2c_client *client) +static void cs35l36_i2c_remove(struct i2c_client *client) { struct cs35l36_private *cs35l36 = i2c_get_clientdata(client); @@ -1924,8 +1924,6 @@ static int cs35l36_i2c_remove(struct i2c_client *client) gpiod_set_value_cansleep(cs35l36->reset_gpio, 0); regulator_bulk_disable(cs35l36->num_supplies, cs35l36->supplies); - - return 0; } static const struct of_device_id cs35l36_of_match[] = { {.compatible = "cirrus,cs35l36"}, diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c index 37c703c08fd5..3676b596f60b 100644 --- a/sound/soc/codecs/cs35l41-i2c.c +++ b/sound/soc/codecs/cs35l41-i2c.c @@ -56,13 +56,11 @@ static int cs35l41_i2c_probe(struct i2c_client *client) return cs35l41_probe(cs35l41, hw_cfg); } -static int cs35l41_i2c_remove(struct i2c_client *client) +static void cs35l41_i2c_remove(struct i2c_client *client) { struct cs35l41_private *cs35l41 = i2c_get_clientdata(client); cs35l41_remove(cs35l41); - - return 0; } #ifdef CONFIG_OF diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 06c2ddffb9c5..39d28641429e 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -36,13 +36,11 @@ static int cs35l45_i2c_probe(struct i2c_client *client) return cs35l45_probe(cs35l45); } -static int cs35l45_i2c_remove(struct i2c_client *client) +static void cs35l45_i2c_remove(struct i2c_client *client) { struct cs35l45_private *cs35l45 = i2c_get_clientdata(client); cs35l45_remove(cs35l45); - - return 0; } static const struct of_device_id cs35l45_of_match[] = { diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c index b49a3cf21ebe..dee1a6662c2e 100644 --- a/sound/soc/codecs/cs4234.c +++ b/sound/soc/codecs/cs4234.c @@ -850,7 +850,7 @@ fail_shutdown: return ret; } -static int cs4234_i2c_remove(struct i2c_client *i2c_client) +static void cs4234_i2c_remove(struct i2c_client *i2c_client) { struct cs4234 *cs4234 = i2c_get_clientdata(i2c_client); struct device *dev = &i2c_client->dev; @@ -858,8 +858,6 @@ static int cs4234_i2c_remove(struct i2c_client *i2c_client) snd_soc_unregister_component(dev); pm_runtime_disable(dev); cs4234_shutdown(cs4234); - - return 0; } static int __maybe_unused cs4234_runtime_resume(struct device *dev) diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 76c19802d5fe..3573363b7e31 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -623,14 +623,12 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client) ARRAY_SIZE(cs4265_dai)); } -static int cs4265_i2c_remove(struct i2c_client *i2c) +static void cs4265_i2c_remove(struct i2c_client *i2c) { struct cs4265_private *cs4265 = i2c_get_clientdata(i2c); if (cs4265->reset_gpio) gpiod_set_value_cansleep(cs4265->reset_gpio, 0); - - return 0; } static const struct of_device_id cs4265_of_match[] = { diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index ba67e43edf35..1b640d8232ba 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -650,13 +650,11 @@ static const struct regmap_config cs4270_regmap = { * This function puts the chip into low power mode when the i2c device * is removed. */ -static int cs4270_i2c_remove(struct i2c_client *i2c_client) +static void cs4270_i2c_remove(struct i2c_client *i2c_client) { struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); gpiod_set_value_cansleep(cs4270->reset_gpio, 0); - - return 0; } /** diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index d545a593a251..2461894de620 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -2340,7 +2340,7 @@ err_disable_noreset: return ret; } -static int cs42l42_i2c_remove(struct i2c_client *i2c_client) +static void cs42l42_i2c_remove(struct i2c_client *i2c_client) { struct cs42l42_private *cs42l42 = i2c_get_clientdata(i2c_client); @@ -2357,8 +2357,6 @@ static int cs42l42_i2c_remove(struct i2c_client *i2c_client) gpiod_set_value_cansleep(cs42l42->reset_gpio, 0); regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies); - - return 0; } static const struct dev_pm_ops cs42l42_pm_ops = { diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index 3613fb12d623..85238339fbca 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -28,11 +28,9 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c) return cs42l51_probe(&i2c->dev, devm_regmap_init_i2c(i2c, &config)); } -static int cs42l51_i2c_remove(struct i2c_client *i2c) +static void cs42l51_i2c_remove(struct i2c_client *i2c) { cs42l51_remove(&i2c->dev); - - return 0; } static const struct dev_pm_ops cs42l51_pm_ops = { diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index 03e2540a0ba1..26066682c983 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1320,13 +1320,12 @@ err_enable: return ret; } -static int cs42l56_i2c_remove(struct i2c_client *client) +static void cs42l56_i2c_remove(struct i2c_client *client) { struct cs42l56_private *cs42l56 = i2c_get_clientdata(client); regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies), cs42l56->supplies); - return 0; } static const struct of_device_id cs42l56_of_match[] = { diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c index cb06a06d48b0..bd80e9fc907f 100644 --- a/sound/soc/codecs/cs42xx8-i2c.c +++ b/sound/soc/codecs/cs42xx8-i2c.c @@ -30,11 +30,9 @@ static int cs42xx8_i2c_probe(struct i2c_client *i2c) return 0; } -static int cs42xx8_i2c_remove(struct i2c_client *i2c) +static void cs42xx8_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static struct i2c_device_id cs42xx8_i2c_id[] = { diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index ca4d47cc9c91..411b95143a2e 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -2583,7 +2583,7 @@ err_supplies: return ret; } -static int cs43130_i2c_remove(struct i2c_client *client) +static void cs43130_i2c_remove(struct i2c_client *client) { struct cs43130_private *cs43130 = i2c_get_clientdata(client); @@ -2610,8 +2610,6 @@ static int cs43130_i2c_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies); - - return 0; } static int __maybe_unused cs43130_runtime_suspend(struct device *dev) diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index f7c5c2fd4304..ba94ffd0a7e4 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -305,14 +305,12 @@ static int cs4349_i2c_probe(struct i2c_client *client) &cs4349_dai, 1); } -static int cs4349_i2c_remove(struct i2c_client *client) +static void cs4349_i2c_remove(struct i2c_client *client) { struct cs4349_private *cs4349 = i2c_get_clientdata(client); /* Hold down reset */ gpiod_set_value_cansleep(cs4349->reset_gpio, 0); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 8796d8e84b7a..69db0013d243 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -1043,7 +1043,7 @@ error_supplies: return ret; } -static int cs53l30_i2c_remove(struct i2c_client *client) +static void cs53l30_i2c_remove(struct i2c_client *client) { struct cs53l30_private *cs53l30 = i2c_get_clientdata(client); @@ -1052,8 +1052,6 @@ static int cs53l30_i2c_remove(struct i2c_client *client) regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies), cs53l30->supplies); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index b6667e8a6099..5deceaa89282 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1673,10 +1673,9 @@ static int cx2072x_i2c_probe(struct i2c_client *i2c) return 0; } -static int cx2072x_i2c_remove(struct i2c_client *i2c) +static void cx2072x_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - return 0; } static const struct i2c_device_id cx2072x_i2c_id[] = { diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 142083b13ac3..06ed2a938108 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2615,11 +2615,9 @@ static void max98090_i2c_shutdown(struct i2c_client *i2c) msleep(40); } -static int max98090_i2c_remove(struct i2c_client *client) +static void max98090_i2c_remove(struct i2c_client *client) { max98090_i2c_shutdown(client); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 771b3dcd6cc3..9611ab1e79e5 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -701,14 +701,13 @@ err_regulator: return ret; } -static int max9860_remove(struct i2c_client *i2c) +static void max9860_remove(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct max9860_priv *max9860 = dev_get_drvdata(dev); pm_runtime_disable(dev); regulator_disable(max9860->dvddio); - return 0; } static const struct i2c_device_id max9860_i2c_id[] = { diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 9cce7c0f0142..331d3e1d735c 100644 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -934,15 +934,13 @@ static int max98927_i2c_probe(struct i2c_client *i2c) return ret; } -static int max98927_i2c_remove(struct i2c_client *i2c) +static void max98927_i2c_remove(struct i2c_client *i2c) { struct max98927_priv *max98927 = i2c_get_clientdata(i2c); if (max98927->reset_gpio) { gpiod_set_value_cansleep(max98927->reset_gpio, 1); } - - return 0; } static const struct i2c_device_id max98927_i2c_id[] = { diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index ba11555796ad..4971cd0b90f8 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -516,14 +516,13 @@ probe_fail: return ret; } -static int mt6660_i2c_remove(struct i2c_client *client) +static void mt6660_i2c_remove(struct i2c_client *client) { struct mt6660_chip *chip = i2c_get_clientdata(client); pm_runtime_disable(chip->dev); pm_runtime_set_suspended(chip->dev); mutex_destroy(&chip->io_lock); - return 0; } static int __maybe_unused mt6660_i2c_runtime_suspend(struct device *dev) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 54ef7b0fa878..87545021cd22 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2668,10 +2668,8 @@ static int nau8825_i2c_probe(struct i2c_client *i2c) &nau8825_dai, 1); } -static int nau8825_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void nau8825_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id nau8825_i2c_ids[] = { { "nau8825", 0 }, diff --git a/sound/soc/codecs/pcm1789-i2c.c b/sound/soc/codecs/pcm1789-i2c.c index 1d2f7480a6e4..fafe0dcbe4ea 100644 --- a/sound/soc/codecs/pcm1789-i2c.c +++ b/sound/soc/codecs/pcm1789-i2c.c @@ -27,11 +27,9 @@ static int pcm1789_i2c_probe(struct i2c_client *client) return pcm1789_common_init(&client->dev, regmap); } -static int pcm1789_i2c_remove(struct i2c_client *client) +static void pcm1789_i2c_remove(struct i2c_client *client) { pcm1789_common_exit(&client->dev); - - return 0; } #ifdef CONFIG_OF diff --git a/sound/soc/codecs/pcm3168a-i2c.c b/sound/soc/codecs/pcm3168a-i2c.c index c0fa0dc80e8f..a0eec82e9872 100644 --- a/sound/soc/codecs/pcm3168a-i2c.c +++ b/sound/soc/codecs/pcm3168a-i2c.c @@ -26,11 +26,9 @@ static int pcm3168a_i2c_probe(struct i2c_client *i2c) return pcm3168a_probe(&i2c->dev, regmap); } -static int pcm3168a_i2c_remove(struct i2c_client *i2c) +static void pcm3168a_i2c_remove(struct i2c_client *i2c) { pcm3168a_remove(&i2c->dev); - - return 0; } static const struct i2c_device_id pcm3168a_i2c_id[] = { diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c index 81754e141a55..9dfbbe8f4a0b 100644 --- a/sound/soc/codecs/pcm512x-i2c.c +++ b/sound/soc/codecs/pcm512x-i2c.c @@ -29,10 +29,9 @@ static int pcm512x_i2c_probe(struct i2c_client *i2c) return pcm512x_probe(&i2c->dev, regmap); } -static int pcm512x_i2c_remove(struct i2c_client *i2c) +static void pcm512x_i2c_remove(struct i2c_client *i2c) { pcm512x_remove(&i2c->dev); - return 0; } static const struct i2c_device_id pcm512x_i2c_id[] = { diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index f2c50b11e4d0..4667bf7561b1 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -1204,14 +1204,12 @@ static int rt274_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt274_i2c_remove(struct i2c_client *i2c) +static void rt274_i2c_remove(struct i2c_client *i2c) { struct rt274_priv *rt274 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, rt274); - - return 0; } diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index c4f7c4c2d793..ceb56647e369 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1249,14 +1249,12 @@ static int rt286_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt286_i2c_remove(struct i2c_client *i2c) +static void rt286_i2c_remove(struct i2c_client *i2c) { struct rt286_priv *rt286 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, rt286); - - return 0; } diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index b0b53d4f07df..a2ce52dafea8 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1290,14 +1290,12 @@ static int rt298_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt298_i2c_remove(struct i2c_client *i2c) +static void rt298_i2c_remove(struct i2c_client *i2c) { struct rt298_priv *rt298 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, rt298); - - return 0; } diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index 970d6c4a358e..948abde10463 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1388,10 +1388,8 @@ static int rt5616_i2c_probe(struct i2c_client *i2c) rt5616_dai, ARRAY_SIZE(rt5616_dai)); } -static int rt5616_i2c_remove(struct i2c_client *i2c) -{ - return 0; -} +static void rt5616_i2c_remove(struct i2c_client *i2c) +{} static void rt5616_i2c_shutdown(struct i2c_client *client) { diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 957f6b19beec..55c232413e2b 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1720,10 +1720,8 @@ static int rt5631_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt5631_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void rt5631_i2c_remove(struct i2c_client *client) +{} static struct i2c_driver rt5631_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 8635bc6567dc..620ecbfa4a7a 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -4145,7 +4145,7 @@ err_enable: return ret; } -static int rt5645_i2c_remove(struct i2c_client *i2c) +static void rt5645_i2c_remove(struct i2c_client *i2c) { struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c); @@ -4162,8 +4162,6 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) cancel_delayed_work_sync(&rt5645->rcclock_work); regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); - - return 0; } static void rt5645_i2c_shutdown(struct i2c_client *i2c) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index ca981b374b0c..f73751dbde30 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -3710,7 +3710,7 @@ err_enable: return ret; } -static int rt5663_i2c_remove(struct i2c_client *i2c) +static void rt5663_i2c_remove(struct i2c_client *i2c) { struct rt5663_priv *rt5663 = i2c_get_clientdata(i2c); @@ -3718,8 +3718,6 @@ static int rt5663_i2c_remove(struct i2c_client *i2c) free_irq(i2c->irq, rt5663); regulator_bulk_disable(ARRAY_SIZE(rt5663->supplies), rt5663->supplies); - - return 0; } static void rt5663_i2c_shutdown(struct i2c_client *client) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 60dbfa2a54f1..ebac6caeb40a 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -3320,11 +3320,9 @@ err: return ret; } -static int rt5670_i2c_remove(struct i2c_client *i2c) +static void rt5670_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static struct i2c_driver rt5670_i2c_driver = { diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 31a2dd0aafb6..c26395f42d8e 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5693,11 +5693,9 @@ static int rt5677_i2c_probe(struct i2c_client *i2c) rt5677_dai, ARRAY_SIZE(rt5677_dai)); } -static int rt5677_i2c_remove(struct i2c_client *i2c) +static void rt5677_i2c_remove(struct i2c_client *i2c) { rt5677_free_gpio(i2c); - - return 0; } static struct i2c_driver rt5677_i2c_driver = { diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 3f72f6093436..2935c1bb81f3 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -302,11 +302,9 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) rt5682_reset(rt5682); } -static int rt5682_i2c_remove(struct i2c_client *client) +static void rt5682_i2c_remove(struct i2c_client *client) { rt5682_i2c_shutdown(client); - - return 0; } static const struct of_device_id rt5682_of_match[] = { diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index eb47e7cd485a..ce6932a26403 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -3194,11 +3194,9 @@ static void rt5682s_i2c_shutdown(struct i2c_client *client) rt5682s_reset(rt5682s); } -static int rt5682s_i2c_remove(struct i2c_client *client) +static void rt5682s_i2c_remove(struct i2c_client *client) { rt5682s_i2c_shutdown(client); - - return 0; } static const struct of_device_id rt5682s_of_match[] = { diff --git a/sound/soc/codecs/rt9120.c b/sound/soc/codecs/rt9120.c index da495bdc8415..644300e88b4c 100644 --- a/sound/soc/codecs/rt9120.c +++ b/sound/soc/codecs/rt9120.c @@ -572,11 +572,10 @@ static int rt9120_probe(struct i2c_client *i2c) &rt9120_dai, 1); } -static int rt9120_remove(struct i2c_client *i2c) +static void rt9120_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); pm_runtime_set_suspended(&i2c->dev); - return 0; } static int __maybe_unused rt9120_runtime_suspend(struct device *dev) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3fafd9fc5cfd..4b2135eba74d 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1790,7 +1790,7 @@ disable_regs: return ret; } -static int sgtl5000_i2c_remove(struct i2c_client *client) +static void sgtl5000_i2c_remove(struct i2c_client *client) { struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client); @@ -1800,8 +1800,6 @@ static int sgtl5000_i2c_remove(struct i2c_client *client) clk_disable_unprepare(sgtl5000->mclk); regulator_bulk_disable(sgtl5000->num_supplies, sgtl5000->supplies); regulator_bulk_free(sgtl5000->num_supplies, sgtl5000->supplies); - - return 0; } static void sgtl5000_i2c_shutdown(struct i2c_client *client) diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 7b2c5b57d5d4..9ed13aeb3cbd 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1242,10 +1242,8 @@ static int sta350_i2c_probe(struct i2c_client *i2c) return ret; } -static int sta350_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void sta350_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id sta350_i2c_id[] = { { "sta350", 0 }, diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 8bd667da8767..59a4ea5f6e30 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -736,10 +736,9 @@ static int tas2552_probe(struct i2c_client *client) return ret; } -static int tas2552_i2c_remove(struct i2c_client *client) +static void tas2552_i2c_remove(struct i2c_client *client) { pm_runtime_disable(&client->dev); - return 0; } static const struct i2c_device_id tas2552_id[] = { diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index a864984225bc..22143cc5afa7 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -981,10 +981,8 @@ static int tas5086_i2c_probe(struct i2c_client *i2c) return ret; } -static int tas5086_i2c_remove(struct i2c_client *i2c) -{ - return 0; -} +static void tas5086_i2c_remove(struct i2c_client *i2c) +{} static struct i2c_driver tas5086_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 4e7f20db57c4..84ec1b527646 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -884,13 +884,11 @@ disable_regs: return ret; } -static int tas571x_i2c_remove(struct i2c_client *client) +static void tas571x_i2c_remove(struct i2c_client *client) { struct tas571x_private *priv = i2c_get_clientdata(client); regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies); - - return 0; } static const struct of_device_id tas571x_of_match[] __maybe_unused = { diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c index b1bb614534f7..beb4ec629a03 100644 --- a/sound/soc/codecs/tas5805m.c +++ b/sound/soc/codecs/tas5805m.c @@ -522,7 +522,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) return 0; } -static int tas5805m_i2c_remove(struct i2c_client *i2c) +static void tas5805m_i2c_remove(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); @@ -531,7 +531,6 @@ static int tas5805m_i2c_remove(struct i2c_client *i2c) gpiod_set_value(tas5805m->gpio_pdn_n, 0); usleep_range(10000, 15000); regulator_disable(tas5805m->pvdd); - return 0; } static const struct i2c_device_id tas5805m_i2c_id[] = { diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index 63d2983c3fcf..f8ff69fa2549 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -774,7 +774,7 @@ disable_regs: return ret; } -static int tas6424_i2c_remove(struct i2c_client *client) +static void tas6424_i2c_remove(struct i2c_client *client) { struct device *dev = &client->dev; struct tas6424_data *tas6424 = dev_get_drvdata(dev); @@ -790,8 +790,6 @@ static int tas6424_i2c_remove(struct i2c_client *client) tas6424->supplies); if (ret < 0) dev_err(dev, "unable to disable supplies: %d\n", ret); - - return 0; } static const struct i2c_device_id tas6424_i2c_ids[] = { diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c index 748998e48af9..baab320ef988 100644 --- a/sound/soc/codecs/tlv320adc3xxx.c +++ b/sound/soc/codecs/tlv320adc3xxx.c @@ -1426,7 +1426,7 @@ err_unprepare_mclk: return ret; } -static int __exit adc3xxx_i2c_remove(struct i2c_client *client) +static void __exit adc3xxx_i2c_remove(struct i2c_client *client) { struct adc3xxx *adc3xxx = i2c_get_clientdata(client); @@ -1434,7 +1434,6 @@ static int __exit adc3xxx_i2c_remove(struct i2c_client *client) clk_disable_unprepare(adc3xxx->mclk); adc3xxx_free_gpio(adc3xxx); snd_soc_unregister_component(&client->dev); - return 0; } static const struct of_device_id tlv320adc3xxx_of_match[] = { diff --git a/sound/soc/codecs/tlv320aic32x4-i2c.c b/sound/soc/codecs/tlv320aic32x4-i2c.c index 0645239901b1..d1e543ca3521 100644 --- a/sound/soc/codecs/tlv320aic32x4-i2c.c +++ b/sound/soc/codecs/tlv320aic32x4-i2c.c @@ -45,11 +45,9 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c) return aic32x4_probe(&i2c->dev, regmap); } -static int aic32x4_i2c_remove(struct i2c_client *i2c) +static void aic32x4_i2c_remove(struct i2c_client *i2c) { aic32x4_remove(&i2c->dev); - - return 0; } static const struct i2c_device_id aic32x4_i2c_id[] = { diff --git a/sound/soc/codecs/tlv320aic3x-i2c.c b/sound/soc/codecs/tlv320aic3x-i2c.c index 7bd9ce08bb7b..d7e94d564dbf 100644 --- a/sound/soc/codecs/tlv320aic3x-i2c.c +++ b/sound/soc/codecs/tlv320aic3x-i2c.c @@ -41,11 +41,9 @@ static int aic3x_i2c_probe(struct i2c_client *i2c) return aic3x_probe(&i2c->dev, regmap, id->driver_data); } -static int aic3x_i2c_remove(struct i2c_client *i2c) +static void aic3x_i2c_remove(struct i2c_client *i2c) { aic3x_remove(&i2c->dev); - - return 0; } static const struct of_device_id aic3x_of_id[] = { diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 17ae3b1d96fb..16ce3ef1134b 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1536,7 +1536,7 @@ err_gpio: return ret; } -static int dac33_i2c_remove(struct i2c_client *client) +static void dac33_i2c_remove(struct i2c_client *client) { struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client); @@ -1545,8 +1545,6 @@ static int dac33_i2c_remove(struct i2c_client *client) if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); - - return 0; } static const struct i2c_device_id tlv320dac33_i2c_id[] = { diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 98343626078b..0064a607ec68 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -228,11 +228,9 @@ static int wm1250_ev1_probe(struct i2c_client *i2c) return 0; } -static int wm1250_ev1_remove(struct i2c_client *i2c) +static void wm1250_ev1_remove(struct i2c_client *i2c) { wm1250_ev1_free(i2c); - - return 0; } static const struct i2c_device_id wm1250_ev1_i2c_id[] = { diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 7b4e162a298c..0a65afa44a59 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2414,7 +2414,7 @@ err_enable: return ret; } -static int wm2200_i2c_remove(struct i2c_client *i2c) +static void wm2200_i2c_remove(struct i2c_client *i2c) { struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c); @@ -2427,8 +2427,6 @@ static int wm2200_i2c_remove(struct i2c_client *i2c) gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), wm2200->core_supplies); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 35a85ce6b464..3b09d4a1684f 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2635,7 +2635,7 @@ err: return ret; } -static int wm5100_i2c_remove(struct i2c_client *i2c) +static void wm5100_i2c_remove(struct i2c_client *i2c) { struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); @@ -2651,8 +2651,6 @@ static int wm5100_i2c_remove(struct i2c_client *i2c) gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); gpio_free(wm5100->pdata.ldo_ena); } - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c index 04dc9fb5afb4..3ce1a39d76eb 100644 --- a/sound/soc/codecs/wm8804-i2c.c +++ b/sound/soc/codecs/wm8804-i2c.c @@ -25,10 +25,9 @@ static int wm8804_i2c_probe(struct i2c_client *i2c) return wm8804_probe(&i2c->dev, regmap); } -static int wm8804_i2c_remove(struct i2c_client *i2c) +static void wm8804_i2c_remove(struct i2c_client *i2c) { wm8804_remove(&i2c->dev); - return 0; } static const struct i2c_device_id wm8804_i2c_id[] = { diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index d6420df3505d..03bbd85ebdf4 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1282,10 +1282,8 @@ static int wm8900_i2c_probe(struct i2c_client *i2c) return ret; } -static int wm8900_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void wm8900_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id wm8900_i2c_id[] = { { "wm8900", 0 }, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 54e0a7628cd5..41346e5ec5ad 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2182,7 +2182,7 @@ err: return ret; } -static int wm8903_i2c_remove(struct i2c_client *client) +static void wm8903_i2c_remove(struct i2c_client *client) { struct wm8903_priv *wm8903 = i2c_get_clientdata(client); @@ -2191,8 +2191,6 @@ static int wm8903_i2c_remove(struct i2c_client *client) if (client->irq) free_irq(client->irq, wm8903); wm8903_free_gpio(wm8903); - - return 0; } static const struct of_device_id wm8903_of_match[] = { diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 37956516d997..0d167238a369 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1486,10 +1486,8 @@ static int wm8960_i2c_probe(struct i2c_client *i2c) return ret; } -static int wm8960_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void wm8960_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id wm8960_i2c_id[] = { { "wm8960", 0 }, diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 398c448ea854..81049664387e 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3778,10 +3778,9 @@ err: return ret; } -static int wm8962_i2c_remove(struct i2c_client *client) +static void wm8962_i2c_remove(struct i2c_client *client) { pm_runtime_disable(&client->dev); - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 8db98b5a06bf..22a47acbc6d1 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1722,15 +1722,13 @@ err_enable: return ret; } -static int wm8993_i2c_remove(struct i2c_client *i2c) +static void wm8993_i2c_remove(struct i2c_client *i2c) { struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, wm8993); regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - - return 0; } static const struct i2c_device_id wm8993_i2c_id[] = { diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 17f307a31046..b52ed89d631a 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -3065,7 +3065,7 @@ err: return ret; } -static int wm8996_i2c_remove(struct i2c_client *client) +static void wm8996_i2c_remove(struct i2c_client *client) { struct wm8996_priv *wm8996 = i2c_get_clientdata(client); @@ -3074,8 +3074,6 @@ static int wm8996_i2c_remove(struct i2c_client *client) gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); gpio_free(wm8996->pdata.ldo_ena); } - - return 0; } static const struct i2c_device_id wm8996_i2c_id[] = { diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index d5151877d0fa..513ec0ba81bb 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1356,10 +1356,8 @@ static int wm9081_i2c_probe(struct i2c_client *i2c) return 0; } -static int wm9081_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void wm9081_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id wm9081_i2c_id[] = { { "wm9081", 0 }, -- cgit v1.2.3 From e4746d94d00c52918461bc169e009b6784a38e21 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 16 Aug 2022 13:17:22 +0200 Subject: ASoC: Intel: Skylake: Introduce HDA codec init and exit routines Preliminary step in making snd_hda_codec_device_init() the only constructor for struct hda_codec instances. To do that, existing usage of hdac_ext equivalents has to be dropped. Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Cezary Rojewski Acked-by: Mark Brown Link: https://lore.kernel.org/r/20220816111727.3218543-2-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/soc/intel/skylake/skl.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index aeca58246fc7..33b0ed6b0534 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -689,6 +689,35 @@ static void load_codec_module(struct hda_codec *codec) #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ +static void skl_codec_device_exit(struct device *dev) +{ + snd_hdac_device_exit(dev_to_hdac_dev(dev)); +} + +static __maybe_unused struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr) +{ + struct hda_codec *codec; + int ret; + + codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr); + if (IS_ERR(codec)) { + dev_err(bus->dev, "device init failed for hdac device\n"); + return codec; + } + + codec->core.type = HDA_DEV_ASOC; + codec->core.dev.release = skl_codec_device_exit; + + ret = snd_hdac_device_register(&codec->core); + if (ret) { + dev_err(bus->dev, "failed to register hdac device\n"); + snd_hdac_device_exit(&codec->core); + return ERR_PTR(ret); + } + + return codec; +} + /* * Probe the given codec address */ -- cgit v1.2.3 From 829c67319806009abfe3b0b82b3b8b153a2c5e32 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 16 Aug 2022 13:17:23 +0200 Subject: ASoC: SOF: Intel: Introduce HDA codec init and exit routines Preliminary step in making snd_hda_codec_device_init() the only constructor for struct hda_codec instances. To do that, existing usage of hdac_ext equivalents has to be dropped. Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Cezary Rojewski Acked-by: Mark Brown Link: https://lore.kernel.org/r/20220816111727.3218543-3-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/soc/sof/intel/hda-codec.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 2f3f4a733d9e..4c128ba02340 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -109,6 +109,36 @@ EXPORT_SYMBOL_NS(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC); #define is_generic_config(x) 0 #endif +static void hda_codec_device_exit(struct device *dev) +{ + snd_hdac_device_exit(dev_to_hdac_dev(dev)); +} + +static __maybe_unused struct hda_codec * +hda_codec_device_init(struct hdac_bus *bus, int addr, int type) +{ + struct hda_codec *codec; + int ret; + + codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr); + if (IS_ERR(codec)) { + dev_err(bus->dev, "device init failed for hdac device\n"); + return codec; + } + + codec->core.type = type; + codec->core.dev.release = hda_codec_device_exit; + + ret = snd_hdac_device_register(&codec->core); + if (ret) { + dev_err(bus->dev, "failed to register hdac device\n"); + snd_hdac_device_exit(&codec->core); + return ERR_PTR(ret); + } + + return codec; +} + /* probe individual codec */ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, bool hda_codec_use_common_hdmi) -- cgit v1.2.3 From 3fd63658caed9494cca1d4789a66d3d2def2a0ab Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 16 Aug 2022 13:17:24 +0200 Subject: ASoC: Intel: Drop hdac_ext usage for codec device creation To make snd_hda_codec_device_init() the only constructor for struct hda_codec instances remaining tasks are: 1) no struct may wrap struct hda_codec as its base type 2) bus drivers (skylake and sof) which are the current hdac_ext users need to be adjusted to make use of newly added codec init and exit routines instead 3) as bus drivers (skylake and sof) are to be responsible for creating codec device and assigning it to hdac_hda_priv->codec, hdac_hda_dev_probe() has to be freed of that job To keep git bisect happy, all of these in made in one-go. Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Cezary Rojewski Acked-by: Mark Brown Link: https://lore.kernel.org/r/20220816111727.3218543-4-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/soc/codecs/hdac_hda.c | 26 ++++++++++--------------- sound/soc/codecs/hdac_hda.h | 2 +- sound/soc/intel/boards/hda_dsp_common.c | 2 +- sound/soc/intel/boards/skl_hda_dsp_generic.c | 2 +- sound/soc/intel/skylake/skl.c | 26 +++++++++++-------------- sound/soc/sof/intel/hda-codec.c | 29 ++++++++++++---------------- 6 files changed, 36 insertions(+), 51 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 8debcee59224..77df4c5b274a 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -246,7 +246,7 @@ static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream, return -EINVAL; hda_stream = &pcm->stream[substream->stream]; - snd_hda_codec_cleanup(&hda_pvt->codec, hda_stream, substream); + snd_hda_codec_cleanup(hda_pvt->codec, hda_stream, substream); return 0; } @@ -264,7 +264,7 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, int ret = 0; hda_pvt = snd_soc_component_get_drvdata(component); - hdev = &hda_pvt->codec.core; + hdev = &hda_pvt->codec->core; pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); if (!pcm) return -EINVAL; @@ -274,7 +274,7 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, stream = hda_pvt->pcm[dai->id].stream_tag[substream->stream]; format_val = hda_pvt->pcm[dai->id].format_val[substream->stream]; - ret = snd_hda_codec_prepare(&hda_pvt->codec, hda_stream, + ret = snd_hda_codec_prepare(hda_pvt->codec, hda_stream, stream, format_val, substream); if (ret < 0) dev_err(&hdev->dev, "codec prepare failed %d\n", ret); @@ -299,7 +299,7 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, hda_stream = &pcm->stream[substream->stream]; - return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream); + return hda_stream->ops.open(hda_stream, hda_pvt->codec, substream); } static void hdac_hda_dai_close(struct snd_pcm_substream *substream, @@ -317,7 +317,7 @@ static void hdac_hda_dai_close(struct snd_pcm_substream *substream, hda_stream = &pcm->stream[substream->stream]; - hda_stream->ops.close(hda_stream, &hda_pvt->codec, substream); + hda_stream->ops.close(hda_stream, hda_pvt->codec, substream); snd_hda_codec_pcm_put(pcm); } @@ -325,7 +325,7 @@ static void hdac_hda_dai_close(struct snd_pcm_substream *substream, static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt, struct snd_soc_dai *dai) { - struct hda_codec *hcodec = &hda_pvt->codec; + struct hda_codec *hcodec = hda_pvt->codec; struct hda_pcm *cpcm; const char *pcm_name; @@ -394,8 +394,8 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - struct hdac_device *hdev = &hda_pvt->codec.core; - struct hda_codec *hcodec = &hda_pvt->codec; + struct hdac_device *hdev = &hda_pvt->codec->core; + struct hda_codec *hcodec = hda_pvt->codec; struct hdac_ext_link *hlink; hda_codec_patch_t patch; int ret; @@ -515,8 +515,8 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) { struct hdac_hda_priv *hda_pvt = snd_soc_component_get_drvdata(component); - struct hdac_device *hdev = &hda_pvt->codec.core; - struct hda_codec *codec = &hda_pvt->codec; + struct hdac_device *hdev = &hda_pvt->codec->core; + struct hda_codec *codec = hda_pvt->codec; struct hdac_ext_link *hlink = NULL; hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); @@ -584,7 +584,6 @@ static const struct snd_soc_component_driver hdac_hda_codec = { static int hdac_hda_dev_probe(struct hdac_device *hdev) { struct hdac_ext_link *hlink; - struct hdac_hda_priv *hda_pvt; int ret; /* hold the ref while we probe */ @@ -595,10 +594,6 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) } snd_hdac_ext_bus_link_get(hdev->bus, hlink); - hda_pvt = hdac_to_hda_priv(hdev); - if (!hda_pvt) - return -ENOMEM; - /* ASoC specific initialization */ ret = devm_snd_soc_register_component(&hdev->dev, &hdac_hda_codec, hdac_hda_dais, @@ -608,7 +603,6 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) return ret; } - dev_set_drvdata(&hdev->dev, hda_pvt); snd_hdac_ext_bus_link_put(hdev->bus, hlink); return ret; diff --git a/sound/soc/codecs/hdac_hda.h b/sound/soc/codecs/hdac_hda.h index d0efc5e254ae..fc19c34ca00e 100644 --- a/sound/soc/codecs/hdac_hda.h +++ b/sound/soc/codecs/hdac_hda.h @@ -23,7 +23,7 @@ struct hdac_hda_pcm { }; struct hdac_hda_priv { - struct hda_codec codec; + struct hda_codec *codec; struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID]; bool need_display_power; }; diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c index 83c7dfbccd9d..04b7d4f7f9e2 100644 --- a/sound/soc/intel/boards/hda_dsp_common.c +++ b/sound/soc/intel/boards/hda_dsp_common.c @@ -54,7 +54,7 @@ int hda_dsp_hdmi_build_controls(struct snd_soc_card *card, return -EINVAL; hda_pvt = snd_soc_component_get_drvdata(comp); - hcodec = &hda_pvt->codec; + hcodec = hda_pvt->codec; list_for_each_entry(hpcm, &hcodec->pcm_list_head, list) { spcm = hda_dsp_hdmi_pcm_handle(card, i); diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 81144efb4b44..879ebba52832 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -190,7 +190,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) * all codecs are on the same bus, so it's sufficient * to look up only the first one */ - snd_hda_set_power_save(hda_pvt->codec.bus, + snd_hda_set_power_save(hda_pvt->codec->bus, HDA_CODEC_AUTOSUSPEND_DELAY_MS); break; } diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 33b0ed6b0534..c7c1cad2a753 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -694,7 +694,7 @@ static void skl_codec_device_exit(struct device *dev) snd_hdac_device_exit(dev_to_hdac_dev(dev)); } -static __maybe_unused struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr) +static struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr) { struct hda_codec *codec; int ret; @@ -729,9 +729,8 @@ static int probe_codec(struct hdac_bus *bus, int addr) struct skl_dev *skl = bus_to_skl(bus); #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) struct hdac_hda_priv *hda_codec; - int err; #endif - struct hdac_device *hdev; + struct hda_codec *codec; mutex_lock(&bus->cmd_mutex); snd_hdac_bus_send_cmd(bus, cmd); @@ -747,25 +746,22 @@ static int probe_codec(struct hdac_bus *bus, int addr) if (!hda_codec) return -ENOMEM; - hda_codec->codec.bus = skl_to_hbus(skl); - hdev = &hda_codec->codec.core; + codec = skl_codec_device_init(bus, addr); + if (IS_ERR(codec)) + return PTR_ERR(codec); - err = snd_hdac_ext_bus_device_init(bus, addr, hdev, HDA_DEV_ASOC); - if (err < 0) - return err; + hda_codec->codec = codec; + dev_set_drvdata(&codec->core.dev, hda_codec); /* use legacy bus only for HDA codecs, idisp uses ext bus */ if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) { - hdev->type = HDA_DEV_LEGACY; - load_codec_module(&hda_codec->codec); + codec->core.type = HDA_DEV_LEGACY; + load_codec_module(hda_codec->codec); } return 0; #else - hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL); - if (!hdev) - return -ENOMEM; - - return snd_hdac_ext_bus_device_init(bus, addr, hdev, HDA_DEV_ASOC); + codec = skl_codec_device_init(bus, addr); + return PTR_ERR_OR_ZERO(codec); #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ } diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 4c128ba02340..73336648cd25 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -114,8 +114,7 @@ static void hda_codec_device_exit(struct device *dev) snd_hdac_device_exit(dev_to_hdac_dev(dev)); } -static __maybe_unused struct hda_codec * -hda_codec_device_init(struct hdac_bus *bus, int addr, int type) +static struct hda_codec *hda_codec_device_init(struct hdac_bus *bus, int addr, int type) { struct hda_codec *codec; int ret; @@ -145,11 +144,10 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) struct hdac_hda_priv *hda_priv; - struct hda_codec *codec; int type = HDA_DEV_LEGACY; #endif struct hda_bus *hbus = sof_to_hbus(sdev); - struct hdac_device *hdev; + struct hda_codec *codec; u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; u32 resp = -1; @@ -172,20 +170,20 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, if (!hda_priv) return -ENOMEM; - hda_priv->codec.bus = hbus; - hdev = &hda_priv->codec.core; - codec = &hda_priv->codec; - /* only probe ASoC codec drivers for HDAC-HDMI */ if (!hda_codec_use_common_hdmi && (resp & 0xFFFF0000) == IDISP_VID_INTEL) type = HDA_DEV_ASOC; - ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, type); + codec = hda_codec_device_init(&hbus->core, address, type); + ret = PTR_ERR_OR_ZERO(codec); if (ret < 0) return ret; + hda_priv->codec = codec; + dev_set_drvdata(&codec->core.dev, hda_priv); + if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) { - if (!hdev->bus->audio_component) { + if (!hbus->core.audio_component) { dev_dbg(sdev->dev, "iDisp hw present but no driver\n"); ret = -ENOENT; @@ -211,15 +209,12 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, out: if (ret < 0) { - snd_hdac_device_unregister(hdev); - put_device(&hdev->dev); + snd_hdac_device_unregister(&codec->core); + put_device(&codec->core.dev); } #else - hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL); - if (!hdev) - return -ENOMEM; - - ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, HDA_DEV_ASOC); + codec = hda_codec_device_init(&hbus->core, address); + ret = PTR_ERR_OR_ZERO(codec); #endif return ret; -- cgit v1.2.3 From 0c5c29cafcea20f1f6a9943640e4a5a790e259ee Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 16 Aug 2022 13:17:25 +0200 Subject: ALSA: hda: Always free codec on the device release With all HDAudio drivers aligned to make use of the same constructor, have codec freed on the device release regardless of its type. Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220816111727.3218543-5-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 384426d7e9dd..aa7a362be290 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -883,13 +883,7 @@ static void snd_hda_codec_dev_release(struct device *dev) snd_hda_sysfs_clear(codec); kfree(codec->modelname); kfree(codec->wcaps); - - /* - * In the case of ASoC HD-audio, hda_codec is device managed. - * It will be freed when the ASoC device is removed. - */ - if (codec->core.type == HDA_DEV_LEGACY) - kfree(codec); + kfree(codec); } #define DEV_NAME_LEN 31 -- cgit v1.2.3 From fb5987844808bf9abeb23f695e94b75b439daa42 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 16 Aug 2022 13:17:26 +0200 Subject: ALSA: hda: Remove codec init and exit routines There are no users for snd_hdac_ext_bus_device_init() and snd_hdac_ext_bus_device_exit(). While at it, remove hdac_to_hda_priv() too for the exact same reason. Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220816111727.3218543-6-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 2 -- include/sound/hdaudio_ext.h | 3 --- sound/hda/ext/hdac_ext_bus.c | 53 -------------------------------------------- 3 files changed, 58 deletions(-) (limited to 'sound') diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 6d3c82c4b6ac..2a8fe7240f10 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -293,8 +293,6 @@ struct hda_codec { #define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, core.dev) #define hda_codec_dev(_dev) (&(_dev)->core.dev) -#define hdac_to_hda_priv(_hdac) \ - container_of(_hdac, struct hdac_hda_priv, codec.core) #define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core) #define list_for_each_codec(c, bus) \ diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index d26234f9ee46..88ebb64fd8a5 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -11,9 +11,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_ext_bus_ops *ext_ops); void snd_hdac_ext_bus_exit(struct hdac_bus *bus); -int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, - struct hdac_device *hdev, int type); -void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev); void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus); #define HDA_CODEC_REV_EXT_ENTRY(_vid, _rev, _name, drv_data) \ diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 765c40a6ccba..6004ea1c373e 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -60,59 +60,6 @@ void snd_hdac_ext_bus_exit(struct hdac_bus *bus) } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit); -static void default_release(struct device *dev) -{ - snd_hdac_ext_bus_device_exit(dev_to_hdac_dev(dev)); -} - -/** - * snd_hdac_ext_bus_device_init - initialize the HDA extended codec base device - * @bus: hdac bus to attach to - * @addr: codec address - * @hdev: hdac device to init - * @type: codec type (HDAC_DEV_*) to use for this device - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, - struct hdac_device *hdev, int type) -{ - char name[15]; - int ret; - - hdev->bus = bus; - - snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr); - - ret = snd_hdac_device_init(hdev, bus, name, addr); - if (ret < 0) { - dev_err(bus->dev, "device init failed for hdac device\n"); - return ret; - } - hdev->type = type; - hdev->dev.release = default_release; - - ret = snd_hdac_device_register(hdev); - if (ret) { - dev_err(bus->dev, "failed to register hdac device\n"); - snd_hdac_ext_bus_device_exit(hdev); - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); - -/** - * snd_hdac_ext_bus_device_exit - clean up a HD-audio extended codec base device - * @hdev: hdac device to clean up - */ -void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) -{ - snd_hdac_device_exit(hdev); -} -EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); - /** * snd_hdac_ext_bus_device_remove - remove HD-audio extended codec base devices * -- cgit v1.2.3 From f2bd1c5ae2cb0cf9525c9bffc0038c12dd7e1338 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Tue, 16 Aug 2022 13:17:27 +0200 Subject: ALSA: hda: Fix page fault in snd_hda_codec_shutdown() If early probe of HDAudio bus driver fails e.g.: due to missing firmware file, snd_hda_codec_shutdown() ends in manipulating uninitialized codec->pcm_list_head causing page fault. Initialization of HDAudio codec in ASoC is split in two: - snd_hda_codec_device_init() - snd_hda_codec_device_new() snd_hda_codec_device_init() is called during probe_codecs() by HDAudio bus driver while snd_hda_codec_device_new() is called by codec-component's ->probe(). The second call will not happen until all components required by related sound card are present within the ASoC framework. With firmware failing to load during the PCI's deferred initialization i.e.: probe_work(), no platform components are ever registered. HDAudio codec enumeration is done at that point though, so the codec components became registered to ASoC framework, calling snd_hda_codec_device_init() in the process. Now, during platform reboot snd_hda_codec_shutdown() is called for every codec found on the HDAudio bus causing oops if any of them has not completed both of their initialization steps. Relocating field initialization fixes the issue. Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220816111727.3218543-7-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_codec.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index aa7a362be290..b4d1e658c556 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -925,8 +925,28 @@ snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr, } codec->bus = bus; + codec->depop_delay = -1; + codec->fixup_id = HDA_FIXUP_ID_NOT_SET; + codec->core.dev.release = snd_hda_codec_dev_release; + codec->core.exec_verb = codec_exec_verb; codec->core.type = HDA_DEV_LEGACY; + mutex_init(&codec->spdif_mutex); + mutex_init(&codec->control_mutex); + snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); + snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); + snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); + snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); + snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); + snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); + snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16); + snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8); + INIT_LIST_HEAD(&codec->conn_list); + INIT_LIST_HEAD(&codec->pcm_list_head); + INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); + refcount_set(&codec->pcm_ref, 1); + init_waitqueue_head(&codec->remove_sleep); + return codec; } EXPORT_SYMBOL_GPL(snd_hda_codec_device_init); @@ -979,29 +999,8 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS)) return -EINVAL; - codec->core.dev.release = snd_hda_codec_dev_release; - codec->core.exec_verb = codec_exec_verb; - codec->card = card; codec->addr = codec_addr; - mutex_init(&codec->spdif_mutex); - mutex_init(&codec->control_mutex); - snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); - snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); - snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); - snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); - snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); - snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); - snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16); - snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8); - INIT_LIST_HEAD(&codec->conn_list); - INIT_LIST_HEAD(&codec->pcm_list_head); - refcount_set(&codec->pcm_ref, 1); - init_waitqueue_head(&codec->remove_sleep); - - INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); - codec->depop_delay = -1; - codec->fixup_id = HDA_FIXUP_ID_NOT_SET; #ifdef CONFIG_PM codec->power_jiffies = jiffies; -- cgit v1.2.3 From d91857059defe6acb443d8a25691b43a0f9390e8 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Thu, 18 Aug 2022 16:15:15 +0200 Subject: ALSA: hda: Rework snd_hdac_stream_reset() to use macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can use existing macros to poll and update register values instead of open coding the functionality. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20220818141517.109280-3-amadeuszx.slawinski@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/hdac_stream.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'sound') diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index f3582012d22f..bdf6d4db6769 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -165,7 +165,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip); void snd_hdac_stream_reset(struct hdac_stream *azx_dev) { unsigned char val; - int timeout; int dma_run_state; snd_hdac_stream_clear(azx_dev); @@ -173,30 +172,17 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev) dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START; snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); - udelay(3); - timeout = 300; - do { - val = snd_hdac_stream_readb(azx_dev, SD_CTL) & - SD_CTL_STREAM_RESET; - if (val) - break; - } while (--timeout); + + /* wait for hardware to report that the stream entered reset */ + snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300); if (azx_dev->bus->dma_stop_delay && dma_run_state) udelay(azx_dev->bus->dma_stop_delay); - val &= ~SD_CTL_STREAM_RESET; - snd_hdac_stream_writeb(azx_dev, SD_CTL, val); - udelay(3); + snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0); - timeout = 300; - /* waiting for hardware to report that the stream is out of reset */ - do { - val = snd_hdac_stream_readb(azx_dev, SD_CTL) & - SD_CTL_STREAM_RESET; - if (!val) - break; - } while (--timeout); + /* wait for hardware to report that the stream is out of reset */ + snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300); /* reset first position - may not be synced with hw at this time */ if (azx_dev->posbuf) -- cgit v1.2.3 From 21b3d4f58401350cc73e67717366d1127caa6f7f Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Thu, 18 Aug 2022 16:15:16 +0200 Subject: ALSA: hda: Remove unused MAX_PIN_CONFIGS constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since it was introduced around v2.6.30 it was never used. Also HDA specification does not mention any limitation on number of PIN configurations. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20220818141517.109280-4-amadeuszx.slawinski@linux.intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_sysfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index bf951c10ae61..69ebc37a4d6f 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -375,8 +375,6 @@ static ssize_t user_pin_configs_show(struct device *dev, return pin_configs_show(codec, &codec->user_pins, buf); } -#define MAX_PIN_CONFIGS 32 - static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) { int nid, cfg, err; -- cgit v1.2.3 From da9d635f07f21b07ceda13a2ac815a058995f113 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Thu, 18 Aug 2022 16:15:17 +0200 Subject: ALSA: hda: Remove unused defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to keep unused defines in file. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://lore.kernel.org/r/20220818141517.109280-5-amadeuszx.slawinski@linux.intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index a77165bd92a9..7720978dc132 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -86,9 +86,6 @@ enum { #define INTEL_SCH_HDA_DEVC 0x78 #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) -/* Define VIA HD Audio Device ID*/ -#define VIA_HDAC_DEVICE_ID 0x3288 - /* max number of SDs */ /* ICH, ATI and VIA have 4 playback and 4 capture */ #define ICH6_NUM_CAPTURE 4 @@ -102,10 +99,6 @@ enum { #define ATIHDMI_NUM_CAPTURE 0 #define ATIHDMI_NUM_PLAYBACK 8 -/* TERA has 4 playback and 3 capture */ -#define TERA_NUM_CAPTURE 3 -#define TERA_NUM_PLAYBACK 4 - static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -- cgit v1.2.3 From 1cda83e42bf66beb06bf61c7a78951ec0c028898 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 19 Aug 2022 14:47:40 +0200 Subject: ASoC: SOF: Fix compilation when HDA_AUDIO_CODEC config is disabled hda_codec_device_init() expects three parameters, not two. Fixes: 3fd63658caed ("ASoC: Intel: Drop hdac_ext usage for codec device creation") Reported-by: kernel test robot Signed-off-by: Cezary Rojewski Acked-by: Mark Brown Link: https://lore.kernel.org/r/20220819124740.3564862-1-cezary.rojewski@intel.com Signed-off-by: Takashi Iwai --- sound/soc/sof/intel/hda-codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 73336648cd25..1e9afc48394c 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -213,7 +213,7 @@ out: put_device(&codec->core.dev); } #else - codec = hda_codec_device_init(&hbus->core, address); + codec = hda_codec_device_init(&hbus->core, address, HDA_DEV_ASOC); ret = PTR_ERR_OR_ZERO(codec); #endif -- cgit v1.2.3 From b01104fc62b6194c852124f6c6df1c0a5c031fc1 Mon Sep 17 00:00:00 2001 From: Conner Knox Date: Thu, 18 Aug 2022 17:14:33 -0300 Subject: ALSA: usb-audio: Add quirk to enable Avid Mbox 3 support Add support for Avid Mbox3 USB audio interface at 48kHz Signed-off-by: Conner Knox Link: https://lore.kernel.org/r/20220818201433.16360-1-mbarriolinares@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/quirks-table.h | 76 ++++++++++++ sound/usb/quirks.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 378 insertions(+) (limited to 'sound') diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index f93201a830b5..06dfdd45cff8 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2985,6 +2985,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{ + USB_DEVICE(0x0dba, 0x5000), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Digidesign", + .product_name = "Mbox 3", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x00, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 3, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .attributes = 0x00, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .maxpacksize = 0x009c, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 4, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &(const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 168fd802d70b..1b05b0220fad 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,304 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; } +static void mbox3_setup_48_24_magic(struct usb_device *dev) +{ + /* The Mbox 3 is "little endian" */ + /* max volume is: 0x0000. */ + /* min volume is: 0x0080 (shown in little endian form) */ + + + /* Load 48000Hz rate into buffer */ + u8 com_buff[4] = {0x80, 0xbb, 0x00, 0x00}; + + /* Set 48000Hz sample rate */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x0001, &com_buff, 4); //Is this really needed? + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x8101, &com_buff, 4); + + /* Deactivate Tuner */ + /* on = 0x01*/ + /* off = 0x00*/ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0003, 0x2001, &com_buff, 1); + + /* Set clock source to Internal (as opposed to S/PDIF) */ + com_buff[0] = 0x01; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x8001, &com_buff, 1); + + /* Mute the hardware loopbacks to start the device in a known state. */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue input 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0110, 0x4001, &com_buff, 2); + /* Analogue input 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0111, 0x4001, &com_buff, 2); + /* Analogue input 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0114, 0x4001, &com_buff, 2); + /* Analogue input 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0115, 0x4001, &com_buff, 2); + /* Analogue input 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0118, 0x4001, &com_buff, 2); + /* Analogue input 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0119, 0x4001, &com_buff, 2); + /* Analogue input 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011c, 0x4001, &com_buff, 2); + /* Analogue input 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011d, 0x4001, &com_buff, 2); + + /* Set software sends to output */ + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* Analogue software return 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* Analogue software return 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0108, 0x4001, &com_buff, 2); + /* Analogue software return 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0109, 0x4001, &com_buff, 2); + /* Analogue software return 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010c, 0x4001, &com_buff, 2); + /* Analogue software return 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010d, 0x4001, &com_buff, 2); + + /* Return to muting sends */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue fx return left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0120, 0x4001, &com_buff, 2); + /* Analogue fx return right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0121, 0x4001, &com_buff, 2); + + /* Analogue software input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4201, &com_buff, 2); + /* Analogue software input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4201, &com_buff, 2); + /* Analogue software input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4201, &com_buff, 2); + /* Analogue software input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4201, &com_buff, 2); + /* Analogue input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4201, &com_buff, 2); + /* Analogue input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4201, &com_buff, 2); + /* Analogue input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4201, &com_buff, 2); + /* Analogue input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4201, &com_buff, 2); + + /* Toggle allowing host control */ + com_buff[0] = 0x02; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0000, 0x2001, &com_buff, 1); + + /* Do not dim fx returns */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0002, 0x2001, &com_buff, 1); + + /* Do not set fx returns to mono */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0001, 0x2001, &com_buff, 1); + + /* Mute the S/PDIF hardware loopback + * same odd volume logic here as above + */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF hardware input 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0112, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0113, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0116, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0117, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011a, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011b, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011e, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011f, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* S/PDIF software return 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010a, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF software return 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010b, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010e, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* S/PDIF software return 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010f, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF fx returns left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0122, 0x4001, &com_buff, 2); + /* S/PDIF fx returns right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0123, 0x4001, &com_buff, 2); + + /* Set the dropdown "Effect" to the first option */ + /* Room1 = 0x00 */ + /* Room2 = 0x01 */ + /* Room3 = 0x02 */ + /* Hall 1 = 0x03 */ + /* Hall 2 = 0x04 */ + /* Plate = 0x05 */ + /* Delay = 0x06 */ + /* Echo = 0x07 */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0200, 0x4301, &com_buff, 1); /* max is 0xff */ + /* min is 0x00 */ + + + /* Set the effect duration to 0 */ + /* max is 0xffff */ + /* min is 0x0000 */ + com_buff[0] = 0x00; + com_buff[1] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0400, 0x4301, &com_buff, 2); + + /* Set the effect volume and feedback to 0 */ + /* max is 0xff */ + /* min is 0x00 */ + com_buff[0] = 0x00; + /* feedback: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0500, 0x4301, &com_buff, 1); + /* volume: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0300, 0x4301, &com_buff, 1); + + /* Set soft button hold duration */ + /* 0x03 = 250ms */ + /* 0x05 = 500ms DEFAULT */ + /* 0x08 = 750ms */ + /* 0x0a = 1sec */ + com_buff[0] = 0x05; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0005, 0x2001, &com_buff, 1); + + /* Use dim LEDs for button of state */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0004, 0x2001, &com_buff, 1); +} + +#define MBOX3_DESCRIPTOR_SIZE 464 + +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{ + struct usb_host_config *config = dev->actconfig; + int err; + int descriptor_size; + + descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength); + + if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) { + dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size); + return -ENODEV; + } + + dev_dbg(&dev->dev, "device initialised!\n"); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); + config = dev->actconfig; + if (err < 0) + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); + + err = usb_reset_configuration(dev); + if (err < 0) + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n", + le16_to_cpu(get_cfg_desc(config)->wTotalLength)); + + mbox3_setup_48_24_magic(dev); + dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz"); + + return 0; /* Successful boot */ +} #define MICROBOOK_BUF_SIZE 128 @@ -1324,6 +1622,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev); + case USB_ID(0x0dba, 0x5000): + /* Digidesign Mbox 3 */ + return snd_usb_mbox3_boot_quirk(dev); + case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */ -- cgit v1.2.3 From 18afcf90d8807fef66d1fd428eeb2b407df90fa8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 22 Aug 2022 21:00:44 +0200 Subject: ALSA: hda: cleanup definitions for multi-link registers For some reason two masks are used without the AZX prefix, and the pattern MLCLT should be ML_LCTL for consistency. Pure rename, no functionality change. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220822190044.170495-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- include/sound/hda_register.h | 20 +++++++++++--------- sound/hda/ext/hdac_ext_controller.c | 16 ++++++++-------- sound/pci/hda/hda_intel.c | 14 +++++++------- 3 files changed, 26 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h index ad8b71b1dbb6..d37cf43546eb 100644 --- a/include/sound/hda_register.h +++ b/include/sound/hda_register.h @@ -260,7 +260,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_ML_LCAP 0x00 #define AZX_REG_ML_LCTL 0x04 + +#define AZX_ML_LCTL_CPA BIT(23) +#define AZX_ML_LCTL_CPA_SHIFT 23 +#define AZX_ML_LCTL_SPA BIT(16) +#define AZX_ML_LCTL_SPA_SHIFT 16 +#define AZX_ML_LCTL_SCF GENMASK(3, 0) + #define AZX_REG_ML_LOSIDV 0x08 + +/* bit0 is reserved, with BIT(1) mapping to stream1 */ +#define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE + #define AZX_REG_ML_LSDIID 0x0C #define AZX_REG_ML_LPSOO 0x10 #define AZX_REG_ML_LPSIO 0x12 @@ -268,15 +279,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_ML_LOUTPAY 0x20 #define AZX_REG_ML_LINPAY 0x30 -/* bit0 is reserved, with BIT(1) mapping to stream1 */ -#define ML_LOSIDV_STREAM_MASK 0xFFFE - -#define ML_LCTL_SCF_MASK 0xF -#define AZX_MLCTL_SPA (0x1 << 16) -#define AZX_MLCTL_CPA (0x1 << 23) -#define AZX_MLCTL_SPA_SHIFT 16 -#define AZX_MLCTL_CPA_SHIFT 23 - /* registers for DMA Resume Capability Structure */ #define AZX_DRSM_CAP_ID 0x5 #define AZX_REG_DRSM_CTL 0x4 diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index a42f66f561f5..80876b9a87f4 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -170,7 +170,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) { int timeout; u32 val; - int mask = (1 << AZX_MLCTL_CPA_SHIFT); + int mask = (1 << AZX_ML_LCTL_CPA_SHIFT); udelay(3); timeout = 150; @@ -178,10 +178,10 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) do { val = readl(link->ml_addr + AZX_REG_ML_LCTL); if (enable) { - if (((val & mask) >> AZX_MLCTL_CPA_SHIFT)) + if (((val & mask) >> AZX_ML_LCTL_CPA_SHIFT)) return 0; } else { - if (!((val & mask) >> AZX_MLCTL_CPA_SHIFT)) + if (!((val & mask) >> AZX_ML_LCTL_CPA_SHIFT)) return 0; } udelay(3); @@ -197,7 +197,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link) { snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, - AZX_MLCTL_SPA, AZX_MLCTL_SPA); + AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA); return check_hdac_link_power_active(link, true); } @@ -209,7 +209,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up); */ int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link) { - snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0); + snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_ML_LCTL_SPA, 0); return check_hdac_link_power_active(link, false); } @@ -226,7 +226,7 @@ int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, - AZX_MLCTL_SPA, AZX_MLCTL_SPA); + AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA); ret = check_hdac_link_power_active(hlink, true); if (ret < 0) return ret; @@ -247,7 +247,7 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, - AZX_MLCTL_SPA, 0); + AZX_ML_LCTL_SPA, 0); ret = check_hdac_link_power_active(hlink, false); if (ret < 0) return ret; @@ -281,7 +281,7 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, * clear the register to invalidate all the output streams */ snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, - ML_LOSIDV_STREAM_MASK, 0); + AZX_ML_LOSIDV_STREAM_MASK, 0); /* * wait for 521usec for codec to report status * HDA spec section 4.3 - Codec Discovery diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 7720978dc132..bf9df9bc8f1b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -489,14 +489,14 @@ static int intel_ml_lctl_set_power(struct azx *chip, int state) * If other links are enabled for stream, they need similar fix */ val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); - val &= ~AZX_MLCTL_SPA; - val |= state << AZX_MLCTL_SPA_SHIFT; + val &= ~AZX_ML_LCTL_SPA; + val |= state << AZX_ML_LCTL_SPA_SHIFT; writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); /* wait for CPA */ timeout = 50; while (timeout) { if (((readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL)) & - AZX_MLCTL_CPA) == (state << AZX_MLCTL_CPA_SHIFT)) + AZX_ML_LCTL_CPA) == (state << AZX_ML_LCTL_CPA_SHIFT)) return 0; timeout--; udelay(10); @@ -514,15 +514,15 @@ static void intel_init_lctl(struct azx *chip) /* 0. check lctl register value is correct or not */ val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); /* if SCF is already set, let's use it */ - if ((val & ML_LCTL_SCF_MASK) != 0) + if ((val & AZX_ML_LCTL_SCF) != 0) return; /* * Before operating on SPA, CPA must match SPA. * Any deviation may result in undefined behavior. */ - if (((val & AZX_MLCTL_SPA) >> AZX_MLCTL_SPA_SHIFT) != - ((val & AZX_MLCTL_CPA) >> AZX_MLCTL_CPA_SHIFT)) + if (((val & AZX_ML_LCTL_SPA) >> AZX_ML_LCTL_SPA_SHIFT) != + ((val & AZX_ML_LCTL_CPA) >> AZX_ML_LCTL_CPA_SHIFT)) return; /* 1. turn link down: set SPA to 0 and wait CPA to 0 */ @@ -532,7 +532,7 @@ static void intel_init_lctl(struct azx *chip) goto set_spa; /* 2. update SCF to select a properly audio clock*/ - val &= ~ML_LCTL_SCF_MASK; + val &= ~AZX_ML_LCTL_SCF; val |= intel_get_lctl_scf(chip); writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); -- cgit v1.2.3 From a5ed0c547d50d30a60d67b0911b4ec2c85c54310 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 23 Aug 2022 13:57:36 +0200 Subject: ALSA: vx: Drop superfluous GFP setup The extra setup with GFP_DMA32 is superfluous for this driver. The whole operation is a simple copy loop, and there is no memory address restriction at all. Drop the useless GFP setup. Link: https://lore.kernel.org/r/20220823115740.14123-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/drivers/vx/vx_pcm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 3924f5283745..ceaeb257003b 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -1215,8 +1215,7 @@ int snd_vx_pcm_new(struct vx_core *chip) if (ins) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops); snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, - snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32), - 0, 0); + NULL, 0, 0); pcm->private_data = chip; pcm->private_free = snd_vx_pcm_free; -- cgit v1.2.3 From 63bfc84672bbdfc19e54ce181d094fc1aab09e8c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 23 Aug 2022 13:57:37 +0200 Subject: ALSA: pdaudiocf: Drop superfluous GFP setup The extra setup with GFP_DMA32 is superfluous for this driver. The whole operation is a simple copy loop, and there is no memory address restriction at all. Drop the useless GFP setup. Link: https://lore.kernel.org/r/20220823115740.14123-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index dfc4295b69c4..aaa82ec36540 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -257,8 +257,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops); - snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, - snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32), + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); pcm->private_data = chip; -- cgit v1.2.3 From 97557ec97a2473ffb9ca5d2e19d21e4807f43fb1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 23 Aug 2022 13:57:38 +0200 Subject: ASoC: Intel: sst: Switch to standard device pages ASoC Atom SST driver is using the continuous RAM pages with GFP_DMA flag for its PCM buffer, but this should work fine with the standard DMA pages. As a part of cleanup work, this patch replaces the buffer allocation to the standard device pages with SNDRV_DMA_TYPE_DEV. Link: https://lore.kernel.org/r/20220823115740.14123-4-tiwai@suse.de Signed-off-by: Takashi Iwai Reviewed-by: Cezary Rojewski --- sound/soc/intel/atom/sst-mfld-platform-pcm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index a56dd48c045f..c75616a5fd0a 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -676,10 +676,9 @@ static int sst_soc_pcm_new(struct snd_soc_component *component, if (dai->driver->playback.channels_min || dai->driver->capture.channels_min) { - snd_pcm_set_managed_buffer_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_DMA), - SST_MIN_BUFFER, SST_MAX_BUFFER); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, + pcm->card->dev, + SST_MIN_BUFFER, SST_MAX_BUFFER); } return 0; } -- cgit v1.2.3 From dd164fbfdc20ccf17be9186b1a5a4b2bc11b6a97 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 23 Aug 2022 13:57:39 +0200 Subject: ALSA: memalloc: Drop special handling of GFP for CONTINUOUS allocation Now that all users of snd_dma_continuous_data() is gone, let's drop this ugly (and dangerous) way. After this commit, SNDRV_DMA_TYPE_CONTINUOUS may take the standard device pointer instead of the hacked pointer by the macro above, and the memalloc core refers to the coherent_dma_mask of the given device like other SNDRV_DMA_TYPE. It's still allowed to pass NULL there, and in that case, the allocation is performed always in the normal zone. For SNDRV_DMA_TYPE_VMALLOC, the device pointer is simply ignored. Link: https://lore.kernel.org/r/20220823115740.14123-5-tiwai@suse.de Signed-off-by: Takashi Iwai --- include/sound/memalloc.h | 3 -- sound/core/memalloc.c | 113 ++++++++++++++++++++--------------------------- 2 files changed, 48 insertions(+), 68 deletions(-) (limited to 'sound') diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index 8d79cebf95f3..43d524580bd2 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h @@ -26,9 +26,6 @@ struct snd_dma_device { struct device *dev; /* generic device */ }; -#define snd_dma_continuous_data(x) ((struct device *)(__force unsigned long)(x)) - - /* * buffer types */ diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index b665ac66ccbe..39561faef6e9 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -18,25 +18,18 @@ #include #include "memalloc_local.h" +#define DEFAULT_GFP \ + (GFP_KERNEL | \ + __GFP_COMP | /* compound page lets parts be mapped */ \ + __GFP_NORETRY | /* don't trigger OOM-killer */ \ + __GFP_NOWARN) /* no stack trace print - this call is non-critical */ + static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab); #ifdef CONFIG_SND_DMA_SGBUF -static void *do_alloc_fallback_pages(struct device *dev, size_t size, - dma_addr_t *addr, bool wc); -static void do_free_fallback_pages(void *p, size_t size, bool wc); static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size); #endif -/* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */ -static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab, - gfp_t default_gfp) -{ - if (!dmab->dev.dev) - return default_gfp; - else - return (__force gfp_t)(unsigned long)dmab->dev.dev; -} - static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size) { const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); @@ -284,24 +277,54 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size); /* * Continuous pages allocator */ -static void *do_alloc_pages(size_t size, dma_addr_t *addr, gfp_t gfp) +static void *do_alloc_pages(struct device *dev, size_t size, dma_addr_t *addr, + bool wc) { - void *p = alloc_pages_exact(size, gfp); + void *p; + gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; - if (p) - *addr = page_to_phys(virt_to_page(p)); + again: + p = alloc_pages_exact(size, gfp); + if (!p) + return NULL; + *addr = page_to_phys(virt_to_page(p)); + if (!dev) + return p; + if ((*addr + size - 1) & ~dev->coherent_dma_mask) { + if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) { + gfp |= GFP_DMA32; + goto again; + } + if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) { + gfp = (gfp & ~GFP_DMA32) | GFP_DMA; + goto again; + } + } +#ifdef CONFIG_X86 + if (wc) + set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT); +#endif return p; } +static void do_free_pages(void *p, size_t size, bool wc) +{ +#ifdef CONFIG_X86 + if (wc) + set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT); +#endif + free_pages_exact(p, size); +} + + static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size) { - return do_alloc_pages(size, &dmab->addr, - snd_mem_get_gfp_flags(dmab, GFP_KERNEL)); + return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, false); } static void snd_dma_continuous_free(struct snd_dma_buffer *dmab) { - free_pages_exact(dmab->area, dmab->bytes); + do_free_pages(dmab->area, dmab->bytes, false); } static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab, @@ -324,9 +347,7 @@ static const struct snd_malloc_ops snd_dma_continuous_ops = { */ static void *snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size) { - gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM); - - return __vmalloc(size, gfp); + return vmalloc(size); } static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab) @@ -440,12 +461,6 @@ static const struct snd_malloc_ops snd_dma_iram_ops = { }; #endif /* CONFIG_GENERIC_ALLOCATOR */ -#define DEFAULT_GFP \ - (GFP_KERNEL | \ - __GFP_COMP | /* compound page lets parts be mapped */ \ - __GFP_NORETRY | /* don't trigger OOM-killer */ \ - __GFP_NOWARN) /* no stack trace print - this call is non-critical */ - /* * Coherent device pages allocator */ @@ -479,12 +494,12 @@ static const struct snd_malloc_ops snd_dma_dev_ops = { #ifdef CONFIG_SND_DMA_SGBUF static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size) { - return do_alloc_fallback_pages(dmab->dev.dev, size, &dmab->addr, true); + return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true); } static void snd_dma_wc_free(struct snd_dma_buffer *dmab) { - do_free_fallback_pages(dmab->area, dmab->bytes, true); + do_free_pages(dmab->area, dmab->bytes, true); } static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab, @@ -697,37 +712,6 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = { .get_chunk_size = snd_dma_noncontig_get_chunk_size, }; -/* manual page allocations with wc setup */ -static void *do_alloc_fallback_pages(struct device *dev, size_t size, - dma_addr_t *addr, bool wc) -{ - gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; - void *p; - - again: - p = do_alloc_pages(size, addr, gfp); - if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) { - if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) { - gfp |= GFP_DMA32; - goto again; - } - if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) { - gfp = (gfp & ~GFP_DMA32) | GFP_DMA; - goto again; - } - } - if (p && wc) - set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT); - return p; -} - -static void do_free_fallback_pages(void *p, size_t size, bool wc) -{ - if (wc) - set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT); - free_pages_exact(p, size); -} - /* Fallback SG-buffer allocations for x86 */ struct snd_dma_sg_fallback { size_t count; @@ -742,7 +726,7 @@ static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab, size_t i; for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++) - do_free_fallback_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc); + do_free_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc); kvfree(sgbuf->pages); kvfree(sgbuf->addrs); kfree(sgbuf); @@ -769,8 +753,7 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size) goto error; for (i = 0; i < count; sgbuf->count++, i++) { - p = do_alloc_fallback_pages(dmab->dev.dev, PAGE_SIZE, - &sgbuf->addrs[i], wc); + p = do_alloc_pages(dmab->dev.dev, PAGE_SIZE, &sgbuf->addrs[i], wc); if (!p) goto error; sgbuf->pages[i] = virt_to_page(p); -- cgit v1.2.3 From 999b95a72d90ed7a7073eae594fa35462d71854f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 29 Aug 2022 16:52:03 -0500 Subject: ALSA: hda/hdmi: Replace zero-length array with DECLARE_FLEX_ARRAY() helper Zero-length arrays are deprecated and we are moving towards adopting C99 flexible-array members, instead. So, replace zero-length array declaration in union audio_infoframe with the new DECLARE_FLEX_ARRAY() helper macro. This helper allows for a flexible-array member in a union. Link: https://github.com/KSPP/linux/issues/193 Link: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html Signed-off-by: Gustavo A. R. Silva Reviewed-by: Kees Cook Link: https://lore.kernel.org/r/Yw01A+TvF1FWQ588@work Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6c209cd26c0c..2191d445d74e 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -229,7 +229,7 @@ struct dp_audio_infoframe { union audio_infoframe { struct hdmi_audio_infoframe hdmi; struct dp_audio_infoframe dp; - u8 bytes[0]; + DECLARE_FLEX_ARRAY(u8, bytes); }; /* -- cgit v1.2.3 From ac5e2fb425e1121ceef2b9d1b3ffccc195d55707 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 31 Aug 2022 15:00:21 +0200 Subject: ALSA: usb-audio: Drop superfluous interface setup at parsing We reset each interface that is being parsed for each stream, but this is superfluous and even can lead to spurious errors. Since the interface is set up properly at opening the endpoint for each actual stream operation, let's drop the superfluous one. Link: https://lore.kernel.org/r/20220831130021.4762-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/stream.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sound') diff --git a/sound/usb/stream.c b/sound/usb/stream.c index ceb93d798182..99578e9a8af0 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1221,12 +1221,6 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, if (err < 0) return err; } - - /* try to set the interface... */ - usb_set_interface(chip->dev, iface_no, 0); - snd_usb_init_pitch(chip, fp); - snd_usb_init_sample_rate(chip, fp, fp->rate_max); - usb_set_interface(chip->dev, iface_no, altno); } return 0; } -- cgit v1.2.3 From f51ba1148a810a16eead9f0b29bfa2a8f8ab3afb Mon Sep 17 00:00:00 2001 From: Valentina Goncharenko Date: Thu, 1 Sep 2022 13:28:14 +0300 Subject: ALSA: asihpi - Remove useless code in hpi_meter_get_peak() The hpi_meter_get_peak() function contains the expression "hm.obj_index = hm.obj_index", which does not carry any semantic load. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 719f82d3987a ("ALSA: Add support of AudioScience ASI boards") Signed-off-by: Valentina Goncharenko Link: https://lore.kernel.org/r/20220901102814.131855-1-goncharenko.vp@ispras.ru Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpifunc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c index 1de05383126a..24047fafef51 100644 --- a/sound/pci/asihpi/hpifunc.c +++ b/sound/pci/asihpi/hpifunc.c @@ -2020,7 +2020,6 @@ u16 hpi_meter_get_peak(u32 h_control, short an_peakdB[HPI_MAX_CHANNELS] HPI_CONTROL_GET_STATE); if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) return HPI_ERROR_INVALID_HANDLE; - hm.obj_index = hm.obj_index; hm.u.c.attribute = HPI_METER_PEAK; hpi_send_recv(&hm, &hr); -- cgit v1.2.3 From 32eeeed963ad4f41b422b3e314d96ded7283b201 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 1 Sep 2022 15:08:31 +0200 Subject: ALSA: usb-audio: Clean up endpoint setups at PCM prepare This patch cleans up the superfluous checks and calls for setting up the endpoints at PCM prepare callback: - Drop stop_endpoints() and sync_pending_stops() calls; the stream is guaranteed to have been already stopped and synced at each PCM prepare call by ALSA PCM core - Call snd_usb_endpoint_prepare() unconditionally; the check for endpoint->need_setup is done in snd_pcm_hw_endpoint_prepare() itself - Apply snd_usb_set_format_quirk() only when the endpoint is actually set up (i.e. the return code from snd_usb_endpoint_prepare() > 0) - Move a few lines back into snd_usb_pcm_prepare(); it's even easier to follow than a small useless function Link: https://lore.kernel.org/r/20220901130831.6136-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) (limited to 'sound') diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b604f7e95e82..4ed53a3dc922 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -433,35 +433,6 @@ static void close_endpoints(struct snd_usb_audio *chip, } } -static int configure_endpoints(struct snd_usb_audio *chip, - struct snd_usb_substream *subs) -{ - int err; - - if (subs->data_endpoint->need_setup) { - /* stop any running stream beforehand */ - if (stop_endpoints(subs, false)) - sync_pending_stops(subs); - if (subs->sync_endpoint) { - err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); - if (err < 0) - return err; - } - err = snd_usb_endpoint_prepare(chip, subs->data_endpoint); - if (err < 0) - return err; - snd_usb_set_format_quirk(subs, subs->cur_audiofmt); - } else { - if (subs->sync_endpoint) { - err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); - if (err < 0) - return err; - } - } - - return 0; -} - /* * hw_params callback * @@ -640,9 +611,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; } - ret = configure_endpoints(chip, subs); + if (subs->sync_endpoint) { + ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + if (ret < 0) + goto unlock; + } + + ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); if (ret < 0) goto unlock; + else if (ret > 0) + snd_usb_set_format_quirk(subs, subs->cur_audiofmt); + ret = 0; /* reset the pointer */ subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); -- cgit v1.2.3 From 6392dcd1d0c7034ccf630ec55fc9e5810ecadf3b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 4 Sep 2022 18:12:47 +0200 Subject: ALSA: usb-audio: Register card at the last interface The USB-audio driver matches per interface, and as default, it registers the card instance at the very first instance. This can be a problem for the devices that have multiple interfaces to be probed, as the udev rule isn't applied properly for the later appearing interfaces. Although we introduced the delayed_register option and the quirks for covering those shortcomings, it's nothing but a workaround for specific devices. This patch is an another attempt to fix the problem in a more generic way. Now the driver checks the whole USB device descriptor at the very first time when an interface is attached to a sound card. It looks at each matching interface in the descriptor and remembers the last matching one. The snd_card_register() is invoked only when this last interface is probed. After this change, the quirks for the delayed registration become superfluous, hence they are removed along with the patch. OTOH, the delayed_register option is still kept, as it might be useful for some corner cases (e.g. a special driver overtakes the interface probe from the standard driver, and the last interface probe may miss). Link: https://lore.kernel.org/r/20220904161247.16461-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/card.c | 32 +++++++++++++++++++++++++------- sound/usb/quirks.c | 42 ------------------------------------------ sound/usb/quirks.h | 2 -- sound/usb/usbaudio.h | 1 + 4 files changed, 26 insertions(+), 51 deletions(-) (limited to 'sound') diff --git a/sound/usb/card.c b/sound/usb/card.c index 706d249a9ad6..3aea241435fb 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -690,7 +690,7 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id) return false; } -static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) +static int check_delayed_register_option(struct snd_usb_audio *chip) { int i; unsigned int id, inum; @@ -699,14 +699,31 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) if (delayed_register[i] && sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 && id == chip->usb_id) - return iface < inum; + return inum; } - return false; + return -1; } static const struct usb_device_id usb_audio_ids[]; /* defined below */ +/* look for the last interface that matches with our ids and remember it */ +static void find_last_interface(struct snd_usb_audio *chip) +{ + struct usb_host_config *config = chip->dev->actconfig; + struct usb_interface *intf; + int i; + + if (!config) + return; + for (i = 0; i < config->desc.bNumInterfaces; i++) { + intf = config->interface[i]; + if (usb_match_id(intf, usb_audio_ids)) + chip->last_iface = intf->altsetting[0].desc.bInterfaceNumber; + } + usb_audio_dbg(chip, "Found last interface = %d\n", chip->last_iface); +} + /* look for the corresponding quirk */ static const struct snd_usb_audio_quirk * get_alias_quirk(struct usb_device *dev, unsigned int id) @@ -813,6 +830,7 @@ static int usb_audio_probe(struct usb_interface *intf, err = -ENODEV; goto __error; } + find_last_interface(chip); } if (chip->num_interfaces >= MAX_CARD_INTERFACES) { @@ -862,11 +880,11 @@ static int usb_audio_probe(struct usb_interface *intf, chip->need_delayed_register = false; /* clear again */ } - /* we are allowed to call snd_card_register() many times, but first - * check to see if a device needs to skip it or do anything special + /* register card if we reach to the last interface or to the specified + * one given via option */ - if (!snd_usb_registration_quirk(chip, ifnum) && - !check_delayed_register_option(chip, ifnum)) { + if (check_delayed_register_option(chip) == ifnum || + chip->last_iface == ifnum) { err = snd_card_register(chip->card); if (err < 0) goto __error; diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 194c75c45628..eadac586bcc8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -2030,48 +2030,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, } } -/* - * registration quirk: - * the registration is skipped if a device matches with the given ID, - * unless the interface reaches to the defined one. This is for delaying - * the registration until the last known interface, so that the card and - * devices appear at the same time. - */ - -struct registration_quirk { - unsigned int usb_id; /* composed via USB_ID() */ - unsigned int interface; /* the interface to trigger register */ -}; - -#define REG_QUIRK_ENTRY(vendor, product, iface) \ - { .usb_id = USB_ID(vendor, product), .interface = (iface) } - -static const struct registration_quirk registration_quirks[] = { - REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ - REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */ - REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */ - { 0 } /* terminator */ -}; - -/* return true if skipping registration */ -bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface) -{ - const struct registration_quirk *q; - - for (q = registration_quirks; q->usb_id; q++) - if (chip->usb_id == q->usb_id) - return iface < q->interface; - - /* Register as normal */ - return false; -} - /* * driver behavior quirk flags */ diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 31abb7cb01a5..f9bfd5ac7bab 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -48,8 +48,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, struct audioformat *fp, int stream); -bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface); - void snd_usb_init_quirk_flags(struct snd_usb_audio *chip); #endif /* __USBAUDIO_QUIRKS_H */ diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index ffbb4b0d09a0..2c6575029b1c 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,6 +37,7 @@ struct snd_usb_audio { unsigned int quirk_flags; unsigned int need_delayed_register:1; /* warn for delayed registration */ int num_interfaces; + int last_iface; int num_suspended_intf; int sample_rate_read_error; -- cgit v1.2.3 From 4c8d695cb9bc5f6fd298a586602947b2fc099a64 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 6 Sep 2022 11:23:06 +0200 Subject: ALSA: hda: beep: Simplify keep-power-at-enable behavior The recent fix for IDT codecs to keep the power up while the beep is enabled can be better integrated into the beep helper code. This patch cleans up the code with refactoring. Fixes: 414d38ba8710 ("ALSA: hda/sigmatel: Keep power up while beep is enabled") Link: https://lore.kernel.org/r/20220906092306.26183-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_beep.c | 15 +++++++++++++-- sound/pci/hda/hda_beep.h | 1 + sound/pci/hda/patch_sigmatel.c | 25 ++----------------------- 3 files changed, 16 insertions(+), 25 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 53a2b89f8983..e63621bcb214 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -118,6 +118,12 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, return 0; } +static void turn_on_beep(struct hda_beep *beep) +{ + if (beep->keep_power_at_enable) + snd_hda_power_up_pm(beep->codec); +} + static void turn_off_beep(struct hda_beep *beep) { cancel_work_sync(&beep->beep_work); @@ -125,6 +131,8 @@ static void turn_off_beep(struct hda_beep *beep) /* turn off beep */ generate_tone(beep, 0); } + if (beep->keep_power_at_enable) + snd_hda_power_down_pm(beep->codec); } /** @@ -140,7 +148,9 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) enable = !!enable; if (beep->enabled != enable) { beep->enabled = enable; - if (!enable) + if (enable) + turn_on_beep(beep); + else turn_off_beep(beep); return 1; } @@ -167,7 +177,8 @@ static int beep_dev_disconnect(struct snd_device *device) input_unregister_device(beep->dev); else input_free_device(beep->dev); - turn_off_beep(beep); + if (beep->enabled) + turn_off_beep(beep); return 0; } diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index a25358a4807a..db76e3ddba65 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -25,6 +25,7 @@ struct hda_beep { unsigned int enabled:1; unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ unsigned int playing:1; + unsigned int keep_power_at_enable:1; /* set by driver */ struct work_struct beep_work; /* scheduled task for beep event */ struct mutex mutex; void (*power_hook)(struct hda_beep *beep, bool on); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7f340f18599c..a794a01a68ca 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4311,6 +4311,8 @@ static int stac_parse_auto_config(struct hda_codec *codec) if (codec->beep) { /* IDT/STAC codecs have linear beep tone parameter */ codec->beep->linear_tone = spec->linear_tone_beep; + /* keep power up while beep is enabled */ + codec->beep->keep_power_at_enable = 1; /* if no beep switch is available, make its own one */ caps = query_amp_caps(codec, nid, HDA_OUTPUT); if (!(caps & AC_AMPCAP_MUTE)) { @@ -4444,28 +4446,6 @@ static int stac_suspend(struct hda_codec *codec) return 0; } - -static int stac_check_power_status(struct hda_codec *codec, hda_nid_t nid) -{ -#ifdef CONFIG_SND_HDA_INPUT_BEEP - struct sigmatel_spec *spec = codec->spec; -#endif - int ret = snd_hda_gen_check_power_status(codec, nid); - -#ifdef CONFIG_SND_HDA_INPUT_BEEP - if (nid == spec->gen.beep_nid && codec->beep) { - if (codec->beep->enabled != spec->beep_power_on) { - spec->beep_power_on = codec->beep->enabled; - if (spec->beep_power_on) - snd_hda_power_up_pm(codec); - else - snd_hda_power_down_pm(codec); - } - ret |= spec->beep_power_on; - } -#endif - return ret; -} #else #define stac_suspend NULL #endif /* CONFIG_PM */ @@ -4478,7 +4458,6 @@ static const struct hda_codec_ops stac_patch_ops = { .unsol_event = snd_hda_jack_unsol_event, #ifdef CONFIG_PM .suspend = stac_suspend, - .check_power_status = stac_check_power_status, #endif }; -- cgit v1.2.3 From aca289f7cd233b3c983b43b59cdaa0d934ea3da7 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 5 Sep 2022 19:58:25 +0300 Subject: ALSA: hda: cs35l41: Call put_device() in the scope of get_device() When put_device() is called in another function it's hard to realize that and easy to "fix" the code in a wrong way. Instead, move put_device() to be in the same scope as get_device(), so we prevent appearance of any attempts to "fix" the code. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220905165826.35979-1-andriy.shevchenko@linux.intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 15e2a0009080..12e955931044 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -1154,7 +1154,6 @@ static int cs35l41_no_acpi_dsd(struct cs35l41_hda *cs35l41, struct device *physd hw_cfg->gpio2.func = CS35L41_INTERRUPT; hw_cfg->gpio2.valid = true; hw_cfg->valid = true; - put_device(physdev); if (strncmp(hid, "CLSA0100", 8) == 0) { hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; @@ -1204,9 +1203,10 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i property = "cirrus,dev-index"; ret = device_property_count_u32(physdev, property); - if (ret <= 0) - return cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid); - + if (ret <= 0) { + ret = cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid); + goto err_put_physdev; + } if (ret > ARRAY_SIZE(values)) { ret = -EINVAL; goto err; @@ -1295,8 +1295,9 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i return 0; err: - put_device(physdev); dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); +err_put_physdev: + put_device(physdev); return ret; } -- cgit v1.2.3 From 7269734abbf5960d0be9050ba3991c0af1d9f574 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 5 Sep 2022 19:58:26 +0300 Subject: ALSA: hda: cs35l41: Utilize acpi_get_subsystem_id() Replace open coded variant of recently introduced acpi_get_subsystem_id(). Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220905165826.35979-2-andriy.shevchenko@linux.intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 46 +++++++++------------------------------------ 1 file changed, 9 insertions(+), 37 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 12e955931044..3952f2853703 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -842,8 +842,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas comps->dev = dev; if (!cs35l41->acpi_subsystem_id) - cs35l41->acpi_subsystem_id = devm_kasprintf(dev, GFP_KERNEL, "%.8x", - comps->codec->core.subsystem_id); + cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x", + comps->codec->core.subsystem_id); cs35l41->codec = comps->codec; strscpy(comps->name, dev_name(dev), sizeof(comps->name)); @@ -1048,36 +1048,6 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41) return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos); } -static int cs35l41_get_acpi_sub_string(struct device *dev, struct acpi_device *adev, - const char **subsysid) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - int ret = 0; - - status = acpi_evaluate_object(adev->handle, "_SUB", NULL, &buffer); - if (ACPI_SUCCESS(status)) { - obj = buffer.pointer; - if (obj->type == ACPI_TYPE_STRING) { - *subsysid = devm_kstrdup(dev, obj->string.pointer, GFP_KERNEL); - if (*subsysid == NULL) { - dev_err(dev, "Cannot allocate Subsystem ID"); - ret = -ENOMEM; - } - } else { - dev_warn(dev, "Warning ACPI _SUB did not return a string\n"); - ret = -ENODEV; - } - acpi_os_free(buffer.pointer); - } else { - dev_dbg(dev, "Warning ACPI _SUB failed: %#x\n", status); - ret = -ENODEV; - } - - return ret; -} - static int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id) { @@ -1182,6 +1152,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i u32 values[HDA_MAX_COMPONENTS]; struct acpi_device *adev; struct device *physdev; + const char *sub; char *property; size_t nval; int i, ret; @@ -1195,11 +1166,10 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i physdev = get_device(acpi_get_first_physical_node(adev)); acpi_dev_put(adev); - ret = cs35l41_get_acpi_sub_string(cs35l41->dev, adev, &cs35l41->acpi_subsystem_id); - if (ret) - dev_info(cs35l41->dev, "No Subsystem ID found in ACPI: %d", ret); - else - dev_dbg(cs35l41->dev, "Subsystem ID %s found", cs35l41->acpi_subsystem_id); + sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); + if (IS_ERR(sub)) + sub = NULL; + cs35l41->acpi_subsystem_id = sub; property = "cirrus,dev-index"; ret = device_property_count_u32(physdev, property); @@ -1434,6 +1404,7 @@ err: if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); + kfree(cs35l41->acpi_subsystem_id); return ret; } @@ -1456,6 +1427,7 @@ void cs35l41_hda_remove(struct device *dev) if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); + kfree(cs35l41->acpi_subsystem_id); } EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); -- cgit v1.2.3 From a0e3a293bc001f5aba8a252b6191030ad5911c82 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Fri, 9 Sep 2022 11:54:42 +0800 Subject: ALSA: line6: remove line6_set_raw declaration line6_set_raw has been removed since commit 9f673d7a6022 ("staging: line6: drop CONFIG_LINE6_USB_RAW"), so remove it. Signed-off-by: Gaosheng Cui Link: https://lore.kernel.org/r/20220909035443.1065737-2-cuigaosheng1@huawei.com Signed-off-by: Takashi Iwai --- sound/usb/line6/driver.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index ecf3a2b39c7e..dbb1d90d3647 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -193,8 +193,6 @@ extern int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, int size); extern int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, int size); -extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); extern int line6_version_request_async(struct usb_line6 *line6); extern int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, unsigned datalen); -- cgit v1.2.3 From 5a55b51a3dea50c8b700cdde0aeb75e0a388486b Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Fri, 9 Sep 2022 11:54:43 +0800 Subject: ALSA: memalloc: remove snd_dma_sg_ops declaration snd_dma_sg_ops has been removed since commit 2c95b92ecd92 ("ALSA: memalloc: Unify x86 SG-buffer handling (take#3)"), so remove it. Signed-off-by: Gaosheng Cui Link: https://lore.kernel.org/r/20220909035443.1065737-3-cuigaosheng1@huawei.com Signed-off-by: Takashi Iwai --- sound/core/memalloc_local.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'sound') diff --git a/sound/core/memalloc_local.h b/sound/core/memalloc_local.h index a6f3a87194da..8b19f3a68a4b 100644 --- a/sound/core/memalloc_local.h +++ b/sound/core/memalloc_local.h @@ -13,8 +13,4 @@ struct snd_malloc_ops { void (*sync)(struct snd_dma_buffer *dmab, enum snd_dma_sync_mode mode); }; -#ifdef CONFIG_SND_DMA_SGBUF -extern const struct snd_malloc_ops snd_dma_sg_ops; -#endif - #endif /* __MEMALLOC_LOCAL_H */ -- cgit v1.2.3 From 5b4fc3956bfda2da22a6f7f25b157ad24ba1cd95 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Fri, 9 Sep 2022 14:11:26 +0800 Subject: sound: oss: dmasound: remove software_input_volume declaration expand_read_bal has been removed since commit fc37449f7959 ("The next round of scheduled OSS code removal"). software_input_volume has been removed since commit 0a1b42db4bf9 ("sound: sound/oss/dmasound/: cleanups"). so remove the declare for them from header file. Signed-off-by: Gaosheng Cui Link: https://lore.kernel.org/r/20220909061126.1129585-1-cuigaosheng1@huawei.com Signed-off-by: Takashi Iwai --- sound/oss/dmasound/dmasound.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'sound') diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h index ad8ce6a1c25c..f065840c0efb 100644 --- a/sound/oss/dmasound/dmasound.h +++ b/sound/oss/dmasound/dmasound.h @@ -250,7 +250,4 @@ extern int dmasound_catchRadius; #define SW_INPUT_VOLUME_SCALE 4 #define SW_INPUT_VOLUME_DEFAULT (128 / SW_INPUT_VOLUME_SCALE) -extern int expand_read_bal; /* Balance factor for reading */ -extern uint software_input_volume; /* software implemented recording volume! */ - #endif /* _dmasound_h_ */ -- cgit v1.2.3 From ead3d3c5b54f76da79c079e61bacb4279ec56965 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 10 Sep 2022 16:25:50 +0200 Subject: ALSA: hda: Fix hang at HD-audio codec unbinding due to refcount saturation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We fixed the potential deadlock at dynamic unbinding the HD-audio codec at the commit 7206998f578d ("ALSA: hda: Fix potential deadlock at codec unbinding"), but ironically, this caused another potential deadlock. The current code uses refcount_dec() and waits for the pending task with wait_event for dropping the refcount to 0. This works fine when PCMs are assigned and actually waiting for the refcount drop. Meanwhile, when there was no PCM assigned, the refcount_dec() call itself was supposed to drop to zero -- alas, it doesn't in reality; refcount_dec() complains, spews kernel warning and it saturates instead of dropping to 0, due to the nature of refcount_dec() implementation. This eventually blocks the wait_event() wakeup and the code get stuck there. For avoiding the problem, we call refcount_dec_and_test() and skips the sync-wait if it already reaches to zero. The patch does a slight code reshuffling to make sure to invoke other disconnect calls before the sync-wait, too. Fixes: 7206998f578d ("ALSA: hda: Fix potential deadlock at codec unbinding") Reported-by: Ville Syrjälä Tested-by: Ville Syrjälä Cc: Link: https://lore.kernel.org/r/YxtflWQnslMHVlU7@intel.com Link: https://lore.kernel.org/r/20220910142550.28494-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_bind.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index cae9a975cbcc..1a868dd9dc4b 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -157,10 +157,10 @@ static int hda_codec_driver_remove(struct device *dev) return codec->bus->core.ext_ops->hdev_detach(&codec->core); } - refcount_dec(&codec->pcm_ref); snd_hda_codec_disconnect_pcms(codec); snd_hda_jack_tbl_disconnect(codec); - wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref)); + if (!refcount_dec_and_test(&codec->pcm_ref)) + wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref)); snd_power_sync_ref(codec->bus->card); if (codec->patch_ops.free) -- cgit v1.2.3 From 7ae22bdf49d513b0555d25df4d361379fc8ad166 Mon Sep 17 00:00:00 2001 From: YJ Lee Date: Mon, 12 Sep 2022 15:28:54 +0800 Subject: ALSA: dummy: Fix trailing whitespaces. Fix checkpatch.pl ERROR: trailing whitespaces. Signed-off-by: YJ Lee Link: https://lore.kernel.org/r/20220912072854.760824-1-yunjunlee@chromium.org Signed-off-by: Takashi Iwai --- sound/drivers/dummy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 2a7fc49c1a7c..fcf1ee00bd21 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -296,7 +296,7 @@ static void dummy_systimer_callback(struct timer_list *t) struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer); unsigned long flags; int elapsed = 0; - + spin_lock_irqsave(&dpcm->lock, flags); dummy_systimer_update(dpcm); dummy_systimer_rearm(dpcm); @@ -717,7 +717,7 @@ static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, uinfo->value.integer.max = 100; return 0; } - + static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -766,7 +766,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); .private_value = addr } #define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info - + static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1100,7 +1100,7 @@ static int snd_dummy_suspend(struct device *pdev) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } - + static int snd_dummy_resume(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); -- cgit v1.2.3 From 446bc11f8614449782feac1d5ff270b3f98bcdf3 Mon Sep 17 00:00:00 2001 From: YJ Lee Date: Mon, 12 Sep 2022 15:29:45 +0800 Subject: ALSA: dummy: Add customizable volume min/max. Add module parameters to support customized min/max volume leveling, which will be useful to test devices with different volume granularity. Signed-off-by: YJ Lee Link: https://lore.kernel.org/r/20220912072945.760949-1-yunjunlee@chromium.org Signed-off-by: Takashi Iwai --- sound/drivers/dummy.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index fcf1ee00bd21..9c17b49a2ae1 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -42,6 +42,8 @@ MODULE_LICENSE("GPL"); #define USE_CHANNELS_MAX 2 #define USE_PERIODS_MIN 1 #define USE_PERIODS_MAX 1024 +#define USE_MIXER_VOLUME_LEVEL_MIN -50 +#define USE_MIXER_VOLUME_LEVEL_MAX 100 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -50,6 +52,8 @@ static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL}; static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; +static int mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN; +static int mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX; #ifdef CONFIG_HIGH_RES_TIMERS static bool hrtimer = 1; #endif @@ -69,6 +73,10 @@ module_param_array(pcm_substreams, int, NULL, 0444); MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver."); //module_param_array(midi_devs, int, NULL, 0444); //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver."); +module_param(mixer_volume_level_min, int, 0444); +MODULE_PARM_DESC(mixer_volume_level_min, "Minimum mixer volume level for dummy driver. Default: -50"); +module_param(mixer_volume_level_max, int, 0444); +MODULE_PARM_DESC(mixer_volume_level_max, "Maximum mixer volume level for dummy driver. Default: 100"); module_param(fake_buffer, bool, 0444); MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations."); #ifdef CONFIG_HIGH_RES_TIMERS @@ -713,8 +721,8 @@ static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; - uinfo->value.integer.min = -50; - uinfo->value.integer.max = 100; + uinfo->value.integer.min = mixer_volume_level_min; + uinfo->value.integer.max = mixer_volume_level_max; return 0; } @@ -739,15 +747,15 @@ static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, int left, right; left = ucontrol->value.integer.value[0]; - if (left < -50) - left = -50; - if (left > 100) - left = 100; + if (left < mixer_volume_level_min) + left = mixer_volume_level_min; + if (left > mixer_volume_level_max) + left = mixer_volume_level_max; right = ucontrol->value.integer.value[1]; - if (right < -50) - right = -50; - if (right > 100) - right = 100; + if (right < mixer_volume_level_min) + right = mixer_volume_level_min; + if (right > mixer_volume_level_max) + right = mixer_volume_level_max; spin_lock_irq(&dummy->mixer_lock); change = dummy->mixer_volume[addr][0] != left || dummy->mixer_volume[addr][1] != right; @@ -1076,6 +1084,12 @@ static int snd_dummy_probe(struct platform_device *devptr) dummy->pcm_hw.channels_max = m->channels_max; } + if (mixer_volume_level_min > mixer_volume_level_max) { + pr_warn("snd-dummy: Invalid mixer volume level: min=%d, max=%d. Fall back to default value.\n", + mixer_volume_level_min, mixer_volume_level_max); + mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN; + mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX; + } err = snd_card_dummy_new_mixer(dummy); if (err < 0) return err; -- cgit v1.2.3 From b2ddf399d0555d3b517ed97f35767c054bbc6535 Mon Sep 17 00:00:00 2001 From: Oder Chiou Date: Mon, 12 Sep 2022 15:29:31 +0800 Subject: ASoC: rt5640: Fix the issue of the abnormal JD2 status The patch fixes the issue of the abnormal JD2 status. Signed-off-by: Oder Chiou Reported-by: Sameer Pujar Link: https://lore.kernel.org/r/20220912072931.1856-1-oder_chiou@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 64 +++++++++++++++++++++++++++++++++-------------- sound/soc/codecs/rt5640.h | 14 +++++++++++ 2 files changed, 59 insertions(+), 19 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 5a844329800f..0f8e6dd214b0 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2494,7 +2494,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, /* Select JD-source */ snd_soc_component_update_bits(component, RT5640_JD_CTRL, - RT5640_JD_MASK, rt5640->jd_src); + RT5640_JD_MASK, rt5640->jd_src << RT5640_JD_SFT); /* Selecting GPIO01 as an interrupt */ snd_soc_component_update_bits(component, RT5640_GPIO_CTRL1, @@ -2504,12 +2504,8 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3, RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT); - /* Enabling jd2 in general control 1 */ snd_soc_component_write(component, RT5640_DUMMY1, 0x3f41); - /* Enabling jd2 in general control 2 */ - snd_soc_component_write(component, RT5640_DUMMY2, 0x4001); - rt5640_set_ovcd_params(component); /* @@ -2518,12 +2514,25 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, * pin 0/1 instead of it being stuck to 1. So we invert the JD polarity * on systems where the hardware does not already do this. */ - if (rt5640->jd_inverted) - snd_soc_component_write(component, RT5640_IRQ_CTRL1, - RT5640_IRQ_JD_NOR); - else - snd_soc_component_write(component, RT5640_IRQ_CTRL1, - RT5640_IRQ_JD_NOR | RT5640_JD_P_INV); + if (rt5640->jd_inverted) { + if (rt5640->jd_src == RT5640_JD_SRC_JD1_IN4P) + snd_soc_component_write(component, RT5640_IRQ_CTRL1, + RT5640_IRQ_JD_NOR); + else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits(component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | RT5640_JD2_EN); + } else { + if (rt5640->jd_src == RT5640_JD_SRC_JD1_IN4P) + snd_soc_component_write(component, RT5640_IRQ_CTRL1, + RT5640_IRQ_JD_NOR | RT5640_JD_P_INV); + else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits(component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | RT5640_JD2_P_MASK | + RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | RT5640_JD2_P_INV | + RT5640_JD2_EN); + } rt5640->jack = jack; if (rt5640->jack->status & SND_JACK_MICROPHONE) { @@ -2725,10 +2734,8 @@ static int rt5640_probe(struct snd_soc_component *component) if (device_property_read_u32(component->dev, "realtek,jack-detect-source", &val) == 0) { - if (val <= RT5640_JD_SRC_GPIO4) - rt5640->jd_src = val << RT5640_JD_SFT; - else if (val == RT5640_JD_SRC_HDA_HEADER) - rt5640->jd_src = RT5640_JD_SRC_HDA_HEADER; + if (val <= RT5640_JD_SRC_HDA_HEADER) + rt5640->jd_src = val; else dev_warn(component->dev, "Warning: Invalid jack-detect-source value: %d, leaving jack-detect disabled\n", val); @@ -2809,12 +2816,31 @@ static int rt5640_resume(struct snd_soc_component *component) regcache_sync(rt5640->regmap); if (rt5640->jack) { - if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) + if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) { snd_soc_component_update_bits(component, RT5640_DUMMY2, 0x1100, 0x1100); - else - snd_soc_component_write(component, RT5640_DUMMY2, - 0x4001); + } else { + if (rt5640->jd_inverted) { + if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits( + component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | + RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | + RT5640_JD2_EN); + + } else { + if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits( + component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | + RT5640_JD2_P_MASK | + RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | + RT5640_JD2_P_INV | + RT5640_JD2_EN); + } + } queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); } diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h index 505c93514051..f58b88e3325b 100644 --- a/sound/soc/codecs/rt5640.h +++ b/sound/soc/codecs/rt5640.h @@ -1984,6 +1984,20 @@ #define RT5640_M_MONO_ADC_R_SFT 12 #define RT5640_MCLK_DET (0x1 << 11) +/* General Control 1 (0xfb) */ +#define RT5640_IRQ_JD2_MASK (0x1 << 12) +#define RT5640_IRQ_JD2_SFT 12 +#define RT5640_IRQ_JD2_BP (0x0 << 12) +#define RT5640_IRQ_JD2_NOR (0x1 << 12) +#define RT5640_JD2_P_MASK (0x1 << 10) +#define RT5640_JD2_P_SFT 10 +#define RT5640_JD2_P_NOR (0x0 << 10) +#define RT5640_JD2_P_INV (0x1 << 10) +#define RT5640_JD2_MASK (0x1 << 8) +#define RT5640_JD2_SFT 8 +#define RT5640_JD2_DIS (0x0 << 8) +#define RT5640_JD2_EN (0x1 << 8) + /* Codec Private Register definition */ /* MIC Over current threshold scale factor (0x15) */ -- cgit v1.2.3 From 4d40ceef4745536289012670103c59264e0fb3ec Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 12 Sep 2022 21:37:16 +0300 Subject: ALSA: hda: add Intel 5 Series / 3400 PCI DID Handle 0x3b57 variant with same AZX_DCAPS_INTEL_PCH_NOPM capabilities as 0x3b56. In practise this allow use of HDMI/DP display audio via i915. BugLink: https://gitlab.freedesktop.org/drm/intel/-/issues/2751 Signed-off-by: Kai Vehmanen Cc: Link: https://lore.kernel.org/r/20220912183716.2126312-1-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b20694fd69de..6f30c374f896 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2550,6 +2550,8 @@ static const struct pci_device_id azx_ids[] = { /* 5 Series/3400 */ { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, + { PCI_DEVICE(0x8086, 0x3b57), + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* Poulsbo */ { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE }, -- cgit v1.2.3 From 3c4d8c24fb6c44f426e447b04800b0ed61a7b5ae Mon Sep 17 00:00:00 2001 From: Mohan Kumar Date: Tue, 13 Sep 2022 11:06:41 +0530 Subject: ALSA: hda/tegra: set depop delay for tegra Reduce the suspend time by setting depop delay to 10ms for tegra. Signed-off-by: Mohan Kumar Cc: Link: https://lore.kernel.org/r/20220913053641.23299-1-mkumard@nvidia.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6c209cd26c0c..acaf6b790ee1 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -3984,6 +3984,7 @@ static int tegra_hdmi_init(struct hda_codec *codec) generic_hdmi_init_per_pins(codec); + codec->depop_delay = 10; codec->patch_ops.build_pcms = tegra_hdmi_build_pcms; spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; -- cgit v1.2.3 From cbcdf8c4d35cd74aee8581eb2f0453e0ecab7b05 Mon Sep 17 00:00:00 2001 From: huangwenhui Date: Tue, 13 Sep 2022 13:46:22 +0800 Subject: ALSA: hda/realtek: Add quirk for Huawei WRT-WX9 Fixes headphone and headset microphone detection on Huawei WRT-WX9. Signed-off-by: huangwenhui Cc: Link: https://lore.kernel.org/r/20220913054622.15979-1-huangwenhuia@uniontech.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 38930cf5aace..0996a8fd008c 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9569,6 +9569,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK), SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), + SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20), SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI), SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101), -- cgit v1.2.3 From f89e409402e2aeb3bc3aa44d2b7a597959e4e6af Mon Sep 17 00:00:00 2001 From: Mohan Kumar Date: Tue, 13 Sep 2022 12:28:18 +0530 Subject: ALSA: hda: Fix Nvidia dp infoframe Nvidia HDA HW expects infoframe data bytes order same for both HDMI and DP i.e infoframe data starts from 5th bytes offset. As dp infoframe structure has 4th byte as valid infoframe data, use hdmi infoframe structure for nvidia dp infoframe to match HW behvaior. Signed-off-by: Mohan Kumar Cc: Link: https://lore.kernel.org/r/20220913065818.13015-1-mkumard@nvidia.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index acaf6b790ee1..c9d9aa6351ec 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -170,6 +170,8 @@ struct hdmi_spec { bool dyn_pcm_no_legacy; /* hdmi interrupt trigger control flag for Nvidia codec */ bool hdmi_intr_trig_ctrl; + bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */ + bool intel_hsw_fixup; /* apply Intel platform-specific fixups */ /* * Non-generic VIA/NVIDIA specific @@ -679,15 +681,24 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, int ca, int active_channels, int conn_type) { + struct hdmi_spec *spec = codec->spec; union audio_infoframe ai; memset(&ai, 0, sizeof(ai)); - if (conn_type == 0) { /* HDMI */ + if ((conn_type == 0) || /* HDMI */ + /* Nvidia DisplayPort: Nvidia HW expects same layout as HDMI */ + (conn_type == 1 && spec->nv_dp_workaround)) { struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; - hdmi_ai->type = 0x84; - hdmi_ai->ver = 0x01; - hdmi_ai->len = 0x0a; + if (conn_type == 0) { /* HDMI */ + hdmi_ai->type = 0x84; + hdmi_ai->ver = 0x01; + hdmi_ai->len = 0x0a; + } else {/* Nvidia DP */ + hdmi_ai->type = 0x84; + hdmi_ai->ver = 0x1b; + hdmi_ai->len = 0x11 << 2; + } hdmi_ai->CC02_CT47 = active_channels - 1; hdmi_ai->CA = ca; hdmi_checksum_audio_infoframe(hdmi_ai); @@ -3617,6 +3628,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) spec->pcm_playback.rates = SUPPORTED_RATES; spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; spec->pcm_playback.formats = SUPPORTED_FORMATS; + spec->nv_dp_workaround = true; return 0; } @@ -3756,6 +3768,7 @@ static int patch_nvhdmi(struct hda_codec *codec) spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + spec->nv_dp_workaround = true; codec->link_down_at_suspend = 1; @@ -3779,6 +3792,7 @@ static int patch_nvhdmi_legacy(struct hda_codec *codec) spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + spec->nv_dp_workaround = true; codec->link_down_at_suspend = 1; @@ -3993,6 +4007,7 @@ static int tegra_hdmi_init(struct hda_codec *codec) spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + spec->nv_dp_workaround = true; return 0; } -- cgit v1.2.3 From 4053a41282f8aae290d3fe7b8daef4c8c53a4ab8 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 13 Sep 2022 09:03:07 +0200 Subject: ALSA: hda/hdmi: change type for the 'assigned' variable This change converts the assigned value from int type to the bool type to retain consistency with other structure members like 'setup', 'non_pcm' etc. Signed-off-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220913070307.3234038-1-perex@perex.cz Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 429cb4b23a1c..1ab7541a63db 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -53,7 +53,7 @@ MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins"); struct hdmi_spec_per_cvt { hda_nid_t cvt_nid; - int assigned; + bool assigned; /* the stream has been assigned */ unsigned int channels_min; unsigned int channels_max; u32 rates; @@ -1193,7 +1193,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, return err; per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 1; + per_cvt->assigned = true; hinfo->nid = per_cvt->cvt_nid; pin_cvt_fixup(codec, NULL, per_cvt->cvt_nid); @@ -1262,7 +1262,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, per_cvt = get_cvt(spec, cvt_idx); /* Claim converter */ - per_cvt->assigned = 1; + per_cvt->assigned = true; set_bit(pcm_idx, &spec->pcm_in_use); per_pin = get_pin(spec, pin_idx); @@ -1296,7 +1296,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, snd_hdmi_eld_update_pcm_info(&eld->info, hinfo); if (hinfo->channels_min > hinfo->channels_max || !hinfo->rates || !hinfo->formats) { - per_cvt->assigned = 0; + per_cvt->assigned = false; hinfo->nid = 0; snd_hda_spdif_ctls_unassign(codec, pcm_idx); err = -ENODEV; @@ -1755,7 +1755,7 @@ static void silent_stream_enable(struct hda_codec *codec, } per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 1; + per_cvt->assigned = true; per_pin->cvt_nid = per_cvt->cvt_nid; per_pin->silent_stream = true; @@ -1815,7 +1815,7 @@ static void silent_stream_disable(struct hda_codec *codec, cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid); if (cvt_idx >= 0 && cvt_idx < spec->num_cvts) { per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 0; + per_cvt->assigned = false; } if (spec->silent_stream_type == SILENT_STREAM_I915) { @@ -2211,7 +2211,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, goto unlock; } per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 0; + per_cvt->assigned = false; hinfo->nid = 0; azx_stream(get_azx_dev(substream))->stripe = 0; -- cgit v1.2.3 From d56ba9a04d7548d4149c46ec86a0e3cc41a70f4a Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Tue, 13 Sep 2022 17:00:01 +0800 Subject: ASoC: imx-card: Fix refcount issue with of_node_put imx_card_parse_of will search all the node with loop, if there is defer probe happen in the middle of loop, the previous released codec node will be released twice, then cause refcount issue. Here assign NULL to pointer of released nodes to fix the issue. Fixes: aa736700f42f ("ASoC: imx-card: Add imx-card machine driver") Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1663059601-29259-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-card.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'sound') diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 14be29530fb5..3f128ced4180 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -698,6 +698,10 @@ static int imx_card_parse_of(struct imx_card_data *data) of_node_put(cpu); of_node_put(codec); of_node_put(platform); + + cpu = NULL; + codec = NULL; + platform = NULL; } return 0; -- cgit v1.2.3 From a74bfc9eaa497951effddefbcb18f1c7ab56fb35 Mon Sep 17 00:00:00 2001 From: Gaosheng Cui Date: Mon, 22 Aug 2022 11:51:33 +0800 Subject: ASoC: Intel: fix unused-variable warning in probe_codec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In configurations with CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC=n, gcc warns about an unused variable: sound/soc/intel/skylake/skl.c: In function ‘probe_codec’: sound/soc/intel/skylake/skl.c:729:18: error: unused variable ‘skl’ [-Werror=unused-variable] struct skl_dev *skl = bus_to_skl(bus); ^~~ cc1: all warnings being treated as errors Fixes: 3fd63658caed9 ("ASoC: Intel: Drop hdac_ext usage for codec device creation") Signed-off-by: Gaosheng Cui Acked-by: Cezary Rojewski Link: https://lore.kernel.org/r/20220822035133.2147381-1-cuigaosheng1@huawei.com Signed-off-by: Takashi Iwai --- sound/soc/intel/skylake/skl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index c7c1cad2a753..52a041d6144c 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -726,8 +726,8 @@ static int probe_codec(struct hdac_bus *bus, int addr) unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; unsigned int res = -1; - struct skl_dev *skl = bus_to_skl(bus); #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) + struct skl_dev *skl = bus_to_skl(bus); struct hdac_hda_priv *hda_codec; #endif struct hda_codec *codec; -- cgit v1.2.3 From bdc9b7396f7d4d6533e70fd8d5472f505b5ef58f Mon Sep 17 00:00:00 2001 From: Callum Osmotherly Date: Wed, 14 Sep 2022 18:44:00 +0930 Subject: ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5570 laptop The Dell Precision 5570 uses the same 4-speakers-on-ALC289 just like the previous Precision 5560. I replicated that patch onto this one, and can confirm that the audio is much better (the woofers are now working); I've tested it on my Dell Precision 5570. Signed-off-by: Callum Osmotherly Cc: Link: https://lore.kernel.org/r/YyGbWM5wEoFMbW2v@piranha Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0996a8fd008c..e722885da5f6 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9165,6 +9165,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0a9d, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), -- cgit v1.2.3 From 39efc9c8a973ddff5918191525d1679d0fb368ea Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 15 Sep 2022 10:59:47 +0200 Subject: ALSA: usb-audio: Fix last interface check for registration The recent fix in commit 6392dcd1d0c7 ("ALSA: usb-audio: Register card at the last interface") tried to delay the card registration until the last found interface is probed. It assumed that the probe callback gets called for those later interfaces, but it's not always true; as the driver loops over the descriptor and probes the matching ones, it's not separately called via multiple probe calls. This results in the missing card registration, i.e. no sound device. For addressing this problem, replace the check whether the last interface is processed with usb_interface_claimed() instead of the comparison with the probe interface number. Fixes: 6392dcd1d0c7 ("ALSA: usb-audio: Register card at the last interface") Link: https://lore.kernel.org/r/20220915085947.7922-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/card.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/usb/card.c b/sound/usb/card.c index 3aea241435fb..a5ed11ea1145 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -884,7 +884,7 @@ static int usb_audio_probe(struct usb_interface *intf, * one given via option */ if (check_delayed_register_option(chip) == ifnum || - chip->last_iface == ifnum) { + usb_interface_claimed(usb_ifnum_to_if(dev, chip->last_iface))) { err = snd_card_register(chip->card); if (err < 0) goto __error; -- cgit v1.2.3 From 1885ff13d4c42910b37a0e3f7c2f182520f4eed1 Mon Sep 17 00:00:00 2001 From: Callum Osmotherly Date: Thu, 15 Sep 2022 22:36:08 +0930 Subject: ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop Just as with the 5570 (and the other Dell laptops), this enables the two subwoofer speakers on the Dell Precision 5530 together with the main ones, significantly increasing the audio quality. I've tested this myself on a 5530 and can confirm it's working as expected. Signed-off-by: Callum Osmotherly Cc: Link: https://lore.kernel.org/r/YyMjQO3mhyXlMbCf@piranha Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e722885da5f6..d309304cdc46 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9149,6 +9149,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB), + SND_PCI_QUIRK(0x1028, 0x087d, "Dell Precision 5530", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), -- cgit v1.2.3 From b16c8f229a58eaddfc58aab447253464abd3c85e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 15 Sep 2022 17:47:24 +0200 Subject: ALSA: hda/realtek: Re-arrange quirk table entries A few entries have been mistakenly inserted in wrong positions without considering the SSID ordering. Place them at right positions. Fixes: b7557267c233 ("ALSA: hda/realtek: Add quirk for ASUS GA402") Fixes: 94db9cc8f8fa ("ALSA: hda/realtek: Add quirk for ASUS GU603") Fixes: 739d0959fbed ("ALSA: hda: Add quirk for ASUS Flow x13") Cc: Link: https://lore.kernel.org/r/20220915154724.31634-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d309304cdc46..90fde53e6956 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9341,10 +9341,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), + SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), + SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS), SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), - SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS), SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC), @@ -9361,13 +9362,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), - SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), - SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), -- cgit v1.2.3 From c611e659044168e7abcbae8ba1ea833521498fbb Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 15 Sep 2022 20:09:19 +1200 Subject: ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack Fixes up the pincfg for ASUS ROG Strix G513 headphone and mic combo jack [ Fixed the position in the quirk table by tiwai ] Signed-off-by: Luke D. Jones Cc: Link: https://lore.kernel.org/r/20220915080921.35563-2-luke@ljones.dev Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 90fde53e6956..5ab20059e4dd 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7067,6 +7067,7 @@ enum { ALC294_FIXUP_ASUS_GU502_HP, ALC294_FIXUP_ASUS_GU502_PINS, ALC294_FIXUP_ASUS_GU502_VERBS, + ALC294_FIXUP_ASUS_G513_PINS, ALC285_FIXUP_HP_GPIO_LED, ALC285_FIXUP_HP_MUTE_LED, ALC236_FIXUP_HP_GPIO_LED, @@ -8405,6 +8406,15 @@ static const struct hda_fixup alc269_fixups[] = { [ALC294_FIXUP_ASUS_GU502_HP] = { .type = HDA_FIXUP_FUNC, .v.func = alc294_fixup_gu502_hp, + }, + [ALC294_FIXUP_ASUS_G513_PINS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x03a11050 }, /* front HP mic */ + { 0x1a, 0x03a11c30 }, /* rear external mic */ + { 0x21, 0x03211420 }, /* front HP out */ + { } + }, }, [ALC294_FIXUP_ASUS_COEF_1B] = { .type = HDA_FIXUP_VERBS, @@ -9366,6 +9376,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), + SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), -- cgit v1.2.3 From bc2c23549ccd7105eb6ff0d4f0ac519285628673 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 15 Sep 2022 20:09:20 +1200 Subject: ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack Fixes up the pincfg for ASUS ROG Strix G15 (G533Z) headphone combo jack [ Fixed the position in the quirk table by tiwai ] Signed-off-by: Luke D. Jones Cc: Link: https://lore.kernel.org/r/20220915080921.35563-3-luke@ljones.dev Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5ab20059e4dd..de8c29d65362 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7068,6 +7068,7 @@ enum { ALC294_FIXUP_ASUS_GU502_PINS, ALC294_FIXUP_ASUS_GU502_VERBS, ALC294_FIXUP_ASUS_G513_PINS, + ALC285_FIXUP_ASUS_G533Z_PINS, ALC285_FIXUP_HP_GPIO_LED, ALC285_FIXUP_HP_MUTE_LED, ALC236_FIXUP_HP_GPIO_LED, @@ -8416,6 +8417,15 @@ static const struct hda_fixup alc269_fixups[] = { { } }, }, + [ALC285_FIXUP_ASUS_G533Z_PINS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x14, 0x90170120 }, + { } + }, + .chained = true, + .chain_id = ALC294_FIXUP_ASUS_G513_PINS, + }, [ALC294_FIXUP_ASUS_COEF_1B] = { .type = HDA_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -9371,6 +9381,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), -- cgit v1.2.3 From ba1f818053b0668a1ce2fe86b840e81b592cc560 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Thu, 15 Sep 2022 20:09:21 +1200 Subject: ALSA: hda/realtek: Add quirk for ASUS GA503R laptop The ASUS G15 2022 (GA503R) series laptop has the same node-to-DAC pairs as early models and the G14, this includes bass speakers which are by default mapped incorrectly to the 0x06 node. Add a quirk to use the same DAC pairs as the G14. Signed-off-by: Luke D. Jones Cc: Link: https://lore.kernel.org/r/20220915080921.35563-4-luke@ljones.dev Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index de8c29d65362..ab0ee0565706 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9389,6 +9389,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), -- cgit v1.2.3 From 5f80d6bd2b01de4cafac3302f58456bf860322fc Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Tue, 13 Sep 2022 09:02:16 +0200 Subject: ALSA: hda/hdmi: Fix the converter reuse for the silent stream When the user space pcm stream uses the silent stream converter, it is no longer allocated for the silent stream. Clear the appropriate flag in the hdmi_pcm_open() function. The silent stream setup may be applied in hdmi_pcm_close() (and the error path - open fcn) again. If the flag is not cleared, the reuse conditions for the silent stream converter in hdmi_choose_cvt() may improperly share this converter. Cc: Kai Vehmanen Signed-off-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220913070216.3233974-1-perex@perex.cz Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c9d9aa6351ec..c239d9dbbaef 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1278,6 +1278,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, set_bit(pcm_idx, &spec->pcm_in_use); per_pin = get_pin(spec, pin_idx); per_pin->cvt_nid = per_cvt->cvt_nid; + per_pin->silent_stream = false; hinfo->nid = per_cvt->cvt_nid; /* flip stripe flag for the assigned stream if supported */ -- cgit v1.2.3 From 7883017bbcc55fcb1888add3dc825e112d7ae336 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Fri, 16 Sep 2022 22:11:08 +0800 Subject: ALSA: ppc: Switch to use for_each_child_of_node() macro Use for_each_child_of_node() macro instead of open coding it. No functional change. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20220916141108.683080-1-yangyingliang@huawei.com Signed-off-by: Takashi Iwai --- sound/ppc/tumbler.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index c65e74d7cd0a..f3f8ad7c3df8 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -1060,8 +1060,7 @@ static struct device_node *find_audio_device(const char *name) if (! gpiop) return NULL; - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { + for_each_child_of_node(gpiop, np) { const char *property = of_get_property(np, "audio-gpio", NULL); if (property && strcmp(property, name) == 0) break; @@ -1080,8 +1079,7 @@ static struct device_node *find_compatible_audio_device(const char *name) if (!gpiop) return NULL; - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { + for_each_child_of_node(gpiop, np) { if (of_device_is_compatible(np, name)) break; } -- cgit v1.2.3 From 496322302bf1e58dc2ff134173527493105f51ab Mon Sep 17 00:00:00 2001 From: Daniel Houldsworth Date: Sun, 18 Sep 2022 18:13:00 +0100 Subject: ALSA: hda/realtek: Add a quirk for HP OMEN 16 (8902) mute LED Similair to the HP OMEN 15, the HP OMEN 16 also needs ALC285_FIXUP_HP_MUTE_LED for the mute LED to work. [ Rearranged the entry in PCI SSID order by tiwai ] Signed-off-by: Daniel Houldsworth Cc: Link: https://lore.kernel.org/r/20220918171300.24693-1-dhould3@gmail.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ab0ee0565706..f9d46ae4c7b7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9314,6 +9314,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x896e, "HP EliteBook x360 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8971, "HP EliteBook 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8972, "HP EliteBook 840 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), -- cgit v1.2.3 From c3afa2a402d1ecefa59f88d55d9e765f52f75bd9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 19 Sep 2022 14:35:16 +0200 Subject: ALSA: core: Fix double-free at snd_card_new() During the code change to add the support for devres-managed card instance, we put an explicit kfree(card) call at the error path in snd_card_new(). This is needed for the early error path before the card is initialized with the device, but is rather superfluous and causes a double-free at the error path after the card instance is initialized, as the destructor of the card object already contains a kfree() call. This patch fixes the double-free situation by removing the superfluous kfree(). Meanwhile we need to call kfree() explicitly for the early error path, so it's added there instead. Fixes: e8ad415b7a55 ("ALSA: core: Add managed card creation") Reported-by: Rondreis Cc: Link: https://lore.kernel.org/r/CAB7eexL1zBnB636hwS27d-LdPYZ_R1-5fJS_h=ZbCWYU=UPWJg@mail.gmail.com Link: https://lore.kernel.org/r/20220919123516.28222-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/init.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sound') diff --git a/sound/core/init.c b/sound/core/init.c index 193dae361fac..5377f94eb211 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -178,10 +178,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, return -ENOMEM; err = snd_card_init(card, parent, idx, xid, module, extra_size); - if (err < 0) { - kfree(card); - return err; - } + if (err < 0) + return err; /* card is freed by error handler */ *card_ret = card; return 0; @@ -233,7 +231,7 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid, card->managed = true; err = snd_card_init(card, parent, idx, xid, module, extra_size); if (err < 0) { - devres_free(card); + devres_free(card); /* in managed mode, we need to free manually */ return err; } @@ -297,6 +295,8 @@ static int snd_card_init(struct snd_card *card, struct device *parent, mutex_unlock(&snd_card_mutex); dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n", idx, snd_ecards_limit - 1, err); + if (!card->managed) + kfree(card); /* manually free here, as no destructor called */ return err; } set_bit(idx, snd_cards_lock); /* lock it */ -- cgit v1.2.3 From 4a13c949501902d4e6b59cc693005f4ca352dc15 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 13:46:40 +0200 Subject: ASoC: Intel: sof_sdw: add support for Dell SKU 0AFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yet another SKU that needs a quirk for jack detection and four-speaker support. BugLink: https://github.com/thesofproject/linux/issues/3777 Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220919114640.42803-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sound') diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index a49bfaab6b21..2ff30b40a1e4 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -266,6 +266,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_FOUR_SPK), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + RT711_JD2 | + SOF_SDW_FOUR_SPK), + }, { .callback = sof_sdw_quirk_cb, .matches = { -- cgit v1.2.3 From 7042bde216ada135b2f88423ae714ab9a22e3a22 Mon Sep 17 00:00:00 2001 From: SJLIN0 Date: Thu, 15 Sep 2022 09:28:00 +0800 Subject: ASoC: nau8824: Fix semaphore is released unexpectedly On resuming, we anticipate that the jack is detected before playback or capture. Therefore, we use semaphore to control the jack detection done without any bothering. During booting, the driver launches jack detection and releases the semaphore. However, it doesn't perceive the maniputation of semaphore is not like resuming procedure. This makes the semaphore's count value become to 2. There is more than one thread can enter into the critical section. This may get unexpected situation and make some chaos. Signed-off-by: SJLIN0 Signed-off-by: Wallace Lin Link: https://lore.kernel.org/r/20220915012800.825196-1-SJLIN0@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8824.c | 17 ++++++++++++++--- sound/soc/codecs/nau8824.h | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c index 15596452ca37..4f19fd9b65d1 100644 --- a/sound/soc/codecs/nau8824.c +++ b/sound/soc/codecs/nau8824.c @@ -901,7 +901,10 @@ static void nau8824_jdet_work(struct work_struct *work) NAU8824_IRQ_KEY_RELEASE_DIS | NAU8824_IRQ_KEY_SHORT_PRESS_DIS, 0); - nau8824_sema_release(nau8824); + if (nau8824->resume_lock) { + nau8824_sema_release(nau8824); + nau8824->resume_lock = false; + } } static void nau8824_setup_auto_irq(struct nau8824 *nau8824) @@ -966,7 +969,10 @@ static irqreturn_t nau8824_interrupt(int irq, void *data) /* release semaphore held after resume, * and cancel jack detection */ - nau8824_sema_release(nau8824); + if (nau8824->resume_lock) { + nau8824_sema_release(nau8824); + nau8824->resume_lock = false; + } cancel_work_sync(&nau8824->jdet_work); } else if (active_irq & NAU8824_KEY_SHORT_PRESS_IRQ) { int key_status, button_pressed; @@ -1524,6 +1530,7 @@ static int __maybe_unused nau8824_suspend(struct snd_soc_component *component) static int __maybe_unused nau8824_resume(struct snd_soc_component *component) { struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component); + int ret; regcache_cache_only(nau8824->regmap, false); regcache_sync(nau8824->regmap); @@ -1531,7 +1538,10 @@ static int __maybe_unused nau8824_resume(struct snd_soc_component *component) /* Hold semaphore to postpone playback happening * until jack detection done. */ - nau8824_sema_acquire(nau8824, 0); + nau8824->resume_lock = true; + ret = nau8824_sema_acquire(nau8824, 0); + if (ret) + nau8824->resume_lock = false; enable_irq(nau8824->irq); } @@ -1940,6 +1950,7 @@ static int nau8824_i2c_probe(struct i2c_client *i2c) nau8824->regmap = devm_regmap_init_i2c(i2c, &nau8824_regmap_config); if (IS_ERR(nau8824->regmap)) return PTR_ERR(nau8824->regmap); + nau8824->resume_lock = false; nau8824->dev = dev; nau8824->irq = i2c->irq; sema_init(&nau8824->jd_sem, 1); diff --git a/sound/soc/codecs/nau8824.h b/sound/soc/codecs/nau8824.h index de4bae8281d0..5fcfc43dfc85 100644 --- a/sound/soc/codecs/nau8824.h +++ b/sound/soc/codecs/nau8824.h @@ -436,6 +436,7 @@ struct nau8824 { struct semaphore jd_sem; int fs; int irq; + int resume_lock; int micbias_voltage; int vref_impedance; int jkdet_polarity; -- cgit v1.2.3 From 0a0342ede303fc420f3a388e1ae82da3ae8ff6bd Mon Sep 17 00:00:00 2001 From: Martin Povišer Date: Mon, 19 Sep 2022 19:34:53 +0200 Subject: ASoC: tas2770: Reinit regcache on reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On probe of the ASoC component, the device is reset but the regcache is retained. This means the regcache gets out of sync if the codec is rebound to a sound card for a second time. Fix it by reinitializing the regcache to defaults after the device is reset. Fixes: b0bcbe615756 ("ASoC: tas2770: Fix calling reset in probe") Signed-off-by: Martin Povišer Link: https://lore.kernel.org/r/20220919173453.84292-1-povik+lin@cutebit.org Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index bb653b664146..b6765235a4b3 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -495,6 +495,8 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = { }, }; +static const struct regmap_config tas2770_i2c_regmap; + static int tas2770_codec_probe(struct snd_soc_component *component) { struct tas2770_priv *tas2770 = @@ -508,6 +510,7 @@ static int tas2770_codec_probe(struct snd_soc_component *component) } tas2770_reset(tas2770); + regmap_reinit_cache(tas2770->regmap, &tas2770_i2c_regmap); return 0; } -- cgit v1.2.3 From fc6f923ecfa2fafd0600f1b7e2de09baf29865e2 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 19 Sep 2022 15:54:44 +0200 Subject: ALSA: hda/hdmi: Fix the converter allocation for the silent stream Track the converters handling the silent stream using a new variable to avoid mixing of the open/close and silent stream use. This change ensures the proper allocation of the converters. Fixes: 5f80d6bd2b01 ("ALSA: hda/hdmi: Fix the converter reuse for the silent stream") Signed-off-by: Jaroslav Kysela Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919135444.3554982-1-perex@perex.cz Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 17f08bf4be14..1eb894e6cdf1 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -54,6 +54,7 @@ MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins"); struct hdmi_spec_per_cvt { hda_nid_t cvt_nid; bool assigned; /* the stream has been assigned */ + bool silent_stream; /* silent stream activated */ unsigned int channels_min; unsigned int channels_max; u32 rates; @@ -988,7 +989,8 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, * of the pin. */ static int hdmi_choose_cvt(struct hda_codec *codec, - int pin_idx, int *cvt_id) + int pin_idx, int *cvt_id, + bool silent) { struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; @@ -1003,6 +1005,9 @@ static int hdmi_choose_cvt(struct hda_codec *codec, if (per_pin && per_pin->silent_stream) { cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid); + per_cvt = get_cvt(spec, cvt_idx); + if (per_cvt->assigned && !silent) + return -EBUSY; if (cvt_id) *cvt_id = cvt_idx; return 0; @@ -1013,7 +1018,7 @@ static int hdmi_choose_cvt(struct hda_codec *codec, per_cvt = get_cvt(spec, cvt_idx); /* Must not already be assigned */ - if (per_cvt->assigned) + if (per_cvt->assigned || per_cvt->silent_stream) continue; if (per_pin == NULL) break; @@ -1199,7 +1204,7 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, if (pcm_idx < 0) return -EINVAL; - err = hdmi_choose_cvt(codec, -1, &cvt_idx); + err = hdmi_choose_cvt(codec, -1, &cvt_idx, false); if (err) return err; @@ -1267,7 +1272,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, } } - err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, false); if (err < 0) goto unlock; @@ -1278,7 +1283,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, set_bit(pcm_idx, &spec->pcm_in_use); per_pin = get_pin(spec, pin_idx); per_pin->cvt_nid = per_cvt->cvt_nid; - per_pin->silent_stream = false; hinfo->nid = per_cvt->cvt_nid; /* flip stripe flag for the assigned stream if supported */ @@ -1760,14 +1764,14 @@ static void silent_stream_enable(struct hda_codec *codec, } pin_idx = pin_id_to_pin_index(codec, per_pin->pin_nid, per_pin->dev_id); - err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, true); if (err) { codec_err(codec, "hdmi: no free converter to enable silent mode\n"); goto unlock_out; } per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = true; + per_cvt->silent_stream = true; per_pin->cvt_nid = per_cvt->cvt_nid; per_pin->silent_stream = true; @@ -1827,7 +1831,7 @@ static void silent_stream_disable(struct hda_codec *codec, cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid); if (cvt_idx >= 0 && cvt_idx < spec->num_cvts) { per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = false; + per_cvt->silent_stream = false; } if (spec->silent_stream_type == SILENT_STREAM_I915) { -- cgit v1.2.3 From 2ea13c83bf7bb3471e33b2d902b101af977ef2d4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:34 +0200 Subject: ALSA: hda: make snd_hdac_stream_clear() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helper has no users outside of hdac_stream.c. External users should only use snd_hdac_stream_start() and snd_hdac_stream_stop(). No functional change beyond making the function static and removing the symbol export. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 1 - sound/hda/hdac_stream.c | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 6e74aeafeda4..24c731e53ccb 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -561,7 +561,6 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev); int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, unsigned int format_val); void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start); -void snd_hdac_stream_clear(struct hdac_stream *azx_dev); void snd_hdac_stream_stop(struct hdac_stream *azx_dev); void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus); void snd_hdac_stream_reset(struct hdac_stream *azx_dev); diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index bdf6d4db6769..2dbde3d1cf68 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -112,10 +112,10 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start) EXPORT_SYMBOL_GPL(snd_hdac_stream_start); /** - * snd_hdac_stream_clear - stop a stream DMA + * snd_hdac_stream_clear - helper to clear stream registers and stop DMA transfers * @azx_dev: HD-audio core stream to stop */ -void snd_hdac_stream_clear(struct hdac_stream *azx_dev) +static void snd_hdac_stream_clear(struct hdac_stream *azx_dev) { snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_DMA_START | SD_INT_MASK, 0); @@ -124,7 +124,6 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev) snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); azx_dev->running = false; } -EXPORT_SYMBOL_GPL(snd_hdac_stream_clear); /** * snd_hdac_stream_stop - stop a stream -- cgit v1.2.3 From ea2ddd2559dc6d1c4b66ccd49314add35ece9062 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:35 +0200 Subject: ALSA: hda: document state machine for hdac_streams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code in this library is far from self-explanatory, hopefully this state diagram reverse-engineered from the code will help others understand the expected transitions. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/hdac_stream.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'sound') diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 2dbde3d1cf68..2e98f5fd50e5 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -13,6 +13,39 @@ #include #include "trace.h" +/* + * the hdac_stream library is intended to be used with the following + * transitions. The states are not formally defined in the code but loosely + * inspired by boolean variables. Note that the 'prepared' field is not used + * in this library but by the callers during the hw_params/prepare transitions + * + * | + * stream_init() | + * v + * +--+-------+ + * | unused | + * +--+----+--+ + * | ^ + * stream_assign() | | stream_release() + * v | + * +--+----+--+ + * | opened | + * +--+----+--+ + * | ^ + * stream_reset() | | + * stream_setup() | | stream_cleanup() + * v | + * +--+----+--+ + * | prepared | + * +--+----+--+ + * | ^ + * stream_start() | | stream_stop() + * v | + * +--+----+--+ + * | running | + * +----------+ + */ + /** * snd_hdac_get_stream_stripe_ctl - get stripe control value * @bus: HD-audio core bus -- cgit v1.2.3 From 791d132a070a8358227b008c0ddda5f4d6f32cc2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:36 +0200 Subject: ALSA: hda: ext: make snd_hdac_ext_stream_init() static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no external users of this helper, move to static and remove sympol export. No functionality change. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio_ext.h | 3 --- sound/hda/ext/hdac_ext_stream.c | 7 +++---- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index 07231f0b93b5..4a4bd1d88612 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -77,9 +77,6 @@ struct hdac_ext_stream { #define stream_to_hdac_ext_stream(s) \ container_of(s, struct hdac_ext_stream, hstream) -void snd_hdac_ext_stream_init(struct hdac_bus *bus, - struct hdac_ext_stream *hext_stream, int idx, - int direction, int tag); int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir); void snd_hdac_stream_free_all(struct hdac_bus *bus); diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index d2b5724b463f..5c665b26f853 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -26,9 +26,9 @@ * initialize the stream, if ppcap is enabled then init those and then * invoke hdac stream initialization routine */ -void snd_hdac_ext_stream_init(struct hdac_bus *bus, - struct hdac_ext_stream *hext_stream, - int idx, int direction, int tag) +static void snd_hdac_ext_stream_init(struct hdac_bus *bus, + struct hdac_ext_stream *hext_stream, + int idx, int direction, int tag) { if (bus->ppcap) { hext_stream->pphc_addr = bus->ppcap + AZX_PPHC_BASE + @@ -56,7 +56,6 @@ void snd_hdac_ext_stream_init(struct hdac_bus *bus, hext_stream->decoupled = false; snd_hdac_stream_init(bus, &hext_stream->hstream, idx, direction, tag); } -EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init); /** * snd_hdac_ext_stream_init_all - create and initialize the stream objects -- cgit v1.2.3 From 0839a04eff9778c3dc37d3a1bb8014a3386dece7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:37 +0200 Subject: ALSA: hda: Use hdac_ext prefix in snd_hdac_stream_free_all() for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure there's no ambiguity on layering with the appropriate prefix added. Pure rename, no functionality changed. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio_ext.h | 2 +- sound/hda/ext/hdac_ext_stream.c | 6 +++--- sound/soc/intel/avs/core.c | 4 ++-- sound/soc/intel/skylake/skl.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index 4a4bd1d88612..83aed26ab143 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -79,7 +79,7 @@ struct hdac_ext_stream { int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, int num_stream, int dir); -void snd_hdac_stream_free_all(struct hdac_bus *bus); +void snd_hdac_ext_stream_free_all(struct hdac_bus *bus); void snd_hdac_link_free_all(struct hdac_bus *bus); struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream, diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 5c665b26f853..9419abd7fc03 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -87,11 +87,11 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all); /** - * snd_hdac_stream_free_all - free hdac extended stream objects + * snd_hdac_ext_stream_free_all - free hdac extended stream objects * * @bus: HD-audio core bus */ -void snd_hdac_stream_free_all(struct hdac_bus *bus) +void snd_hdac_ext_stream_free_all(struct hdac_bus *bus) { struct hdac_stream *s, *_s; struct hdac_ext_stream *hext_stream; @@ -103,7 +103,7 @@ void snd_hdac_stream_free_all(struct hdac_bus *bus) kfree(hext_stream); } } -EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); +EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_free_all); void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, struct hdac_ext_stream *hext_stream, diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index c50c20fd681a..bb0719c58ca4 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -466,7 +466,7 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) err_acquire_irq: snd_hdac_bus_free_stream_pages(bus); - snd_hdac_stream_free_all(bus); + snd_hdac_ext_stream_free_all(bus); err_init_streams: iounmap(adev->dsp_ba); err_remap_bar4: @@ -502,7 +502,7 @@ static void avs_pci_remove(struct pci_dev *pci) snd_hda_codec_unregister(hdac_to_hda_codec(hdev)); snd_hdac_bus_free_stream_pages(bus); - snd_hdac_stream_free_all(bus); + snd_hdac_ext_stream_free_all(bus); /* reverse ml_capabilities */ snd_hdac_link_free_all(bus); snd_hdac_ext_bus_exit(bus); diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 52a041d6144c..0122926f9c58 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -444,7 +444,7 @@ static int skl_free(struct hdac_bus *bus) if (bus->irq >= 0) free_irq(bus->irq, (void *)bus); snd_hdac_bus_free_stream_pages(bus); - snd_hdac_stream_free_all(bus); + snd_hdac_ext_stream_free_all(bus); snd_hdac_link_free_all(bus); if (bus->remap_addr) -- cgit v1.2.3 From 24ad3835a6db4f8857975effa6bf47730371a5ff Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:38 +0200 Subject: ALSA: hda: add snd_hdac_stop_streams() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor code reuse, no functionality change. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 1 + sound/hda/hdac_stream.c | 17 ++++++++++++++--- sound/pci/hda/hda_controller.c | 4 +--- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 24c731e53ccb..35459d740f00 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -562,6 +562,7 @@ int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, unsigned int format_val); void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start); void snd_hdac_stream_stop(struct hdac_stream *azx_dev); +void snd_hdac_stop_streams(struct hdac_bus *bus); void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus); void snd_hdac_stream_reset(struct hdac_stream *azx_dev); void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index 2e98f5fd50e5..c056bcc5543d 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -174,17 +174,28 @@ void snd_hdac_stream_stop(struct hdac_stream *azx_dev) } EXPORT_SYMBOL_GPL(snd_hdac_stream_stop); +/** + * snd_hdac_stop_streams - stop all streams + * @bus: HD-audio core bus + */ +void snd_hdac_stop_streams(struct hdac_bus *bus) +{ + struct hdac_stream *stream; + + list_for_each_entry(stream, &bus->stream_list, list) + snd_hdac_stream_stop(stream); +} +EXPORT_SYMBOL_GPL(snd_hdac_stop_streams); + /** * snd_hdac_stop_streams_and_chip - stop all streams and chip if running * @bus: HD-audio core bus */ void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus) { - struct hdac_stream *stream; if (bus->chip_init) { - list_for_each_entry(stream, &bus->stream_list, list) - snd_hdac_stream_stop(stream); + snd_hdac_stop_streams(bus); snd_hdac_bus_stop_chip(bus); } } diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 75dcb14ff20a..0ff286b7b66b 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1033,10 +1033,8 @@ EXPORT_SYMBOL_GPL(azx_init_chip); void azx_stop_all_streams(struct azx *chip) { struct hdac_bus *bus = azx_bus(chip); - struct hdac_stream *s; - list_for_each_entry(s, &bus->stream_list, list) - snd_hdac_stream_stop(s); + snd_hdac_stop_streams(bus); } EXPORT_SYMBOL_GPL(azx_stop_all_streams); -- cgit v1.2.3 From 53f4f6b4e56d5fb6ef95a7e14c10ec244a79b996 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:39 +0200 Subject: ALSA: hda: ext: simplify logic for stream assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic is needlessly complicated, the basic rule is: The host streams can be found by checking the 'opened' boolean. The link streams can be found by checking the 'link_locked' boolean. Once a stream is found, it can be unconditionally decoupled. The snd_hdac_ext_stream_decouple_locked() routine will make sure the register status is modified as needed and the 'decoupled' boolean set. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/ext/hdac_ext_stream.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'sound') diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 9419abd7fc03..254df9a67bd2 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -267,19 +267,15 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus, if (hstream->direction != substream->stream) continue; - /* check if decoupled stream and not in use is available */ - if (hext_stream->decoupled && !hext_stream->link_locked) { - res = hext_stream; - break; - } - + /* check if link stream is available */ if (!hext_stream->link_locked) { - snd_hdac_ext_stream_decouple_locked(bus, hext_stream, true); res = hext_stream; break; } + } if (res) { + snd_hdac_ext_stream_decouple_locked(bus, res, true); res->link_locked = 1; res->link_substream = substream; } @@ -308,13 +304,12 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus, continue; if (!hstream->opened) { - if (!hext_stream->decoupled) - snd_hdac_ext_stream_decouple_locked(bus, hext_stream, true); res = hext_stream; break; } } if (res) { + snd_hdac_ext_stream_decouple_locked(bus, res, true); res->hstream.opened = 1; res->hstream.running = 0; res->hstream.substream = substream; -- cgit v1.2.3 From ac3467ad7f8734a21b65fa1852316a9b1b8c1fad Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:40 +0200 Subject: ALSA: hda: ext: fix locking in stream_release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The snd_hdac_ext_stream_release() routine uses the bus reg_lock, but releases it before calling snd_hdac_stream_release() where the bus reg_lock is taken again. This creates a timing window where the link stream release could test an invalid 'opened' boolean status and fail to recouple the host and link parts. Fix by exposing a locked version of snd_hdac_stream_release() and use it without releasing the spinlock. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- include/sound/hdaudio.h | 1 + sound/hda/ext/hdac_ext_stream.c | 2 +- sound/hda/hdac_stream.c | 19 ++++++++++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 35459d740f00..ddff03e546e9 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -551,6 +551,7 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, int idx, int direction, int tag); struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream); +void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev); void snd_hdac_stream_release(struct hdac_stream *azx_dev); struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus, int dir, int stream_tag); diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 254df9a67bd2..9a2bc7e803dd 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -384,8 +384,8 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type) spin_lock_irq(&bus->reg_lock); if (hext_stream->decoupled && !hext_stream->link_locked) snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); + snd_hdac_stream_release_locked(&hext_stream->hstream); spin_unlock_irq(&bus->reg_lock); - snd_hdac_stream_release(&hext_stream->hstream); break; case HDAC_EXT_STREAM_TYPE_LINK: diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index c056bcc5543d..1b8be39c38a9 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -365,6 +365,21 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, } EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); +/** + * snd_hdac_stream_release_locked - release the assigned stream + * @azx_dev: HD-audio core stream to release + * + * Release the stream that has been assigned by snd_hdac_stream_assign(). + * The bus->reg_lock needs to be taken at a higher level + */ +void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev) +{ + azx_dev->opened = 0; + azx_dev->running = 0; + azx_dev->substream = NULL; +} +EXPORT_SYMBOL_GPL(snd_hdac_stream_release_locked); + /** * snd_hdac_stream_release - release the assigned stream * @azx_dev: HD-audio core stream to release @@ -376,9 +391,7 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev) struct hdac_bus *bus = azx_dev->bus; spin_lock_irq(&bus->reg_lock); - azx_dev->opened = 0; - azx_dev->running = 0; - azx_dev->substream = NULL; + snd_hdac_stream_release_locked(azx_dev); spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_stream_release); -- cgit v1.2.3 From c6fe6be65aeaa03c7cdfc807b47c1e59b9c9ea71 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 19 Sep 2022 14:10:41 +0200 Subject: ALSA: hda: ext: remove always-true conditions on host and link release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By construction a host and link DMA are always decoupled. This decoupling happens in the assign() phase. There's no point in checking if the two parts are decoupled, this is by-design always-true. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220919121041.43463-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/ext/hdac_ext_stream.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index 9a2bc7e803dd..70f3ad71aaf0 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -382,7 +382,8 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type) case HDAC_EXT_STREAM_TYPE_HOST: spin_lock_irq(&bus->reg_lock); - if (hext_stream->decoupled && !hext_stream->link_locked) + /* couple link only if not in use */ + if (!hext_stream->link_locked) snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); snd_hdac_stream_release_locked(&hext_stream->hstream); spin_unlock_irq(&bus->reg_lock); @@ -390,7 +391,8 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type) case HDAC_EXT_STREAM_TYPE_LINK: spin_lock_irq(&bus->reg_lock); - if (hext_stream->decoupled && !hext_stream->hstream.opened) + /* couple host only if not in use */ + if (!hext_stream->hstream.opened) snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); hext_stream->link_locked = 0; hext_stream->link_substream = NULL; -- cgit v1.2.3 From 96ecdc718649fe01940e7f5dc4fc15dacd18cada Mon Sep 17 00:00:00 2001 From: ye xingchen Date: Tue, 20 Sep 2022 06:46:05 +0000 Subject: ALSA: es18xx: Remove the unneeded result variable Return the value inb() directly instead of storing it in another redundant variable. Reported-by: Zeal Robot Signed-off-by: ye xingchen Link: https://lore.kernel.org/r/20220920064605.215318-1-ye.xingchen@zte.com.cn Signed-off-by: Takashi Iwai --- sound/isa/es18xx.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 3fcd168480b6..0a32845b1017 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1344,11 +1344,8 @@ ES18XX_SINGLE("GPO1 Switch", 0, ES18XX_PM, 1, 1, ES18XX_FL_PMPORT), static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg) { - int data; - outb(reg, chip->ctrl_port); - data = inb(chip->ctrl_port + 1); - return data; + return inb(chip->ctrl_port + 1); } static void snd_es18xx_config_write(struct snd_es18xx *chip, -- cgit v1.2.3 From 79764ec772bc1346441ae1c4b1f3bd1991d634e8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Sep 2022 13:39:29 +0200 Subject: Revert "ALSA: usb-audio: Split endpoint setups for hw_params and prepare" This reverts commit ff878b408a03bef5d610b7e2302702e16a53636e. Unfortunately the recent fix seems bringing another regressions with PulseAudio / pipewire, at least for Steinberg and MOTU devices. As a temporary solution, do a straight revert. The issue for Android will be revisited again later by another different fix (if any). Fixes: ff878b408a03 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare") Cc: BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216500 Link: https://lore.kernel.org/r/20220920113929.25162-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 23 ++++++++++++++--------- sound/usb/endpoint.h | 6 ++---- sound/usb/pcm.c | 14 ++++---------- 3 files changed, 20 insertions(+), 23 deletions(-) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 8c8f9a851f89..eb71df9da831 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -758,8 +758,7 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, * The endpoint needs to be closed via snd_usb_endpoint_close() later. * * Note that this function doesn't configure the endpoint. The substream - * needs to set it up later via snd_usb_endpoint_set_params() and - * snd_usb_endpoint_prepare(). + * needs to set it up later via snd_usb_endpoint_configure(). */ struct snd_usb_endpoint * snd_usb_endpoint_open(struct snd_usb_audio *chip, @@ -1293,13 +1292,12 @@ out_of_memory: /* * snd_usb_endpoint_set_params: configure an snd_usb_endpoint * - * It's called either from hw_params callback. * Determine the number of URBs to be used on this endpoint. * An endpoint must be configured before it can be started. * An endpoint that is already running can not be reconfigured. */ -int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep) +static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) { const struct audioformat *fmt = ep->cur_audiofmt; int err; @@ -1382,18 +1380,18 @@ static int init_sample_rate(struct snd_usb_audio *chip, } /* - * snd_usb_endpoint_prepare: Prepare the endpoint + * snd_usb_endpoint_configure: Configure the endpoint * * This function sets up the EP to be fully usable state. - * It's called either from prepare callback. + * It's called either from hw_params or prepare callback. * The function checks need_setup flag, and performs nothing unless needed, * so it's safe to call this multiple times. * * This returns zero if unchanged, 1 if the configuration has changed, * or a negative error code. */ -int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep) +int snd_usb_endpoint_configure(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) { bool iface_first; int err = 0; @@ -1414,6 +1412,9 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, if (err < 0) goto unlock; } + err = snd_usb_endpoint_set_params(chip, ep); + if (err < 0) + goto unlock; goto done; } @@ -1441,6 +1442,10 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, if (err < 0) goto unlock; + err = snd_usb_endpoint_set_params(chip, ep); + if (err < 0) + goto unlock; + err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt); if (err < 0) goto unlock; diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index e67ea28faa54..6a9af04cf175 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -17,10 +17,8 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, bool is_sync_ep); void snd_usb_endpoint_close(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep); -int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep); -int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep); +int snd_usb_endpoint_configure(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock); bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b604f7e95e82..d45d1d7e6664 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -443,17 +443,17 @@ static int configure_endpoints(struct snd_usb_audio *chip, if (stop_endpoints(subs, false)) sync_pending_stops(subs); if (subs->sync_endpoint) { - err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + err = snd_usb_endpoint_configure(chip, subs->sync_endpoint); if (err < 0) return err; } - err = snd_usb_endpoint_prepare(chip, subs->data_endpoint); + err = snd_usb_endpoint_configure(chip, subs->data_endpoint); if (err < 0) return err; snd_usb_set_format_quirk(subs, subs->cur_audiofmt); } else { if (subs->sync_endpoint) { - err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + err = snd_usb_endpoint_configure(chip, subs->sync_endpoint); if (err < 0) return err; } @@ -551,13 +551,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->cur_audiofmt = fmt; mutex_unlock(&chip->mutex); - if (subs->sync_endpoint) { - ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint); - if (ret < 0) - goto unlock; - } - - ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint); + ret = configure_endpoints(chip, subs); unlock: if (ret < 0) -- cgit v1.2.3 From 01a72aefbacca4d6e169caa776c87d3c1f6faf4a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Sep 2022 13:42:43 +0200 Subject: Revert "ALSA: usb-audio: Clean up endpoint setups at PCM prepare" This reverts commit 32eeeed963ad4f41b422b3e314d96ded7283b201. As the fix for endpoint configuration split is reverted at next, do another revert here for a clean patch application. Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'sound') diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 4ed53a3dc922..b604f7e95e82 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -433,6 +433,35 @@ static void close_endpoints(struct snd_usb_audio *chip, } } +static int configure_endpoints(struct snd_usb_audio *chip, + struct snd_usb_substream *subs) +{ + int err; + + if (subs->data_endpoint->need_setup) { + /* stop any running stream beforehand */ + if (stop_endpoints(subs, false)) + sync_pending_stops(subs); + if (subs->sync_endpoint) { + err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + if (err < 0) + return err; + } + err = snd_usb_endpoint_prepare(chip, subs->data_endpoint); + if (err < 0) + return err; + snd_usb_set_format_quirk(subs, subs->cur_audiofmt); + } else { + if (subs->sync_endpoint) { + err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + if (err < 0) + return err; + } + } + + return 0; +} + /* * hw_params callback * @@ -611,18 +640,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; } - if (subs->sync_endpoint) { - ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); - if (ret < 0) - goto unlock; - } - - ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); + ret = configure_endpoints(chip, subs); if (ret < 0) goto unlock; - else if (ret > 0) - snd_usb_set_format_quirk(subs, subs->cur_audiofmt); - ret = 0; /* reset the pointer */ subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); -- cgit v1.2.3 From 2be79d58645465351af5320eb14c70a94724c5ef Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Sep 2022 20:11:06 +0200 Subject: ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2) This is a second attempt to fix the bug appearing on Android with the recent kernel; the first try was ff878b408a03 and reverted at commit 79764ec772bc. The details taken from the v1 patch: One of the former changes for the endpoint management was the more consistent setup of endpoints at hw_params. snd_usb_endpoint_configure() is a single function that does the full setup, and it's called from both PCM hw_params and prepare callbacks. Although the EP setup at the prepare phase is usually skipped (by checking need_setup flag), it may be still effective in some cases like suspend/resume that requires the interface setup again. As it's a full and single setup, the invocation of snd_usb_endpoint_configure() includes not only the USB interface setup but also the buffer release and allocation. OTOH, doing the buffer release and re-allocation at PCM prepare phase is rather superfluous, and better to be done only in the hw_params phase. For those optimizations, this patch splits the endpoint setup to two phases: snd_usb_endpoint_set_params() and snd_usb_endpoint_prepare(), to be called from hw_params and from prepare, respectively. Note that this patch changes the driver operation slightly, effectively moving the USB interface setup again to PCM prepare stage instead of hw_params stage, while the buffer allocation and such initializations are still done at hw_params stage. And, the change of the USB interface setup timing (moving to prepare) gave an interesting "fix", too: it was reported that the recent kernels caused silent output at the beginning on playbacks on some devices on Android, and this change casually fixed the regression. It seems that those devices are picky about the sample rate change (or the interface change?), and don't follow the too immediate rate changes. Meanwhile, Android operates the PCM in the following order: - open, then hw_params with the possibly highest sample rate - close without prepare - re-open, hw_params with the normal sample rate - prepare, and start streaming This procedure ended up the hw_params twice with different rates, and because the recent kernel did set up the sample rate twice one and after, it screwed up the device. OTOH, the earlier kernels didn't set up the USB interface at hw_params, hence this problem didn't appear. Now, with this patch, the USB interface setup is again back to the prepare phase, and it works around the problem automagically. Although we should address the sample rate problem in a more solid way in future, let's keep things working as before for now. *** What's new in the take#2 patch: - The regression caused by the v1 patch (bko#216500) was due to the missing check of need_setup flag at hw_params. Now the check is added, and the snd_usb_endpoint_set_params() call is skipped when the running EP is re-opened. - There was another bug in v1 where the clock reference rate wasn't updated at hw_params phase, which may lead to a lack of the proper hw constraints when an application doesn't issue the prepare but only the hw_params call. This patch fixes it as well by tracking the clock rate change in the prepare callback with a new flag "need_update" for the clock reference object, just like others. - The configure_endpoints() are simplified and folded back into snd_usb_pcm_prepare(). Fixes: bf6313a0ff76 ("ALSA: usb-audio: Refactor endpoint management") Fixes: ff878b408a03 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare") Reported-by: chihhao chen Link: https://lore.kernel.org/r/87e6d6ae69d68dc588ac9acc8c0f24d6188375c3.camel@mediatek.com Link: https://lore.kernel.org/r/20220901124136.4984-1-tiwai@suse.de Link: https://bugzilla.kernel.org/show_bug.cgi?id=216500 Link: https://lore.kernel.org/r/20220920181106.4894-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 76 +++++++++++++++++++++++++++++++--------------------- sound/usb/endpoint.h | 6 +++-- sound/usb/pcm.c | 51 ++++++++++++++--------------------- 3 files changed, 70 insertions(+), 63 deletions(-) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index eb71df9da831..0c94ebc98e90 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -40,6 +40,7 @@ struct snd_usb_clock_ref { unsigned char clock; atomic_t locked; int rate; + bool need_setup; struct list_head list; }; @@ -758,7 +759,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, * The endpoint needs to be closed via snd_usb_endpoint_close() later. * * Note that this function doesn't configure the endpoint. The substream - * needs to set it up later via snd_usb_endpoint_configure(). + * needs to set it up later via snd_usb_endpoint_set_params() and + * snd_usb_endpoint_prepare(). */ struct snd_usb_endpoint * snd_usb_endpoint_open(struct snd_usb_audio *chip, @@ -1289,15 +1291,39 @@ out_of_memory: return -ENOMEM; } +/* update the rate of the referred clock; return the actual rate */ +static int update_clock_ref_rate(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) +{ + struct snd_usb_clock_ref *clock = ep->clock_ref; + int rate = ep->cur_rate; + + if (!clock || clock->rate == rate) + return rate; + if (clock->rate) { + if (atomic_read(&clock->locked)) + return clock->rate; + if (clock->rate != rate) { + usb_audio_err(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n", + clock->rate, rate, ep->ep_num); + return clock->rate; + } + } + clock->rate = rate; + clock->need_setup = true; + return rate; +} + /* * snd_usb_endpoint_set_params: configure an snd_usb_endpoint * + * It's called either from hw_params callback. * Determine the number of URBs to be used on this endpoint. * An endpoint must be configured before it can be started. * An endpoint that is already running can not be reconfigured. */ -static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep) +int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) { const struct audioformat *fmt = ep->cur_audiofmt; int err; @@ -1349,49 +1375,46 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes; ep->curframesize = ep->curpacksize / ep->cur_frame_bytes; - return 0; + return update_clock_ref_rate(chip, ep); } static int init_sample_rate(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep) { struct snd_usb_clock_ref *clock = ep->clock_ref; - int err; + int rate, err; - if (clock) { - if (atomic_read(&clock->locked)) - return 0; - if (clock->rate == ep->cur_rate) - return 0; - if (clock->rate && clock->rate != ep->cur_rate) { - usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n", - clock->rate, ep->cur_rate, ep->ep_num); - return -EINVAL; - } - } + rate = update_clock_ref_rate(chip, ep); + if (rate < 0) + return rate; + if (clock && !clock->need_setup) + return 0; - err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate); - if (err < 0) + err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate); + if (err < 0) { + if (clock) + clock->rate = 0; /* reset rate */ return err; + } if (clock) - clock->rate = ep->cur_rate; + clock->need_setup = false; return 0; } /* - * snd_usb_endpoint_configure: Configure the endpoint + * snd_usb_endpoint_prepare: Prepare the endpoint * * This function sets up the EP to be fully usable state. - * It's called either from hw_params or prepare callback. + * It's called either from prepare callback. * The function checks need_setup flag, and performs nothing unless needed, * so it's safe to call this multiple times. * * This returns zero if unchanged, 1 if the configuration has changed, * or a negative error code. */ -int snd_usb_endpoint_configure(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep) +int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) { bool iface_first; int err = 0; @@ -1412,9 +1435,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip, if (err < 0) goto unlock; } - err = snd_usb_endpoint_set_params(chip, ep); - if (err < 0) - goto unlock; goto done; } @@ -1442,10 +1462,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip, if (err < 0) goto unlock; - err = snd_usb_endpoint_set_params(chip, ep); - if (err < 0) - goto unlock; - err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt); if (err < 0) goto unlock; diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index 6a9af04cf175..e67ea28faa54 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h @@ -17,8 +17,10 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, bool is_sync_ep); void snd_usb_endpoint_close(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep); -int snd_usb_endpoint_configure(struct snd_usb_audio *chip, - struct snd_usb_endpoint *ep); +int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); +int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep); int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock); bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip, diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index d45d1d7e6664..e721fc12acde 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -433,35 +433,6 @@ static void close_endpoints(struct snd_usb_audio *chip, } } -static int configure_endpoints(struct snd_usb_audio *chip, - struct snd_usb_substream *subs) -{ - int err; - - if (subs->data_endpoint->need_setup) { - /* stop any running stream beforehand */ - if (stop_endpoints(subs, false)) - sync_pending_stops(subs); - if (subs->sync_endpoint) { - err = snd_usb_endpoint_configure(chip, subs->sync_endpoint); - if (err < 0) - return err; - } - err = snd_usb_endpoint_configure(chip, subs->data_endpoint); - if (err < 0) - return err; - snd_usb_set_format_quirk(subs, subs->cur_audiofmt); - } else { - if (subs->sync_endpoint) { - err = snd_usb_endpoint_configure(chip, subs->sync_endpoint); - if (err < 0) - return err; - } - } - - return 0; -} - /* * hw_params callback * @@ -551,7 +522,16 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->cur_audiofmt = fmt; mutex_unlock(&chip->mutex); - ret = configure_endpoints(chip, subs); + if (!subs->data_endpoint->need_setup) + goto unlock; + + if (subs->sync_endpoint) { + ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint); + if (ret < 0) + goto unlock; + } + + ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint); unlock: if (ret < 0) @@ -634,9 +614,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; } - ret = configure_endpoints(chip, subs); + if (subs->sync_endpoint) { + ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + if (ret < 0) + goto unlock; + } + + ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); if (ret < 0) goto unlock; + else if (ret > 0) + snd_usb_set_format_quirk(subs, subs->cur_audiofmt); + ret = 0; /* reset the pointer */ subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); -- cgit v1.2.3 From 9a737e7f8b371e97eb649904276407cee2c9cf30 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Sep 2022 20:11:26 +0200 Subject: ALSA: usb-audio: Properly refcounting clock rate We fixed the bug introduced by the patch for managing the shared clocks at the commit 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock rate at closing EP"), but it was merely a workaround. By this change, the clock reference rate is cleared at each EP close, hence the still remaining EP may need a re-setup of rate unnecessarily. This patch introduces the proper refcounting for the clock reference object so that the clock setup is done only when needed. Fixes: 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock rate at closing EP") Fixes: c11117b634f4 ("ALSA: usb-audio: Refcount multiple accesses on the single clock") Link: https://lore.kernel.org/r/20220920181126.4912-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 0c94ebc98e90..b2d0b42b581f 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -39,6 +39,7 @@ struct snd_usb_iface_ref { struct snd_usb_clock_ref { unsigned char clock; atomic_t locked; + int opened; int rate; bool need_setup; struct list_head list; @@ -803,6 +804,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep = NULL; goto unlock; } + ep->clock_ref->opened++; } ep->cur_audiofmt = fp; @@ -926,8 +928,10 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, endpoint_set_interface(chip, ep, false); if (!--ep->opened) { - if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked)) - ep->clock_ref->rate = 0; + if (ep->clock_ref) { + if (!--ep->clock_ref->opened) + ep->clock_ref->rate = 0; + } ep->iface = 0; ep->altsetting = 0; ep->cur_audiofmt = NULL; @@ -1649,8 +1653,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending) WRITE_ONCE(ep->sync_source->sync_sink, NULL); stop_urbs(ep, false, keep_pending); if (ep->clock_ref) - if (!atomic_dec_return(&ep->clock_ref->locked)) - ep->clock_ref->rate = 0; + atomic_dec(&ep->clock_ref->locked); } } -- cgit v1.2.3 From 9bf320f0cf872bf23d9f03abefeff2130acbd6c5 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 21 Sep 2022 11:33:22 +0200 Subject: ALSA: hda/hdmi: Simplify the pcm_idx condition in hdmi_pcm_setup_pin() Make the code more readable. Signed-off-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220921093322.82609-1-perex@perex.cz Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1eb894e6cdf1..11c22dfced06 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1472,10 +1472,9 @@ static void hdmi_pcm_setup_pin(struct hdmi_spec *spec, int mux_idx; bool non_pcm; - if (per_pin->pcm_idx >= 0 && per_pin->pcm_idx < spec->pcm_used) - pcm = get_pcm_rec(spec, per_pin->pcm_idx); - else + if (per_pin->pcm_idx < 0 || per_pin->pcm_idx >= spec->pcm_used) return; + pcm = get_pcm_rec(spec, per_pin->pcm_idx); if (!pcm->pcm) return; if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use)) -- cgit v1.2.3 From 2fa22c3c755fb06a0c4507320c929616bbae1ec3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Wed, 21 Sep 2022 11:33:49 +0200 Subject: ALSA: hda/hdmi: ELD procfs - print the codec NIDs It is useful for the debugging to print also the used HDA codec NIDs used for the given HDMI device. With the dynamic converter assignment the converter NID is changed dynamically. Signed-off-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220921093349.82680-1-perex@perex.cz Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_eld.c | 6 +++++- sound/pci/hda/hda_local.h | 3 ++- sound/pci/hda/patch_hdmi.c | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 9e97443795f8..1d108ed5c6f2 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -440,7 +440,8 @@ static void hdmi_print_sad_info(int i, struct cea_sad *a, } void snd_hdmi_print_eld_info(struct hdmi_eld *eld, - struct snd_info_buffer *buffer) + struct snd_info_buffer *buffer, + hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid) { struct parsed_hdmi_eld *e = &eld->info; char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; @@ -462,6 +463,9 @@ void snd_hdmi_print_eld_info(struct hdmi_eld *eld, snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present); snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid); + snd_iprintf(buffer, "codec_pin_nid\t\t0x%x\n", pin_nid); + snd_iprintf(buffer, "codec_dev_id\t\t0x%x\n", dev_id); + snd_iprintf(buffer, "codec_cvt_nid\t\t0x%x\n", cvt_nid); if (!eld->eld_valid) return; snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name); diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 682dca2057db..53a5a62b78fa 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -712,7 +712,8 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid, #ifdef CONFIG_SND_PROC_FS void snd_hdmi_print_eld_info(struct hdmi_eld *eld, - struct snd_info_buffer *buffer); + struct snd_info_buffer *buffer, + hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid); void snd_hdmi_write_eld_info(struct hdmi_eld *eld, struct snd_info_buffer *buffer); #endif diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 11c22dfced06..d2c6ba2634f1 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -496,7 +496,8 @@ static void print_eld_info(struct snd_info_entry *entry, struct hdmi_spec_per_pin *per_pin = entry->private_data; mutex_lock(&per_pin->lock); - snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer); + snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer, per_pin->pin_nid, + per_pin->dev_id, per_pin->cvt_nid); mutex_unlock(&per_pin->lock); } -- cgit v1.2.3 From 6de0b0292b548010b09917e8cdfc337a6dcf67ce Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 22 Sep 2022 11:59:12 +0200 Subject: ASoC: es8316: fix register sync error in suspend/resume tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SOF CI tests report failures with the following error thrown kernel: es8316 i2c-ESSX8336:00: Unable to sync registers 0x0-0x1. -121 ES8336 only supports I2C read/write one byte a time, so we do need to set the .use_single_read and .use_single_write flags to avoid this sync issue. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: FRED OH Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220922095912.27010-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index de7185f73e1e..10a204255b6a 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -793,6 +793,8 @@ static const struct regmap_access_table es8316_volatile_table = { static const struct regmap_config es8316_regmap = { .reg_bits = 8, .val_bits = 8, + .use_single_read = true, + .use_single_write = true, .max_register = 0x53, .volatile_table = &es8316_volatile_table, .cache_type = REGCACHE_RBTREE, -- cgit v1.2.3 From c35fbea48659ec99a4f532c9ee9e8692405afdd0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 22 Sep 2022 12:00:14 +0200 Subject: ALSA: hda: intel-dsp-config: add missing RaptorLake PCI IDs These two missed IDs need to be added for dynamic selection of drivers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Link: https://lore.kernel.org/r/20220922100014.27080-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Takashi Iwai --- sound/hda/intel-dsp-config.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'sound') diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index d84ffdf47210..5a478649f338 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -450,6 +450,16 @@ static const struct config_entry config_table[] = { .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x51cb, }, + /* RaptorLake-M */ + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x51ce, + }, + /* RaptorLake-PX */ + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x51cf, + }, #endif }; -- cgit v1.2.3 From b5eee17cf7ddaf7b29a031b2c48277038e7a171a Mon Sep 17 00:00:00 2001 From: ye xingchen Date: Thu, 22 Sep 2022 11:28:46 +0000 Subject: ALSA: hda/ca0132 - remove the unneeded result variable Return the value dsp_allocate_ports() directly instead of storing it in another redundant variable. Reported-by: Zeal Robot Signed-off-by: ye xingchen Link: https://lore.kernel.org/r/20220922112846.236987-1-ye.xingchen@zte.com.cn Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_ca0132.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 208933792787..9580fe00cbd9 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -2962,7 +2962,6 @@ static int dsp_allocate_ports_format(struct hda_codec *codec, const unsigned short fmt, unsigned int *port_map) { - int status; unsigned int num_chans; unsigned int sample_rate_div = ((get_hdafmt_rate(fmt) >> 0) & 3) + 1; @@ -2976,9 +2975,7 @@ static int dsp_allocate_ports_format(struct hda_codec *codec, num_chans = get_hdafmt_chs(fmt) + 1; - status = dsp_allocate_ports(codec, num_chans, rate_multi, port_map); - - return status; + return dsp_allocate_ports(codec, num_chans, rate_multi, port_map); } /* -- cgit v1.2.3 From ef6f5494faf6a37c74990689a3bb3cee76d2544c Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 22 Sep 2022 10:40:17 +0200 Subject: ALSA: hda/hdmi: Use only dynamic PCM device allocation Per discussion on the alsa-devel mailing list [1], the legacy PIN to PCM device mapping is obsolete nowadays. The maximum number of the simultaneously usable PCM devices is equal to the HDMI codec converters. Remove the extra PCM devices (beyond the detected converters) and force the use of the dynamic PCM device allocation. The legacy code is removed. I believe that all HDMI codecs have the jack sensing feature. Move the check to the codec probe function and print a warning, if a codec without this feature is detected. [1] https://lore.kernel.org/alsa-devel/2f37e0b2-1e82-8c0b-2bbd-1e5038d6ecc6@perex.cz/ Cc: Kai Vehmanen Signed-off-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220922084017.25925-1-perex@perex.cz Signed-off-by: Takashi Iwai --- include/sound/hda_codec.h | 1 - sound/pci/hda/patch_hdmi.c | 153 ++++++++------------------------------------ sound/soc/codecs/hda.c | 3 - sound/soc/codecs/hdac_hda.c | 3 - 4 files changed, 28 insertions(+), 132 deletions(-) (limited to 'sound') diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 2a8fe7240f10..25ec8c181688 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -258,7 +258,6 @@ struct hda_codec { unsigned int link_down_at_suspend:1; /* link down at runtime suspend */ unsigned int relaxed_resume:1; /* don't resume forcibly for jack */ unsigned int forced_resume:1; /* forced resume for jack */ - unsigned int mst_no_extra_pcms:1; /* no backup PCMs for DP-MST */ #ifdef CONFIG_PM unsigned long power_on_acct; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index d2c6ba2634f1..1863836b2685 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -167,8 +167,6 @@ struct hdmi_spec { struct hdmi_ops ops; bool dyn_pin_out; - bool dyn_pcm_assign; - bool dyn_pcm_no_legacy; /* hdmi interrupt trigger control flag for Nvidia codec */ bool hdmi_intr_trig_ctrl; bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */ @@ -1188,9 +1186,7 @@ static void pin_cvt_fixup(struct hda_codec *codec, spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid); } -/* called in hdmi_pcm_open when no pin is assigned to the PCM - * in dyn_pcm_assign mode. - */ +/* called in hdmi_pcm_open when no pin is assigned to the PCM */ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) @@ -1258,19 +1254,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (!spec->dyn_pcm_assign) { - if (snd_BUG_ON(pin_idx < 0)) { - err = -EINVAL; - goto unlock; - } - } else { - /* no pin is assigned to the PCM - * PA need pcm open successfully when probe - */ - if (pin_idx < 0) { - err = hdmi_pcm_open_no_pin(hinfo, codec, substream); - goto unlock; - } + /* no pin is assigned to the PCM + * PA need pcm open successfully when probe + */ + if (pin_idx < 0) { + err = hdmi_pcm_open_no_pin(hinfo, codec, substream); + goto unlock; } err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, false); @@ -1375,43 +1364,6 @@ static int hdmi_find_pcm_slot(struct hdmi_spec *spec, { int i; - /* on the new machines, try to assign the pcm slot dynamically, - * not use the preferred fixed map (legacy way) anymore. - */ - if (spec->dyn_pcm_no_legacy) - goto last_try; - - /* - * generic_hdmi_build_pcms() may allocate extra PCMs on some - * platforms (with maximum of 'num_nids + dev_num - 1') - * - * The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n - * if m==0. This guarantees that dynamic pcm assignments are compatible - * with the legacy static per_pin-pcm assignment that existed in the - * days before DP-MST. - * - * Intel DP-MST prefers this legacy behavior for compatibility, too. - * - * per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)). - */ - - if (per_pin->dev_id == 0 || spec->intel_hsw_fixup) { - if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) - return per_pin->pin_nid_idx; - } else { - i = spec->num_nids + (per_pin->dev_id - 1); - if (i < spec->pcm_used && !(test_bit(i, &spec->pcm_bitmap))) - return i; - } - - /* have a second try; check the area over num_nids */ - for (i = spec->num_nids; i < spec->pcm_used; i++) { - if (!test_bit(i, &spec->pcm_bitmap)) - return i; - } - - last_try: - /* the last try; check the empty slots in pins */ for (i = 0; i < spec->pcm_used; i++) { if (!test_bit(i, &spec->pcm_bitmap)) return i; @@ -1573,14 +1525,12 @@ static void update_eld(struct hda_codec *codec, */ pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); - if (spec->dyn_pcm_assign) { - if (eld->eld_valid) { - hdmi_attach_hda_pcm(spec, per_pin); - hdmi_pcm_setup_pin(spec, per_pin); - } else { - hdmi_pcm_reset_pin(spec, per_pin); - hdmi_detach_hda_pcm(spec, per_pin); - } + if (eld->eld_valid) { + hdmi_attach_hda_pcm(spec, per_pin); + hdmi_pcm_setup_pin(spec, per_pin); + } else { + hdmi_pcm_reset_pin(spec, per_pin); + hdmi_detach_hda_pcm(spec, per_pin); } /* if pcm_idx == -1, it means this is in monitor connection event * we can get the correct pcm_idx now. @@ -1942,7 +1892,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) * structures based on worst case. */ dev_num = spec->dev_num; - } else if (spec->dyn_pcm_assign && codec->dp_mst) { + } else if (codec->dp_mst) { dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1; /* * spec->dev_num is the maxinum number of device entries @@ -1967,13 +1917,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) if (!per_pin) return -ENOMEM; - if (spec->dyn_pcm_assign) { - per_pin->pcm = NULL; - per_pin->pcm_idx = -1; - } else { - per_pin->pcm = get_hdmi_pcm(spec, pin_idx); - per_pin->pcm_idx = pin_idx; - } + per_pin->pcm = NULL; + per_pin->pcm_idx = -1; per_pin->pin_nid = pin_nid; per_pin->pin_nid_idx = spec->num_nids; per_pin->dev_id = i; @@ -1982,6 +1927,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) err = hdmi_read_pin_conn(codec, pin_idx); if (err < 0) return err; + if (!is_jack_detectable(codec, pin_nid)) + codec_warn(codec, "HDMI: pin NID 0x%x - jack not detectable\n", pin_nid); spec->num_pins++; } spec->num_nids++; @@ -2129,10 +2076,9 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (spec->dyn_pcm_assign && pin_idx < 0) { - /* when dyn_pcm_assign and pcm is not bound to a pin - * skip pin setup and return 0 to make audio playback - * be ongoing + if (pin_idx < 0) { + /* when pcm is not bound to a pin skip pin setup and return 0 + * to make audio playback be ongoing */ pin_cvt_fixup(codec, NULL, cvt_nid); snd_hda_codec_setup_stream(codec, cvt_nid, @@ -2235,7 +2181,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (spec->dyn_pcm_assign && pin_idx < 0) + if (pin_idx < 0) goto unlock; if (snd_BUG_ON(pin_idx < 0)) { @@ -2333,21 +2279,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int idx, pcm_num; - /* - * for non-mst mode, pcm number is the same as before - * for DP MST mode without extra PCM, pcm number is same - * for DP MST mode with extra PCMs, pcm number is - * (nid number + dev_num - 1) - * dev_num is the device entry number in a pin - */ - - if (spec->dyn_pcm_no_legacy && codec->mst_no_extra_pcms) - pcm_num = spec->num_cvts; - else if (codec->mst_no_extra_pcms) - pcm_num = spec->num_nids; - else - pcm_num = spec->num_nids + spec->dev_num - 1; - + /* limit the PCM devices to the codec converters */ + pcm_num = spec->num_cvts; codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num); for (idx = 0; idx < pcm_num; idx++) { @@ -2386,17 +2319,12 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) { char hdmi_str[32] = "HDMI/DP"; struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pcm_idx); struct snd_jack *jack; int pcmdev = get_pcm_rec(spec, pcm_idx)->device; int err; if (pcmdev > 0) sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); - if (!spec->dyn_pcm_assign && - !is_jack_detectable(codec, per_pin->pin_nid)) - strncat(hdmi_str, " Phantom", - sizeof(hdmi_str) - strlen(hdmi_str) - 1); err = snd_jack_new(codec->card, hdmi_str, SND_JACK_AVOUT, &jack, true, false); @@ -2429,18 +2357,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) /* create the spdif for each pcm * pin will be bound when monitor is connected */ - if (spec->dyn_pcm_assign) - err = snd_hda_create_dig_out_ctls(codec, + err = snd_hda_create_dig_out_ctls(codec, 0, spec->cvt_nids[0], HDA_PCM_TYPE_HDMI); - else { - struct hdmi_spec_per_pin *per_pin = - get_pin(spec, pcm_idx); - err = snd_hda_create_dig_out_ctls(codec, - per_pin->pin_nid, - per_pin->mux_nids[0], - HDA_PCM_TYPE_HDMI); - } if (err < 0) return err; snd_hda_spdif_ctls_unassign(codec, pcm_idx); @@ -2560,11 +2479,7 @@ static void generic_hdmi_free(struct hda_codec *codec) for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { if (spec->pcm_rec[pcm_idx].jack == NULL) continue; - if (spec->dyn_pcm_assign) - snd_device_free(codec->card, - spec->pcm_rec[pcm_idx].jack); - else - spec->pcm_rec[pcm_idx].jack = NULL; + snd_device_free(codec->card, spec->pcm_rec[pcm_idx].jack); } generic_spec_free(codec); @@ -3044,7 +2959,6 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, return err; spec = codec->spec; codec->dp_mst = true; - spec->dyn_pcm_assign = true; spec->vendor_nid = vendor_nid; spec->port_map = port_map; spec->port_num = port_num; @@ -3108,17 +3022,9 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec) * the index indicate the port number. */ static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; - int ret; - - ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4, - enable_silent_stream); - if (!ret) { - struct hdmi_spec *spec = codec->spec; - spec->dyn_pcm_no_legacy = true; - } - - return ret; + return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4, + enable_silent_stream); } static int patch_i915_adlp_hdmi(struct hda_codec *codec) @@ -3758,7 +3664,6 @@ static int patch_nvhdmi(struct hda_codec *codec) codec->dp_mst = true; spec = codec->spec; - spec->dyn_pcm_assign = true; err = hdmi_parse_codec(codec); if (err < 0) { @@ -4038,10 +3943,8 @@ static int patch_tegra234_hdmi(struct hda_codec *codec) return err; codec->dp_mst = true; - codec->mst_no_extra_pcms = true; spec = codec->spec; spec->dyn_pin_out = true; - spec->dyn_pcm_assign = true; spec->hdmi_intr_trig_ctrl = true; return tegra_hdmi_init(codec); diff --git a/sound/soc/codecs/hda.c b/sound/soc/codecs/hda.c index ad20a3dff9b7..61e8e9be6b8d 100644 --- a/sound/soc/codecs/hda.c +++ b/sound/soc/codecs/hda.c @@ -224,9 +224,6 @@ static int hda_codec_probe(struct snd_soc_component *component) goto err; } - /* configure codec for 1:1 PCM:DAI mapping */ - codec->mst_no_extra_pcms = 1; - ret = snd_hda_codec_parse_pcms(codec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 77df4c5b274a..8af434e14bfb 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -461,9 +461,6 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) dev_dbg(&hdev->dev, "no patch file found\n"); } - /* configure codec for 1:1 PCM:DAI mapping */ - hcodec->mst_no_extra_pcms = 1; - ret = snd_hda_codec_parse_pcms(hcodec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); -- cgit v1.2.3 From ea8ef003aa53ad23e7705c5cab1c4e664faa6c79 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 21 Sep 2022 16:53:53 +0200 Subject: ASoC: wcd9335: fix order of Slimbus unprepare/disable Slimbus streams are first prepared and then enabled, so the cleanup path should reverse it. The unprepare sets stream->num_ports to 0 and frees the stream->ports. Calling disable after unprepare was not really effective (channels was not deactivated) and could lead to further issues due to making transfers on unprepared stream. Fixes: 20aedafdf492 ("ASoC: wcd9335: add support to wcd9335 codec") Cc: Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20220921145354.1683791-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index beeeb35e8032..8a1f741de948 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1974,8 +1974,8 @@ static int wcd9335_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - slim_stream_unprepare(dai_data->sruntime); slim_stream_disable(dai_data->sruntime); + slim_stream_unprepare(dai_data->sruntime); break; default: break; -- cgit v1.2.3 From e96bca7eaa5747633ec638b065630ff83728982a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 21 Sep 2022 16:53:54 +0200 Subject: ASoC: wcd934x: fix order of Slimbus unprepare/disable Slimbus streams are first prepared and then enabled, so the cleanup path should reverse it. The unprepare sets stream->num_ports to 0 and frees the stream->ports. Calling disable after unprepare was not really effective (channels was not deactivated) and could lead to further issues due to making transfers on unprepared stream. Fixes: a61f3b4f476e ("ASoC: wcd934x: add support to wcd9340/wcd9341 codec") Cc: Signed-off-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20220921145354.1683791-2-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index f56907d0942d..28175c746b9a 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1913,8 +1913,8 @@ static int wcd934x_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - slim_stream_unprepare(dai_data->sruntime); slim_stream_disable(dai_data->sruntime); + slim_stream_unprepare(dai_data->sruntime); break; default: break; -- cgit v1.2.3 From 086ceada2107b482df437d76f581062b547eb7f2 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Tue, 6 Sep 2022 14:49:21 +0800 Subject: ASoC: fsl_audmux: Fix amixer write errors This reverts commit 944c517b8c8388 ("ASoC: fsl_audmix: make clock and output src write only"). There is error after making clock and output src write only $amixer -c imxaudmix cset numid=1 1 amixer: Cannot read the given element from control sysdefault:3 Which is worse than before, so let's revert the change. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1662446961-20799-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 43857b7a81c9..672148dd4b23 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -199,18 +199,10 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new fsl_audmix_snd_controls[] = { /* FSL_AUDMIX_CTR controls */ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mixing Clock Source", - .info = snd_soc_info_enum_double, - .access = SNDRV_CTL_ELEM_ACCESS_WRITE, - .put = fsl_audmix_put_mix_clk_src, - .private_value = (unsigned long)&fsl_audmix_enum[0] }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Output Source", - .info = snd_soc_info_enum_double, - .access = SNDRV_CTL_ELEM_ACCESS_WRITE, - .put = fsl_audmix_put_out_src, - .private_value = (unsigned long)&fsl_audmix_enum[1] }, + SOC_ENUM_EXT("Mixing Clock Source", fsl_audmix_enum[0], + snd_soc_get_enum_double, fsl_audmix_put_mix_clk_src), + SOC_ENUM_EXT("Output Source", fsl_audmix_enum[1], + snd_soc_get_enum_double, fsl_audmix_put_out_src), SOC_ENUM("Output Width", fsl_audmix_enum[2]), SOC_ENUM("Frame Rate Diff Error", fsl_audmix_enum[3]), SOC_ENUM("Clock Freq Diff Error", fsl_audmix_enum[4]), -- cgit v1.2.3 From b23975e60a944e1a3ef419a01838fca51a29baf3 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Fri, 23 Sep 2022 10:22:36 +0200 Subject: ALSA: hda/hdmi: Limit the maximal count of PCM devices to 8 The current hardware has up to 4 converters. Save little space. The limit 8 is enough even for a more improved hardware. Signed-off-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220923082236.61024-1-perex@perex.cz Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1863836b2685..c172640c8a41 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -151,7 +151,7 @@ struct hdmi_spec { */ int dev_num; struct snd_array pins; /* struct hdmi_spec_per_pin */ - struct hdmi_pcm pcm_rec[16]; + struct hdmi_pcm pcm_rec[8]; struct mutex pcm_lock; struct mutex bind_lock; /* for audio component binding */ /* pcm_bitmap means which pcms have been assigned to pins*/ @@ -2299,8 +2299,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; pstr->substreams = 1; pstr->ops = generic_ops; - /* pcm number is less than 16 */ - if (spec->pcm_used >= 16) + /* pcm number is less than pcm_rec array size */ + if (spec->pcm_used >= ARRAY_SIZE(spec->pcm_rec)) break; /* other pstr fields are set in open */ } -- cgit v1.2.3 From a61c7d88d38cf3b9c88cf667c4f8a389a57744d4 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 23 Sep 2022 18:35:01 +0300 Subject: ALSA: memalloc: use __GFP_RETRY_MAYFAIL for DMA mem allocs Use __GFP_RETRY_MAYFAIL instead of __GFP__NORETRY in snd_dma_dev_alloc(), snd_dma_wc_alloc() and friends, to allocate pages for device memory. The MAYFAIL flag retains the semantics of not triggering the OOM killer, but lowers the risk of alloc failure. MAYFAIL flag was added in commit dcda9b04713c3 ("mm, tree wide: replace __GFP_REPEAT by __GFP_RETRY_MAYFAIL with more useful semantic"). This change addresses recurring failures with SOF audio driver in test cases where a system suspend-resume stress test is run, combined with an active high memory-load use-case. The failure typically shows up as: [ 379.480229] sof-audio-pci-intel-tgl 0000:00:1f.3: booting DSP firmware [ 379.484803] sof-audio-pci-intel-tgl 0000:00:1f.3: error: memory alloc failed: -12 [ 379.484810] sof-audio-pci-intel-tgl 0000:00:1f.3: error: dma prepare for ICCMAX stream failed Multiple fixes to reduce the memory usage of DSP boot have been identified in SOF driver, but even with those fixes, debug on affected systems has shown that even a single page alloc may fail with __GFP_NORETRY. When this occurs, system is under significant load on physical memory, but a lot of reclaimable pages are available, so the system has not run out of memory. With __GFP_RETRY_MAYFAIL, the errors are not hit in these stress tests. The alloc failure is severe as audio capability is completely lost if alloc failure is hit at system resume. An alternative solution was considered where the resources for DSP boot would be kept allocated until driver is unbound. This would avoid the allocation failure, but consume memory that is only needed temporarily at probe and resume time. It seems better to not hang on to the memory, but rather work a bit harder for allocating the pages at resume. BugLink: https://github.com/thesofproject/linux/issues/3844 Signed-off-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20220923153501.3326041-1-kai.vehmanen@linux.intel.com Signed-off-by: Takashi Iwai --- sound/core/memalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 2c11413bea61..03cffe771366 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -21,7 +21,7 @@ #define DEFAULT_GFP \ (GFP_KERNEL | \ __GFP_COMP | /* compound page lets parts be mapped */ \ - __GFP_NORETRY | /* don't trigger OOM-killer */ \ + __GFP_RETRY_MAYFAIL | /* don't trigger OOM-killer */ \ __GFP_NOWARN) /* no stack trace print - this call is non-critical */ static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab); -- cgit v1.2.3 From 1dd0dd0b1fefd1e51cfaddf62316f759fde7de7d Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 25 Sep 2022 14:57:51 +0200 Subject: ALSA: firewire: Remove some left-over license text in sound/firewire There is already a SPDX-License-Identifier tag, so the corresponding license text can be removed. While at it, be more consistent and: - add a missing .c (ff-protocol-latter) - remove an empty line (motu-protocol-v1) Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/2bfe76c7eeb0f5205a1427e280bf8d9da0354a62.1664110649.git.christophe.jaillet@wanadoo.fr Signed-off-by: Takashi Iwai --- sound/firewire/dice/dice-harman.c | 2 -- sound/firewire/dice/dice-presonus.c | 2 -- sound/firewire/fireface/ff-protocol-former.c | 2 -- sound/firewire/fireface/ff-protocol-latter.c | 4 +--- sound/firewire/motu/motu-protocol-v1.c | 3 --- 5 files changed, 1 insertion(+), 12 deletions(-) (limited to 'sound') diff --git a/sound/firewire/dice/dice-harman.c b/sound/firewire/dice/dice-harman.c index a8ca00c397e8..212ae77dfca2 100644 --- a/sound/firewire/dice/dice-harman.c +++ b/sound/firewire/dice/dice-harman.c @@ -2,8 +2,6 @@ // dice-harman.c - a part of driver for DICE based devices // // Copyright (c) 2021 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include "dice.h" diff --git a/sound/firewire/dice/dice-presonus.c b/sound/firewire/dice/dice-presonus.c index 503f462a83f4..967cc3119a64 100644 --- a/sound/firewire/dice/dice-presonus.c +++ b/sound/firewire/dice/dice-presonus.c @@ -2,8 +2,6 @@ // dice-presonus.c - a part of driver for DICE based devices // // Copyright (c) 2019 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include "dice.h" diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c index bf44cad7985e..8900ffe517ed 100644 --- a/sound/firewire/fireface/ff-protocol-former.c +++ b/sound/firewire/fireface/ff-protocol-former.c @@ -2,8 +2,6 @@ // ff-protocol-former.c - a part of driver for RME Fireface series // // Copyright (c) 2019 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index 7ddb7b97f02d..76c3eab36d4e 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 -// ff-protocol-latter - a part of driver for RME Fireface series +// ff-protocol-latter.c - a part of driver for RME Fireface series // // Copyright (c) 2019 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include diff --git a/sound/firewire/motu/motu-protocol-v1.c b/sound/firewire/motu/motu-protocol-v1.c index f1d6a326dc07..e811629f167b 100644 --- a/sound/firewire/motu/motu-protocol-v1.c +++ b/sound/firewire/motu/motu-protocol-v1.c @@ -1,10 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only - // motu-protocol-v1.c - a part of driver for MOTU FireWire series // // Copyright (c) 2021 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include "motu.h" -- cgit v1.2.3 From f0061c18c169f0c32d96b59485c3edee85e343ed Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:48 +0200 Subject: ALSA: pcm: Avoid reference to status->state In the PCM core and driver code, there are lots place referring to the current PCM state via runtime->status->state. This patch introduced a local PCM state in runtime itself and replaces those references with runtime->state. It has improvements in two aspects: - The reduction of a indirect access leads to more code optimization - It avoids a possible (unexpected) modification of the state via mmap of the status record The status->state is updated together with runtime->state, so that user-space can still read the current state via mmap like before, too. This patch touches only the ALSA core code. The changes in each driver will follow in later patches. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- include/sound/pcm.h | 20 +++++++- sound/core/oss/pcm_oss.c | 42 ++++++++-------- sound/core/pcm.c | 9 ++-- sound/core/pcm_compat.c | 4 +- sound/core/pcm_lib.c | 16 +++--- sound/core/pcm_native.c | 127 ++++++++++++++++++++++++----------------------- 6 files changed, 118 insertions(+), 100 deletions(-) (limited to 'sound') diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 8c48a5bce88c..7b1a022910e8 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -346,6 +346,8 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy struct snd_pcm_runtime { /* -- Status -- */ + snd_pcm_state_t state; /* stream state */ + snd_pcm_state_t suspended_state; /* suspended stream state */ struct snd_pcm_substream *trigger_master; struct timespec64 trigger_tstamp; /* trigger timestamp */ bool trigger_tstamp_latched; /* trigger timestamp latched in low-level driver/hardware */ @@ -678,11 +680,25 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, */ static inline int snd_pcm_running(struct snd_pcm_substream *substream) { - return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING || - (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING && + return (substream->runtime->state == SNDRV_PCM_STATE_RUNNING || + (substream->runtime->state == SNDRV_PCM_STATE_DRAINING && substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); } +/** + * __snd_pcm_set_state - Change the current PCM state + * @runtime: PCM runtime to set + * @state: the current state to set + * + * Call within the stream lock + */ +static inline void __snd_pcm_set_state(struct snd_pcm_runtime *runtime, + snd_pcm_state_t state) +{ + runtime->state = state; + runtime->status->state = state; /* copy for mmap */ +} + /** * bytes_to_samples - Unit conversion of the size from bytes to samples * @runtime: PCM runtime instance diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 02df915eb3c6..ac2efeb63a39 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1237,12 +1237,12 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: write: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); @@ -1257,7 +1257,7 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const break; /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) + if (runtime->state == SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1269,18 +1269,18 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p snd_pcm_sframes_t delay; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: read: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { + } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -1293,7 +1293,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p frames, in_kernel); mutex_lock(&runtime->oss.params_lock); if (ret == -EPIPE) { - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (runtime->state == SNDRV_PCM_STATE_DRAINING) { ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if (ret < 0) break; @@ -1312,12 +1312,12 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: writev: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); @@ -1330,7 +1330,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) + if (runtime->state == SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1341,18 +1341,18 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: readv: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { + } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -1635,7 +1635,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) result = 0; set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_lock_irq(substream); - state = runtime->status->state; + state = runtime->state; snd_pcm_stream_unlock_irq(substream); if (state != SNDRV_PCM_STATE_RUNNING) { set_current_state(TASK_RUNNING); @@ -2854,8 +2854,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) struct snd_pcm_runtime *runtime = psubstream->runtime; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(psubstream); - if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && - (runtime->status->state != SNDRV_PCM_STATE_RUNNING || + if (runtime->state != SNDRV_PCM_STATE_DRAINING && + (runtime->state != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_playback_ready(psubstream))) mask |= EPOLLOUT | EPOLLWRNORM; snd_pcm_stream_unlock_irq(psubstream); @@ -2865,7 +2865,7 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) snd_pcm_state_t ostate; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(csubstream); - ostate = runtime->status->state; + ostate = runtime->state; if (ostate != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_capture_ready(csubstream)) mask |= EPOLLIN | EPOLLRDNORM; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 82925709fa12..9d95e3731123 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -387,7 +387,7 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); goto unlock; } - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); goto unlock; } @@ -424,7 +424,7 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); goto unlock; } - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); goto unlock; } @@ -970,7 +970,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, init_waitqueue_head(&runtime->sleep); init_waitqueue_head(&runtime->tsleep); - runtime->status->state = SNDRV_PCM_STATE_OPEN; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_OPEN); mutex_init(&runtime->buffer_mutex); atomic_set(&runtime->buffer_accessing, 0); @@ -1112,7 +1112,8 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) if (snd_pcm_running(substream)) snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); /* to be sure, set the state unconditionally */ - substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + __snd_pcm_set_state(substream->runtime, + SNDRV_PCM_STATE_DISCONNECTED); wake_up(&substream->runtime->sleep); wake_up(&substream->runtime->tsleep); } diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 917c5b4f19d7..42c2ada8e888 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -295,7 +295,7 @@ static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, return -ENOTTY; if (substream->stream != dir) return -EINVAL; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (get_user(buf, &data32->buf) || @@ -341,7 +341,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, return -ENOTTY; if (substream->stream != dir) return -EINVAL; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; ch = substream->runtime->channels; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 40751e5aff09..8b6aeb8a78f7 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -186,7 +186,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, avail = snd_pcm_avail(substream); if (avail > runtime->avail_max) runtime->avail_max = avail; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (runtime->state == SNDRV_PCM_STATE_DRAINING) { if (avail >= runtime->buffer_size) { snd_pcm_drain_done(substream); return -EPIPE; @@ -1911,7 +1911,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream, snd_pcm_stream_lock_irq(substream); set_current_state(TASK_INTERRUPTIBLE); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_SUSPENDED: err = -ESTRPIPE; goto _endloop; @@ -2099,14 +2099,14 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) runtime = substream->runtime; if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area)) return -EINVAL; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; return 0; } static int pcm_accessible_state(struct snd_pcm_runtime *runtime) { - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PAUSED: @@ -2225,7 +2225,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, goto _end_unlock; runtime->twake = runtime->control->avail_min ? : 1; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) + if (runtime->state == SNDRV_PCM_STATE_RUNNING) snd_pcm_update_hw_ptr(substream); /* @@ -2233,7 +2233,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, * thread may start capture */ if (!is_playback && - runtime->status->state == SNDRV_PCM_STATE_PREPARED && + runtime->state == SNDRV_PCM_STATE_PREPARED && size >= runtime->start_threshold) { err = snd_pcm_start(substream); if (err < 0) @@ -2247,7 +2247,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, snd_pcm_uframes_t cont; if (!avail) { if (!is_playback && - runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + runtime->state == SNDRV_PCM_STATE_DRAINING) { snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); goto _end_unlock; } @@ -2303,7 +2303,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, xfer += frames; avail -= frames; if (is_playback && - runtime->status->state == SNDRV_PCM_STATE_PREPARED && + runtime->state == SNDRV_PCM_STATE_PREPARED && snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { err = snd_pcm_start(substream); if (err < 0) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ad0541e9e888..d9485b1ab719 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -595,8 +595,8 @@ static void snd_pcm_set_state(struct snd_pcm_substream *substream, snd_pcm_state_t state) { snd_pcm_stream_lock_irq(substream); - if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) - substream->runtime->status->state = state; + if (substream->runtime->state != SNDRV_PCM_STATE_DISCONNECTED) + __snd_pcm_set_state(substream->runtime, state); snd_pcm_stream_unlock_irq(substream); } @@ -724,7 +724,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_SETUP: case SNDRV_PCM_STATE_PREPARED: @@ -889,7 +889,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) if (result < 0) return result; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_SETUP: case SNDRV_PCM_STATE_PREPARED: if (atomic_read(&substream->mmap_count)) @@ -920,7 +920,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, return -ENXIO; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_pcm_stream_unlock_irq(substream); return -EBADFD; } @@ -1013,8 +1013,8 @@ int snd_pcm_status64(struct snd_pcm_substream *substream, } else runtime->audio_tstamp_report.valid = 1; - status->state = runtime->status->state; - status->suspended_state = runtime->status->suspended_state; + status->state = runtime->state; + status->suspended_state = runtime->suspended_state; if (status->state == SNDRV_PCM_STATE_OPEN) goto _end; status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec; @@ -1148,7 +1148,7 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream, channel = info->channel; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_pcm_stream_unlock_irq(substream); return -EBADFD; } @@ -1411,7 +1411,7 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state != SNDRV_PCM_STATE_PREPARED) + if (runtime->state != SNDRV_PCM_STATE_PREPARED) return -EBADFD; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !snd_pcm_playback_data(substream)) @@ -1444,7 +1444,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, runtime->hw_ptr_jiffies = jiffies; runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / runtime->rate; - runtime->status->state = state; + __snd_pcm_set_state(runtime, state); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) snd_pcm_playback_silence(substream, ULONG_MAX); @@ -1485,7 +1485,7 @@ static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; runtime->trigger_master = substream; return 0; @@ -1506,9 +1506,9 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state != state) { + if (runtime->state != state) { snd_pcm_trigger_tstamp(substream); - runtime->status->state = state; + __snd_pcm_set_state(runtime, state); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP); } wake_up(&runtime->sleep); @@ -1584,9 +1584,9 @@ static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, if (!(runtime->info & SNDRV_PCM_INFO_PAUSE)) return -ENOSYS; if (pause_pushed(state)) { - if (runtime->status->state != SNDRV_PCM_STATE_RUNNING) + if (runtime->state != SNDRV_PCM_STATE_RUNNING) return -EBADFD; - } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED) + } else if (runtime->state != SNDRV_PCM_STATE_PAUSED) return -EBADFD; runtime->trigger_master = substream; return 0; @@ -1628,12 +1628,12 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); if (pause_pushed(state)) { - runtime->status->state = SNDRV_PCM_STATE_PAUSED; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_PAUSED); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE); wake_up(&runtime->sleep); wake_up(&runtime->tsleep); } else { - runtime->status->state = SNDRV_PCM_STATE_RUNNING; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_RUNNING); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MCONTINUE); } } @@ -1668,7 +1668,7 @@ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_SUSPENDED: return -EBUSY; /* unresumable PCM state; return -EBUSY for skipping suspend */ @@ -1699,8 +1699,9 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); - runtime->status->suspended_state = runtime->status->state; - runtime->status->state = SNDRV_PCM_STATE_SUSPENDED; + runtime->suspended_state = runtime->state; + runtime->status->suspended_state = runtime->suspended_state; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SUSPENDED); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSUSPEND); wake_up(&runtime->sleep); wake_up(&runtime->tsleep); @@ -1791,8 +1792,8 @@ static int snd_pcm_do_resume(struct snd_pcm_substream *substream, if (runtime->trigger_master != substream) return 0; /* DMA not running previously? */ - if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING && - (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING || + if (runtime->suspended_state != SNDRV_PCM_STATE_RUNNING && + (runtime->suspended_state != SNDRV_PCM_STATE_DRAINING || substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) return 0; return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME); @@ -1811,7 +1812,7 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); - runtime->status->state = runtime->status->suspended_state; + __snd_pcm_set_state(runtime, runtime->suspended_state); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); } @@ -1848,7 +1849,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) int result; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_XRUN: result = 0; /* already there */ break; @@ -1871,7 +1872,7 @@ static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PAUSED: @@ -1933,8 +1934,8 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; int f_flags = (__force int)state; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (snd_pcm_running(substream)) return -EBUSY; @@ -1985,7 +1986,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, f_flags = substream->f_flags; snd_pcm_stream_lock_irq(substream); - switch (substream->runtime->status->state) { + switch (substream->runtime->state) { case SNDRV_PCM_STATE_PAUSED: snd_pcm_pause(substream, false); fallthrough; @@ -2009,7 +2010,7 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_DISCONNECTED: case SNDRV_PCM_STATE_SUSPENDED: @@ -2024,28 +2025,28 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_PREPARED: /* start playback stream if possible */ if (! snd_pcm_playback_empty(substream)) { snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); } else { - runtime->status->state = SNDRV_PCM_STATE_SETUP; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP); } break; case SNDRV_PCM_STATE_RUNNING: - runtime->status->state = SNDRV_PCM_STATE_DRAINING; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_DRAINING); break; case SNDRV_PCM_STATE_XRUN: - runtime->status->state = SNDRV_PCM_STATE_SETUP; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP); break; default: break; } } else { /* stop running stream */ - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) { + if (runtime->state == SNDRV_PCM_STATE_RUNNING) { snd_pcm_state_t new_state; new_state = snd_pcm_capture_avail(runtime) > 0 ? @@ -2055,7 +2056,7 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, } } - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && + if (runtime->state == SNDRV_PCM_STATE_DRAINING && runtime->trigger_master == substream && (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER)) return substream->ops->trigger(substream, @@ -2096,7 +2097,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, card = substream->pcm->card; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (file) { @@ -2107,7 +2108,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, snd_pcm_stream_lock_irq(substream); /* resume pause */ - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) + if (runtime->state == SNDRV_PCM_STATE_PAUSED) snd_pcm_pause(substream, false); /* pre-start/stop - all running streams are changed to DRAINING state */ @@ -2135,7 +2136,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) continue; runtime = s->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (runtime->state == SNDRV_PCM_STATE_DRAINING) { to_check = runtime; break; } @@ -2174,7 +2175,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, break; } if (tout == 0) { - if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) + if (substream->runtime->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; else { dev_dbg(substream->pcm->card->dev, @@ -2206,13 +2207,13 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; snd_pcm_stream_lock_irq(substream); /* resume pause */ - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) + if (runtime->state == SNDRV_PCM_STATE_PAUSED) snd_pcm_pause(substream, false); snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); @@ -2275,8 +2276,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) snd_pcm_group_init(group); down_write(&snd_pcm_link_rwsem); - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || - substream->runtime->status->state != substream1->runtime->status->state || + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN || + substream->runtime->state != substream1->runtime->state || substream->pcm->nonatomic != substream1->pcm->nonatomic) { res = -EBADFD; goto _end; @@ -2700,7 +2701,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) snd_pcm_drop(substream); if (substream->hw_opened) { - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) do_hw_free(substream); substream->ops->close(substream); substream->hw_opened = 0; @@ -2904,7 +2905,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file) */ static int do_pcm_hwsync(struct snd_pcm_substream *substream) { - switch (substream->runtime->status->state) { + switch (substream->runtime->state) { case SNDRV_PCM_STATE_DRAINING: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) return -EBADFD; @@ -3203,7 +3204,7 @@ static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (put_user(0, &_xferi->result)) return -EFAULT; @@ -3226,7 +3227,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream, void *bufs; snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (runtime->channels > 128) return -EINVAL; @@ -3290,7 +3291,7 @@ static int snd_pcm_common_ioctl(struct file *file, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; - if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; res = snd_power_wait(substream->pcm->card); @@ -3421,7 +3422,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, snd_pcm_uframes_t *frames = arg; snd_pcm_sframes_t result; - if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; switch (cmd) { @@ -3466,8 +3467,8 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!frame_aligned(runtime, count)) return -EINVAL; @@ -3491,8 +3492,8 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!frame_aligned(runtime, count)) return -EINVAL; @@ -3518,8 +3519,8 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!iter_is_iovec(to)) return -EINVAL; @@ -3555,8 +3556,8 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!iter_is_iovec(from)) return -EINVAL; @@ -3595,7 +3596,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) return ok | EPOLLERR; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return ok | EPOLLERR; poll_wait(file, &runtime->sleep, wait); @@ -3603,7 +3604,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) mask = 0; snd_pcm_stream_lock_irq(substream); avail = snd_pcm_avail(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PAUSED: @@ -3874,7 +3875,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, return -EINVAL; } runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) return -ENXIO; @@ -3911,7 +3912,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) substream = pcm_file->substream; if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; - if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; offset = area->vm_pgoff << PAGE_SHIFT; @@ -3949,7 +3950,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; return snd_fasync_helper(fd, file, on, &runtime->fasync); } -- cgit v1.2.3 From 1be2143fb7b19e247f7c4aa1097f85fe92c132bf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:49 +0200 Subject: ALSA: pcm: Make mmap status read-only The mmap status record should be read-only. Modifying it from user-space may screw up things unexpectedly, so let's clear the write bits at exposing it. Note that alsa-lib and other known user-space apps access the mmapped status only as read-only, hence this change shouldn't break the existing applications. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/pcm_native.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index d9485b1ab719..33769ca78cc8 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3668,6 +3668,7 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file area->vm_ops = &snd_pcm_vm_ops_status; area->vm_private_data = substream; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + area->vm_flags &= ~(VM_WRITE | VM_MAYWRITE); return 0; } -- cgit v1.2.3 From f7efa9b8a7d959813c63275b2e980de996b8e626 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:50 +0200 Subject: ALSA: aloop: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/drivers/aloop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 12f12a294df5..a38e602b4fc6 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -535,7 +535,7 @@ static void copy_play_buf(struct loopback_pcm *play, /* check if playback is draining, trim the capture copy size * when our pointer is at the end of playback ring buffer */ - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && + if (runtime->state == SNDRV_PCM_STATE_DRAINING && snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) { snd_pcm_uframes_t appl_ptr, appl_ptr1, diff; appl_ptr = appl_ptr1 = runtime->control->appl_ptr; @@ -730,7 +730,7 @@ static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable, if (event == SNDRV_TIMER_EVENT_MSTOP) { if (!dpcm_play || - dpcm_play->substream->runtime->status->state != + dpcm_play->substream->runtime->state != SNDRV_PCM_STATE_DRAINING) { spin_unlock_irqrestore(&cable->lock, flags); return; -- cgit v1.2.3 From 23cb0767f0544858169c02cec445d066d4e02e2b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:51 +0200 Subject: ALSA: firewire: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-5-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/firewire/bebob/bebob_pcm.c | 4 ++-- sound/firewire/dice/dice-pcm.c | 4 ++-- sound/firewire/digi00x/digi00x-pcm.c | 4 ++-- sound/firewire/fireface/ff-pcm.c | 4 ++-- sound/firewire/fireworks/fireworks_pcm.c | 4 ++-- sound/firewire/motu/motu-pcm.c | 4 ++-- sound/firewire/oxfw/oxfw-pcm.c | 8 ++++---- sound/firewire/tascam/tascam-pcm.c | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) (limited to 'sound') diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index f8d9a2041264..ce49eef0fcba 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -214,7 +214,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_bebob *bebob = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -236,7 +236,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&bebob->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) bebob->substreams_counter--; snd_bebob_stream_stop_duplex(bebob); diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index a69ca1111b03..d64366217d57 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -266,7 +266,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_dice *dice = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int events_per_period = params_period_size(hw_params); unsigned int events_per_buffer = params_buffer_size(hw_params); @@ -293,7 +293,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dice->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index b7f6eda09f9f..3bd1575c9d9c 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -190,7 +190,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_dg00x *dg00x = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -212,7 +212,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dg00x->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index f978cc2fed7d..ec915671a79b 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -230,7 +230,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_ff *ff = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -252,7 +252,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&ff->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --ff->substreams_counter; snd_ff_stream_stop_duplex(ff); diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index a0d5db1d8eb2..c3c21860b245 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -250,7 +250,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_efw *efw = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -272,7 +272,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&efw->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --efw->substreams_counter; snd_efw_stream_stop_duplex(efw); diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 8e1437371263..d410c2efbde5 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -210,7 +210,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_motu *motu = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -232,7 +232,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&motu->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 2dfa7e179cb6..5f43a0b826d2 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -239,7 +239,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_oxfw *oxfw = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int channels = params_channels(hw_params); unsigned int frames_per_period = params_period_size(hw_params); @@ -262,7 +262,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_oxfw *oxfw = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int channels = params_channels(hw_params); unsigned int frames_per_period = params_period_size(hw_params); @@ -286,7 +286,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&oxfw->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); @@ -301,7 +301,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&oxfw->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 36c1353f2494..f6da571707ac 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -119,7 +119,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_tscm *tscm = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -141,7 +141,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&tscm->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --tscm->substreams_counter; snd_tscm_stream_stop_duplex(tscm); -- cgit v1.2.3 From 38d8be5df88539dc4a024250ab5988028e21826e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:52 +0200 Subject: ALSA: hda: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-6-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/hda/hdmi_chmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/hda/hdmi_chmap.c b/sound/hda/hdmi_chmap.c index aad5c4bf4d34..5d8e1d944b0a 100644 --- a/sound/hda/hdmi_chmap.c +++ b/sound/hda/hdmi_chmap.c @@ -774,7 +774,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, substream = snd_pcm_chmap_substream(info, ctl_idx); if (!substream || !substream->runtime) return 0; /* just for avoiding error from alsactl restore */ - switch (substream->runtime->status->state) { + switch (substream->runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_SETUP: break; -- cgit v1.2.3 From 7246e5c80630bb4dfdd50c7de2c38c4a91fd36fc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:53 +0200 Subject: ALSA: asihpi: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-7-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/asihpi/asihpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 5e1f9f10051b..8de43aaa10aa 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -632,7 +632,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, /*? workaround linked streams don't transition to SETUP 20070706*/ - s->runtime->status->state = SNDRV_PCM_STATE_SETUP; + __snd_pcm_set_state(s->runtime, SNDRV_PCM_STATE_SETUP); if (card->support_grouping) { snd_printdd("%d group\n", s->number); -- cgit v1.2.3 From d8b4efeeb37ae5e221be6b265a5b93f54c242e82 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:54 +0200 Subject: ALSA: usb-audio: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-8-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e721fc12acde..8ed165f036a0 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1395,7 +1395,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, transfer_done = subs->transfer_done; if (subs->lowlatency_playback && - runtime->status->state != SNDRV_PCM_STATE_DRAINING) { + runtime->state != SNDRV_PCM_STATE_DRAINING) { unsigned int hwptr = subs->hwptr_done / stride; /* calculate the byte offset-in-buffer of the appl_ptr */ @@ -1583,7 +1583,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea return 0; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: - stop_endpoints(subs, substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING); + stop_endpoints(subs, substream->runtime->state == SNDRV_PCM_STATE_DRAINING); snd_usb_endpoint_set_callback(subs->data_endpoint, NULL, NULL, NULL); subs->running = 0; -- cgit v1.2.3 From ca4833c5a21bf419fe505e9798bbf49cbd482e8f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:55 +0200 Subject: ALSA: usx2y: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Link: https://lore.kernel.org/r/20220926135558.26580-9-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/usx2y/usbusx2yaudio.c | 3 +-- sound/usb/usx2y/usx2yhwdeppcm.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 9cd5e3aae4f7..5197599e7aa6 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -822,8 +822,7 @@ static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) usx2y_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || - !cap_subs->pcm_substream->runtime->status || - cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { + cap_subs->pcm_substream->runtime->state < SNDRV_PCM_STATE_PREPARED) { atomic_set(&cap_subs->state, STATE_STOPPED); usx2y_urbs_release(cap_subs); } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 240349b644f3..767a227d54da 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -374,8 +374,7 @@ static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) usx2y_usbpcm_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || - !cap_subs->pcm_substream->runtime->status || - cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { + cap_subs->pcm_substream->runtime->state < SNDRV_PCM_STATE_PREPARED) { atomic_set(&cap_subs->state, STATE_STOPPED); if (cap_subs2) atomic_set(&cap_subs2->state, STATE_STOPPED); -- cgit v1.2.3 From 2bd2dc2672b2d0d45be371430970084330879a46 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:56 +0200 Subject: ASoC: intel: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Acked-by: Mark Brown Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20220926135558.26580-10-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/soc/intel/skylake/skl-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 9d72ebd812af..1015716f9336 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -275,7 +275,7 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream, * calls prepare another time, reset the FW pipe to clean state */ if (mconfig && - (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN || + (substream->runtime->state == SNDRV_PCM_STATE_XRUN || mconfig->pipe->state == SKL_PIPE_CREATED || mconfig->pipe->state == SKL_PIPE_PAUSED)) { @@ -593,7 +593,7 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, /* In case of XRUN recovery, reset the FW pipe to clean state */ mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); if (mconfig && !mconfig->pipe->passthru && - (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) + (substream->runtime->state == SNDRV_PCM_STATE_XRUN)) skl_reset_pipe(skl, mconfig->pipe); return 0; -- cgit v1.2.3 From a267fdd0a6ce3edd6419b10ee7bcde61aa15eb43 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 26 Sep 2022 15:55:57 +0200 Subject: ASoC: sh: Replace runtime->status->state reference to runtime->state The recent change in ALSA core allows drivers to get the current PCM state directly from runtime object. Replace the calls accordingly. Reviewed-by: Jaroslav Kysela Acked-by: Mark Brown Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20220926135558.26580-11-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/soc/sh/rz-ssi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 7ace0c0db5b1..5d6bae33ae34 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -598,7 +598,7 @@ static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi, return -EINVAL; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) + if (runtime->state == SNDRV_PCM_STATE_DRAINING) /* * Stream is ending, so do not queue up any more DMA * transfers otherwise we play partial sound clips -- cgit v1.2.3 From d1c442019594692c64a70a86ad88eb5b6db92216 Mon Sep 17 00:00:00 2001 From: Andreas Pape Date: Mon, 26 Sep 2022 18:58:13 +0200 Subject: ALSA: dmaengine: increment buffer pointer atomically Setting pointer and afterwards checking for wraparound leads to the possibility of returning the inconsistent pointer position. This patch increments buffer pointer atomically to avoid this issue. Fixes: e7f73a1613567a ("ASoC: Add dmaengine PCM helper functions") Signed-off-by: Andreas Pape Signed-off-by: Eugeniu Rosca Link: https://lore.kernel.org/r/1664211493-11789-1-git-send-email-erosca@de.adit-jv.com Signed-off-by: Takashi Iwai --- sound/core/pcm_dmaengine.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 5b2ca028f5aa..494ec0c207fa 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -133,12 +133,14 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); static void dmaengine_pcm_dma_complete(void *arg) { + unsigned int new_pos; struct snd_pcm_substream *substream = arg; struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - prtd->pos += snd_pcm_lib_period_bytes(substream); - if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) - prtd->pos = 0; + new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream); + if (new_pos >= snd_pcm_lib_buffer_bytes(substream)) + new_pos = 0; + prtd->pos = new_pos; snd_pcm_period_elapsed(substream); } -- cgit v1.2.3 From eefe77fdc0de86480f5dbb6bc721396d82d095d3 Mon Sep 17 00:00:00 2001 From: Shang XiaoJing Date: Tue, 27 Sep 2022 22:11:10 +0800 Subject: ALSA: sb: Use DIV_ROUND_UP() instead of open-coding it Use DIV_ROUND_UP() instead of open-coding it, which intents and makes it more clear what is going on for the casual reviewer. The Coccinelle references Commit e4d8aef21403 ("ALSA: usb: Use DIV_ROUND_UP() instead of open-coding it"). Signed-off-by: Shang XiaoJing Link: https://lore.kernel.org/r/20220927141110.18033-1-shangxiaojing@huawei.com Signed-off-by: Takashi Iwai --- sound/isa/sb/emu8000_pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index f8d90a1e989b..c8afc4347c54 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -236,7 +236,7 @@ static int emu8k_pcm_open(struct snd_pcm_substream *subs) /* use timer to update periods.. (specified in msec) */ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, - (1000000 + HZ - 1) / HZ, UINT_MAX); + DIV_ROUND_UP(1000000, HZ), UINT_MAX); return 0; } -- cgit v1.2.3 From 2d6bd853cabc40f9fa7bf48edaa728e19f335e48 Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Wed, 28 Sep 2022 08:48:33 +0000 Subject: ALSA: asihpi - Remove unused struct hpi_subsys_response After commit 3285ea10e9b0("ALSA: asihpi - Interrelated HPI tidy up."), struct hpi_subsys_response is not used any more and can be removed as well. Signed-off-by: Yuan Can Link: https://lore.kernel.org/r/20220928084833.61131-1-yuancan@huawei.com Signed-off-by: Takashi Iwai --- sound/pci/asihpi/hpimsgx.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'sound') diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index f7427f8eb630..d0caef299481 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c @@ -93,11 +93,6 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); #pragma pack(push, 1) #endif -struct hpi_subsys_response { - struct hpi_response_header h; - struct hpi_subsys_res s; -}; - struct hpi_adapter_response { struct hpi_response_header h; struct hpi_adapter_res a; -- cgit v1.2.3 From 225f6e1bc151978041595c7d2acaded3aac41f54 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 29 Sep 2022 08:14:55 +0200 Subject: ALSA: hda/realtek: Add quirk for HP Zbook Firefly 14 G9 model HP Zbook Firefly 14 G9 model (103c:8abb) requires yet another binding with CS35L41 codec, but with a slightly different configuration. It's over spi1 instead of spi0. Create a new fixup entry for that. Cc: Link: https://lore.kernel.org/r/20220929061455.13355-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f9d46ae4c7b7..3dc19174670e 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6741,6 +6741,11 @@ static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixu cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 2); } +static void cs35l41_fixup_spi1_two(struct hda_codec *codec, const struct hda_fixup *fix, int action) +{ + cs35l41_generic_fixup(codec, action, "spi1", "CSC3551", 2); +} + static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fixup *fix, int action) { cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 4); @@ -7132,6 +7137,8 @@ enum { ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED, ALC245_FIXUP_CS35L41_SPI_2, ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED, + ALC245_FIXUP_CS35L41_SPI1_2, + ALC245_FIXUP_CS35L41_SPI1_2_HP_GPIO_LED, ALC245_FIXUP_CS35L41_SPI_4, ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED, ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED, @@ -8979,6 +8986,16 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC285_FIXUP_HP_GPIO_LED, }, + [ALC245_FIXUP_CS35L41_SPI1_2] = { + .type = HDA_FIXUP_FUNC, + .v.func = cs35l41_fixup_spi1_two, + }, + [ALC245_FIXUP_CS35L41_SPI1_2_HP_GPIO_LED] = { + .type = HDA_FIXUP_FUNC, + .v.func = cs35l41_fixup_spi1_two, + .chained = true, + .chain_id = ALC285_FIXUP_HP_GPIO_LED, + }, [ALC245_FIXUP_CS35L41_SPI_4] = { .type = HDA_FIXUP_FUNC, .v.func = cs35l41_fixup_spi_four, @@ -9341,6 +9358,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8aa8, "HP EliteBook 640 G9 (MB 8AA6)", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8aab, "HP EliteBook 650 G9 (MB 8AA9)", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI1_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), -- cgit v1.2.3 From e18f6bcf8e864ea0e9690691d0d749c662b6a2c7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 29 Sep 2022 15:15:28 +0200 Subject: ASoC: wcd-mbhc-v2: Revert "ASoC: wcd-mbhc-v2: use pm_runtime_resume_and_get()" This reverts commit ddea4bbf287b6028eaa15a185d0693856956ecf2 ("ASoC: wcd-mbhc-v2: use pm_runtime_resume_and_get()"), because it introduced double runtime PM put if pm_runtime_get_sync() returns -EACCES: wcd934x-codec wcd934x-codec.3.auto: WCD934X Minor:0x1 Version:0x401 wcd934x-codec wcd934x-codec.3.auto: Runtime PM usage count underflow! The commit claimed no changes in functionality except dropping the reference on -EACCESS. This is exactly the change introducing bug because function calls unconditionally pm_runtime_put_autosuspend() at the end. Fixes: ddea4bbf287b ("ASoC: wcd-mbhc-v2: use pm_runtime_resume_and_get()") Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220929131528.217502-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd-mbhc-v2.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 98baef594bf3..31009283e7d4 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -714,11 +714,12 @@ static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc) struct snd_soc_component *component = mbhc->component; int ret; - ret = pm_runtime_resume_and_get(component->dev); + ret = pm_runtime_get_sync(component->dev); if (ret < 0 && ret != -EACCES) { dev_err_ratelimited(component->dev, - "pm_runtime_resume_and_get failed in %s, ret %d\n", + "pm_runtime_get_sync failed in %s, ret %d\n", __func__, ret); + pm_runtime_put_noidle(component->dev); return ret; } @@ -1096,11 +1097,12 @@ static void wcd_correct_swch_plug(struct work_struct *work) mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch); component = mbhc->component; - ret = pm_runtime_resume_and_get(component->dev); + ret = pm_runtime_get_sync(component->dev); if (ret < 0 && ret != -EACCES) { dev_err_ratelimited(component->dev, - "pm_runtime_resume_and_get failed in %s, ret %d\n", + "pm_runtime_get_sync failed in %s, ret %d\n", __func__, ret); + pm_runtime_put_noidle(component->dev); return; } micbias_mv = wcd_mbhc_get_micbias(mbhc); -- cgit v1.2.3 From 35a1744423743247026668e2323d1b932583fc2a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Sep 2022 10:48:10 +0200 Subject: ALSA: hda/realtek: More robust component matching for CS35L41 As the previous commit implies, a system may have a different SPI bus number that is embedded in the device string. And, assuming the fixed bus number is rather fragile; it may be assigned differently depending on the configuration or on the boot environment. Once when a bus number change happens, the binding fails, resulting in the silence. This patch tries to make the matching a bit more relaxed, allowing to bind with a different bus number (or without it). So the previous fix, the introduction of ALC245_FIXUP_CS35L41_SPI1_2 fixup became superfluous, and this is unified to ALC245_FIXUP_CS35L41_SPI_2. Fixes: 225f6e1bc151 ("ALSA: hda/realtek: Add quirk for HP Zbook Firefly 14 G9 model") Link: https://lore.kernel.org/r/20220930084810.10435-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 62 ++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 25 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3dc19174670e..bce82b834cec 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -6704,23 +6705,51 @@ static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_ } } +struct cs35l41_dev_name { + const char *bus; + const char *hid; + int index; +}; + +/* match the device name in a slightly relaxed manner */ +static int comp_match_cs35l41_dev_name(struct device *dev, void *data) +{ + struct cs35l41_dev_name *p = data; + const char *d = dev_name(dev); + int n = strlen(p->bus); + char tmp[32]; + + /* check the bus name */ + if (strncmp(d, p->bus, n)) + return 0; + /* skip the bus number */ + if (isdigit(d[n])) + n++; + /* the rest must be exact matching */ + snprintf(tmp, sizeof(tmp), "-%s:00-cs35l41-hda.%d", p->hid, p->index); + return !strcmp(d + n, tmp); +} + static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus, const char *hid, int count) { struct device *dev = hda_codec_dev(cdc); struct alc_spec *spec = cdc->spec; - char *name; + struct cs35l41_dev_name *rec; int ret, i; switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: for (i = 0; i < count; i++) { - name = devm_kasprintf(dev, GFP_KERNEL, - "%s-%s:00-cs35l41-hda.%d", bus, hid, i); - if (!name) + rec = devm_kmalloc(dev, sizeof(*rec), GFP_KERNEL); + if (!rec) return; + rec->bus = bus; + rec->hid = hid; + rec->index = i; spec->comps[i].codec = cdc; - component_match_add(dev, &spec->match, component_compare_dev_name, name); + component_match_add(dev, &spec->match, + comp_match_cs35l41_dev_name, rec); } ret = component_master_add_with_match(dev, &comp_master_ops, spec->match); if (ret) @@ -6738,17 +6767,12 @@ static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 2); -} - -static void cs35l41_fixup_spi1_two(struct hda_codec *codec, const struct hda_fixup *fix, int action) -{ - cs35l41_generic_fixup(codec, action, "spi1", "CSC3551", 2); + cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 2); } static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 4); + cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 4); } static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix, @@ -7137,8 +7161,6 @@ enum { ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED, ALC245_FIXUP_CS35L41_SPI_2, ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED, - ALC245_FIXUP_CS35L41_SPI1_2, - ALC245_FIXUP_CS35L41_SPI1_2_HP_GPIO_LED, ALC245_FIXUP_CS35L41_SPI_4, ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED, ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED, @@ -8986,16 +9008,6 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC285_FIXUP_HP_GPIO_LED, }, - [ALC245_FIXUP_CS35L41_SPI1_2] = { - .type = HDA_FIXUP_FUNC, - .v.func = cs35l41_fixup_spi1_two, - }, - [ALC245_FIXUP_CS35L41_SPI1_2_HP_GPIO_LED] = { - .type = HDA_FIXUP_FUNC, - .v.func = cs35l41_fixup_spi1_two, - .chained = true, - .chain_id = ALC285_FIXUP_HP_GPIO_LED, - }, [ALC245_FIXUP_CS35L41_SPI_4] = { .type = HDA_FIXUP_FUNC, .v.func = cs35l41_fixup_spi_four, @@ -9358,7 +9370,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8aa8, "HP EliteBook 640 G9 (MB 8AA6)", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8aab, "HP EliteBook 650 G9 (MB 8AA9)", ALC236_FIXUP_HP_GPIO_LED), - SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI1_2_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), -- cgit v1.2.3 From 568be8aaf8a535f79c4db76cabe17b035aa2584d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Sep 2022 12:01:29 +0200 Subject: ALSA: usb-audio: Fix NULL dererence at error path At an error path to release URB buffers and contexts, the driver might hit a NULL dererence for u->urb pointer, when u->buffer_size has been already set but the actual URB allocation failed. Fix it by adding the NULL check of urb. Also, make sure that buffer_size is cleared after the error path or the close. Cc: Reported-by: Sabri N. Ferreiro Link: https://lore.kernel.org/r/CAKG+3NRjTey+fFfUEGwuxL-pi_=T4cUskYG9OzpzHytF+tzYng@mail.gmail.com Link: https://lore.kernel.org/r/20220930100129.19445-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index b2d0b42b581f..36f753a28341 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -95,12 +95,13 @@ static inline unsigned get_usb_high_speed_rate(unsigned int rate) */ static void release_urb_ctx(struct snd_urb_ctx *u) { - if (u->buffer_size) + if (u->urb && u->buffer_size) usb_free_coherent(u->ep->chip->dev, u->buffer_size, u->urb->transfer_buffer, u->urb->transfer_dma); usb_free_urb(u->urb); u->urb = NULL; + u->buffer_size = 0; } static const char *usb_error_string(int err) -- cgit v1.2.3 From 6382da0828995af87aa8b8bef28cc61aceb4aff3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 30 Sep 2022 12:01:51 +0200 Subject: ALSA: usb-audio: Fix potential memory leaks When the driver hits -ENOMEM at allocating a URB or a buffer, it aborts and goes to the error path that releases the all previously allocated resources. However, when -ENOMEM hits at the middle of the sync EP URB allocation loop, the partially allocated URBs might be left without released, because ep->nurbs is still zero at that point. Fix it by setting ep->nurbs at first, so that the error handler loops over the full URB list. Cc: Link: https://lore.kernel.org/r/20220930100151.19461-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 36f753a28341..48a3843a08f1 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1268,6 +1268,7 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep) if (!ep->syncbuf) return -ENOMEM; + ep->nurbs = SYNC_URBS; for (i = 0; i < SYNC_URBS; i++) { struct snd_urb_ctx *u = &ep->urb[i]; u->index = i; @@ -1287,8 +1288,6 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep) u->urb->complete = snd_complete_urb; } - ep->nurbs = SYNC_URBS; - return 0; out_of_memory: -- cgit v1.2.3 From 5226c7b9784eee215e3914f440b3c2e1764f67a8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 1 Oct 2022 09:48:10 +0200 Subject: ALSA: hda/hdmi: Don't skip notification handling during PM operation The HDMI driver skips the notification handling from the graphics driver when the codec driver is being in the PM operation. This behavior was introduced by the commit eb399d3c99d8 ("ALSA: hda - Skip ELD notification during PM process"). This skip may cause a problem, as we may miss the ELD update when the connection/disconnection happens right at the runtime-PM operation of the audio codec. Although this workaround was valid at that time, it's no longer true; the fix was required just because the ELD update procedure needed to wake up the audio codec, which had lead to a runtime-resume during a runtime-suspend. Meanwhile, the ELD update procedure doesn't need a codec wake up any longer since the commit 788d441a164c ("ALSA: hda - Use component ops for i915 HDMI/DP audio jack handling"); i.e. there is no much reason for skipping the notification. Let's drop those checks for addressing the missing notification. Fixes: 788d441a164c ("ALSA: hda - Use component ops for i915 HDMI/DP audio jack handling") Reported-by: Brent Lu Link: https://lore.kernel.org/r/20220927135807.4097052-1-brent.lu@intel.com Link: https://lore.kernel.org/r/20221001074809.7461-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_hdmi.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index c172640c8a41..21edf7a619f0 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2666,9 +2666,6 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id) */ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) return; - /* ditto during suspend/resume process itself */ - if (snd_hdac_is_in_pm(&codec->core)) - return; check_presence_and_report(codec, pin_nid, dev_id); } @@ -2852,9 +2849,6 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) */ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) return; - /* ditto during suspend/resume process itself */ - if (snd_hdac_is_in_pm(&codec->core)) - return; snd_hdac_i915_set_bclk(&codec->bus->core); check_presence_and_report(codec, pin_nid, dev_id); -- cgit v1.2.3 From 56e696c0f0c71b77fff921fc94b58a02f0445b2c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 1 Oct 2022 16:21:24 +0200 Subject: ALSA: hda: Fix position reporting on Poulsbo Hans reported that his Sony VAIO VPX11S1E showed the broken sound behavior at the start of the stream for a couple of seconds, and it turned out that the position_fix=1 option fixes the issue. It implies that the position reporting is inaccurate, and very likely hitting on all Poulsbo devices. The patch applies the workaround for Poulsbo generically to switch to LPIB mode instead of the default position buffer. Reported-and-tested-by: Hans de Goede Cc: Link: https://lore.kernel.org/r/3e8697e1-87c6-7a7b-d2e8-b21f1d2f181b@redhat.com Link: https://lore.kernel.org/r/20221001142124.7241-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2a93bc64c2d8..6ff19dd0d10c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2547,7 +2547,8 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* Poulsbo */ { PCI_DEVICE(0x8086, 0x811b), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE }, + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE | + AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */ { PCI_DEVICE(0x8086, 0x080a), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE }, -- cgit v1.2.3 From 417b9c51f59734d852e47252476fadc293ad994a Mon Sep 17 00:00:00 2001 From: Callum Osmotherly Date: Wed, 5 Oct 2022 17:44:16 +1030 Subject: ALSA: hda/realtek: remove ALC289_FIXUP_DUAL_SPK for Dell 5530 After some feedback from users with Dell Precision 5530 machines, this patch reverts the previous change to add ALC289_FIXUP_DUAL_SPK. While it improved the speaker output quality, it caused the headphone jack to have an audible "pop" sound when power saving was toggled. Fixes: 1885ff13d4c4 ("ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop") Signed-off-by: Callum Osmotherly Cc: Link: https://lore.kernel.org/r/Yz0uyN1zwZhnyRD6@piranha Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bce82b834cec..d89f95ae0efc 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9198,7 +9198,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB), - SND_PCI_QUIRK(0x1028, 0x087d, "Dell Precision 5530", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), -- cgit v1.2.3 From 9902b303b5ade208b58f0dd38a09831813582211 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 9 Oct 2022 12:42:09 +0200 Subject: ALSA: usb-audio: Avoid unnecessary interface change at EP close We toggle USB interface at PCM prepare and reset at close. When the PCM isn't prepared, resetting again makes little sense. Check the current altset and avoid unnecessary interface reset at EP close. Link: https://lore.kernel.org/r/20221009104212.18877-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 48a3843a08f1..f21acbc9f4f4 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -32,6 +32,7 @@ struct snd_usb_iface_ref { unsigned char iface; bool need_setup; int opened; + int altset; struct list_head list; }; @@ -899,6 +900,9 @@ static int endpoint_set_interface(struct snd_usb_audio *chip, int altset = set ? ep->altsetting : 0; int err; + if (ep->iface_ref->altset == altset) + return 0; + usb_audio_dbg(chip, "Setting usb interface %d:%d for EP 0x%x\n", ep->iface, altset, ep->ep_num); err = usb_set_interface(chip->dev, ep->iface, altset); @@ -910,6 +914,7 @@ static int endpoint_set_interface(struct snd_usb_audio *chip, if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY) msleep(50); + ep->iface_ref->altset = altset; return 0; } -- cgit v1.2.3 From a74f8d0aa902ca494676b79226e0b5a1747b81d4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 9 Oct 2022 12:42:10 +0200 Subject: ALSA: usb-audio: Apply mutex around snd_usb_endpoint_set_params() The protection with chip->mutex was lost after splitting snd_usb_endpoint_set_params() and snd_usb_endpoint_prepare(). Apply the same mutex again to the former function. Fixes: 2be79d586454 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2)") Link: https://lore.kernel.org/r/20221009104212.18877-3-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index f21acbc9f4f4..da378e565ef8 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1337,10 +1337,11 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, const struct audioformat *fmt = ep->cur_audiofmt; int err; + mutex_lock(&chip->mutex); /* release old buffers, if any */ err = release_urbs(ep, false); if (err < 0) - return err; + goto unlock; ep->datainterval = fmt->datainterval; ep->maxpacksize = fmt->maxpacksize; @@ -1378,13 +1379,16 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, usb_audio_dbg(chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err); if (err < 0) - return err; + goto unlock; /* some unit conversions in runtime */ ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes; ep->curframesize = ep->curpacksize / ep->cur_frame_bytes; - return update_clock_ref_rate(chip, ep); + err = update_clock_ref_rate(chip, ep); + unlock: + mutex_unlock(&chip->mutex); + return err; } static int init_sample_rate(struct snd_usb_audio *chip, -- cgit v1.2.3 From 9355b60e401d825590d37f04ea873c58efe9b7bf Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 9 Oct 2022 12:42:11 +0200 Subject: ALSA: usb-audio: Correct the return code from snd_usb_endpoint_set_params() snd_usb_endpoint_set_params() should return zero for a success, but currently it returns the sample rate. Correct it. Fixes: 2be79d586454 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2)") Link: https://lore.kernel.org/r/20221009104212.18877-4-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/endpoint.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound') diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index da378e565ef8..44cce6cec9da 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -1386,6 +1386,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, ep->curframesize = ep->curpacksize / ep->cur_frame_bytes; err = update_clock_ref_rate(chip, ep); + if (err >= 0) + err = 0; unlock: mutex_unlock(&chip->mutex); return err; -- cgit v1.2.3 From 1045f5f1ff0751423aeb65648e5e1abd7a7a8672 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sun, 9 Oct 2022 12:42:12 +0200 Subject: ALSA: usb-audio: Avoid superfluous endpoint setup After splitting to snd_usb_endpoint_set_params() and *_prepare(), the skip of each function should be checked with different flags, while we still use ep->need_setup as the single one. Introduce ep->need_prepare for indicating the need of prepare, and also add the missing check of ep->need_setup at the set_params. Fixes: 2be79d586454 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2)") Link: https://lore.kernel.org/r/20221009104212.18877-5-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/usb/card.h | 3 ++- sound/usb/endpoint.c | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/usb/card.h b/sound/usb/card.h index ca75f2206170..40061550105a 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -129,7 +129,8 @@ struct snd_usb_endpoint { in a stream */ bool implicit_fb_sync; /* syncs with implicit feedback */ bool lowlatency_playback; /* low-latency playback mode */ - bool need_setup; /* (re-)need for configure? */ + bool need_setup; /* (re-)need for hw_params? */ + bool need_prepare; /* (re-)need for prepare? */ /* for hw constraints */ const struct audioformat *cur_audiofmt; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 44cce6cec9da..d0b8d61d1d22 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -824,6 +824,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep->implicit_fb_sync = fp->implicit_fb; ep->need_setup = true; + ep->need_prepare = true; usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n", ep->cur_channels, ep->cur_rate, @@ -952,7 +953,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, /* Prepare for suspening EP, called from the main suspend handler */ void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep) { - ep->need_setup = true; + ep->need_prepare = true; if (ep->iface_ref) ep->iface_ref->need_setup = true; if (ep->clock_ref) @@ -1335,9 +1336,12 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep) { const struct audioformat *fmt = ep->cur_audiofmt; - int err; + int err = 0; mutex_lock(&chip->mutex); + if (!ep->need_setup) + goto unlock; + /* release old buffers, if any */ err = release_urbs(ep, false); if (err < 0) @@ -1386,8 +1390,11 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, ep->curframesize = ep->curpacksize / ep->cur_frame_bytes; err = update_clock_ref_rate(chip, ep); - if (err >= 0) + if (err >= 0) { + ep->need_setup = false; err = 0; + } + unlock: mutex_unlock(&chip->mutex); return err; @@ -1437,7 +1444,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, mutex_lock(&chip->mutex); if (WARN_ON(!ep->iface_ref)) goto unlock; - if (!ep->need_setup) + if (!ep->need_prepare) goto unlock; /* If the interface has been already set up, just set EP parameters */ @@ -1491,7 +1498,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, ep->iface_ref->need_setup = false; done: - ep->need_setup = false; + ep->need_prepare = false; err = 1; unlock: -- cgit v1.2.3 From 66ba7c88507344dee68ad1acbdb630473ab36114 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Mon, 10 Oct 2022 19:57:02 +1300 Subject: ALSA: hda/realtek: Correct pin configs for ASUS G533Z The initial fix for ASUS G533Z was based on faulty information. This fixes the pincfg to values that have been verified with no existing module options or other hacks enabled. Enables headphone jack, and 5.1 surround. [ corrected the indent level by tiwai ] Fixes: bc2c23549ccd ("ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack") Signed-off-by: Luke D. Jones Cc: Link: https://lore.kernel.org/r/20221010065702.35190-1-luke@ljones.dev Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d89f95ae0efc..77a308a71cd4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -8449,11 +8449,13 @@ static const struct hda_fixup alc269_fixups[] = { [ALC285_FIXUP_ASUS_G533Z_PINS] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { - { 0x14, 0x90170120 }, + { 0x14, 0x90170152 }, /* Speaker Surround Playback Switch */ + { 0x19, 0x03a19020 }, /* Mic Boost Volume */ + { 0x1a, 0x03a11c30 }, /* Mic Boost Volume */ + { 0x1e, 0x90170151 }, /* Rear jack, IN OUT EAPD Detect */ + { 0x21, 0x03211420 }, { } }, - .chained = true, - .chain_id = ALC294_FIXUP_ASUS_G513_PINS, }, [ALC294_FIXUP_ASUS_COEF_1B] = { .type = HDA_FIXUP_VERBS, -- cgit v1.2.3 From 2ea8e1297801f7b0220ebf6ae61a5b74ca83981e Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" Date: Mon, 10 Oct 2022 20:03:47 +1300 Subject: ALSA: hda/realtek: Add quirk for ASUS GV601R laptop The ASUS ROG X16 (GV601R) series laptop has the same node-to-DAC pairs as early models and the G14, this includes bass speakers which are by default mapped incorrectly to the 0x06 node. Add a quirk to use the same DAC pairs as the G14. Signed-off-by: Luke D. Jones Cc: Link: https://lore.kernel.org/r/20221010070347.36883-1-luke@ljones.dev Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 77a308a71cd4..54a0f6b4ffc7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9423,6 +9423,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1f92, "ASUS ROG Flow X16", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), -- cgit v1.2.3 From 4f2e56a59b9947b3e698d3cabcb858765c12b1e8 Mon Sep 17 00:00:00 2001 From: Saranya Gopal Date: Tue, 11 Oct 2022 10:19:16 +0530 Subject: ALSA: hda/realtek: Add Intel Reference SSID to support headset keys This patch fixes the issue with 3.5mm headset keys on RPL-P platform. [ Rearranged the entry in SSID order by tiwai ] Signed-off-by: Saranya Gopal Signed-off-by: Ninad Naik Cc: Link: https://lore.kernel.org/r/20221011044916.2278867-1-saranya.gopal@intel.com Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) (limited to 'sound') diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 54a0f6b4ffc7..4b076912bbf4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -9445,6 +9445,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE), SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE), SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), + SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE), -- cgit v1.2.3 From a70aef7982b012e86dfd39fbb235e76a21ae778a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 11 Oct 2022 09:01:46 +0200 Subject: ALSA: rawmidi: Drop register_mutex in snd_rawmidi_free() The register_mutex taken around the dev_unregister callback call in snd_rawmidi_free() may potentially lead to a mutex deadlock, when OSS emulation and a hot unplug are involved. Since the mutex doesn't protect the actual race (as the registration itself is already protected by another means), let's drop it. Link: https://lore.kernel.org/r/CAB7eexJP7w1B0mVgDF0dQ+gWor7UdkiwPczmL7pn91xx8xpzOA@mail.gmail.com Cc: Link: https://lore.kernel.org/r/20221011070147.7611-1-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/rawmidi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'sound') diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6963d5a487b3..d8edb6055072 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1899,10 +1899,8 @@ static int snd_rawmidi_free(struct snd_rawmidi *rmidi) snd_info_free_entry(rmidi->proc_entry); rmidi->proc_entry = NULL; - mutex_lock(®ister_mutex); if (rmidi->ops && rmidi->ops->dev_unregister) rmidi->ops->dev_unregister(rmidi); - mutex_unlock(®ister_mutex); snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); -- cgit v1.2.3 From 97d917879d7f92df09c3f21fd54609a8bcd654b2 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 11 Oct 2022 09:01:47 +0200 Subject: ALSA: oss: Fix potential deadlock at unregistration We took sound_oss_mutex around the calls of unregister_sound_special() at unregistering OSS devices. This may, however, lead to a deadlock, because we manage the card release via the card's device object, and the release may happen at unregister_sound_special() call -- which will take sound_oss_mutex again in turn. Although the deadlock might be fixed by relaxing the rawmidi mutex in the previous commit, it's safer to move unregister_sound_special() calls themselves out of the sound_oss_mutex, too. The call is race-safe as the function has a spinlock protection by itself. Link: https://lore.kernel.org/r/CAB7eexJP7w1B0mVgDF0dQ+gWor7UdkiwPczmL7pn91xx8xpzOA@mail.gmail.com Cc: Link: https://lore.kernel.org/r/20221011070147.7611-2-tiwai@suse.de Signed-off-by: Takashi Iwai --- sound/core/sound_oss.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'sound') diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 7ed0a2a91035..2751bf2ff61b 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -162,7 +162,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) mutex_unlock(&sound_oss_mutex); return -ENOENT; } - unregister_sound_special(minor); switch (SNDRV_MINOR_OSS_DEVICE(minor)) { case SNDRV_MINOR_OSS_PCM: track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO); @@ -174,12 +173,18 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); break; } - if (track2 >= 0) { - unregister_sound_special(track2); + if (track2 >= 0) snd_oss_minors[track2] = NULL; - } snd_oss_minors[minor] = NULL; mutex_unlock(&sound_oss_mutex); + + /* call unregister_sound_special() outside sound_oss_mutex; + * otherwise may deadlock, as it can trigger the release of a card + */ + unregister_sound_special(minor); + if (track2 >= 0) + unregister_sound_special(track2); + kfree(mptr); return 0; } -- cgit v1.2.3 From 49b0dea1eb5e0fd5e498a2c2ce50d2e036494072 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Tue, 11 Oct 2022 15:35:48 +0100 Subject: ALSA: hda: hda_cs_dsp_ctl: Minor clean and redundant code removal The cs_dsp core will return an error if passed a NULL cs_dsp struct so there is no need for the hda_cs_dsp_write|read_ctl functions to manually check that. The cs_dsp core will also check the data is within bounds of the control so the additional bounds check is redundant too. Simplify things a bit by removing said code. Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20221011143552.621792-2-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_cs_dsp_ctl.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 89ee549cb7d5..41d3e8fd289d 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -199,16 +199,10 @@ EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS); int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, const void *buf, size_t len) { - struct cs_dsp_coeff_ctl *cs_ctl; + struct cs_dsp_coeff_ctl *cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); struct hda_cs_dsp_coeff_ctl *ctl; int ret; - cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); - if (!cs_ctl) - return -EINVAL; - - ctl = cs_ctl->priv; - ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len); if (ret) return ret; @@ -216,6 +210,8 @@ int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) return 0; + ctl = cs_ctl->priv; + snd_ctl_notify(ctl->card, SNDRV_CTL_EVENT_MASK_VALUE, &ctl->kctl->id); return 0; @@ -225,13 +221,8 @@ EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, SND_HDA_CS_DSP_CONTROLS); int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, void *buf, size_t len) { - struct cs_dsp_coeff_ctl *cs_ctl; - - cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); - if (!cs_ctl) - return -EINVAL; + return cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len); - return cs_dsp_coeff_read_ctrl(cs_ctl, 0, buf, len); } EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_read_ctl, SND_HDA_CS_DSP_CONTROLS); -- cgit v1.2.3 From 06f3a0a758c4246dc644e22fb33f85c6e5f92af6 Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Tue, 11 Oct 2022 15:35:49 +0100 Subject: ALSA: hda: hda_cs_dsp_ctl: Ensure pwr_lock is held before reading/writing controls These apis require the pwr_lock to be held. Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20221011143552.621792-3-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_cs_dsp_ctl.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 41d3e8fd289d..75fb69185817 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -199,11 +199,14 @@ EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS); int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, const void *buf, size_t len) { - struct cs_dsp_coeff_ctl *cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); + struct cs_dsp_coeff_ctl *cs_ctl; struct hda_cs_dsp_coeff_ctl *ctl; int ret; + mutex_lock(&dsp->pwr_lock); + cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len); + mutex_unlock(&dsp->pwr_lock); if (ret) return ret; @@ -221,7 +224,13 @@ EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, SND_HDA_CS_DSP_CONTROLS); int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, void *buf, size_t len) { - return cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len); + int ret; + + mutex_lock(&dsp->pwr_lock); + ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len); + mutex_unlock(&dsp->pwr_lock); + + return ret; } EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_read_ctl, SND_HDA_CS_DSP_CONTROLS); -- cgit v1.2.3 From 2176c6b599dba55a640cffec0182c0b6bab680d1 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Tue, 11 Oct 2022 15:35:50 +0100 Subject: ALSA: hda/cs_dsp_ctl: Fix mutex inversion when creating controls Redesign the creation of ALSA controls so that the cs_dsp pwr_lock is not held when calling snd_ctl_add(). Instead of creating the ALSA control from the cs_dsp control_add callback, do it after cs_dsp_power_up() has completed. The existing functions are changed to return void instead of passing errors back - this duplicates the original behaviour, as cs_dsp does not abort firmware load if creation of a control fails. It is safe to walk the control list without taking any mutex provided that the caller is not trying to load a new firmware or remove the driver in parallel. There is no other situation that the list can change. So the caller can trigger creation of ALSA controls after cs_dsp_power_up() has returned. A cs_dsp control will have a non-NULL priv pointer if we have created an ALSA control. With the previous code the ALSA controls were created from the cs_dsp control_add callback. But this is called with pwr_lock held (as it is part of the DSP power-up sequence). The kernel lock checking will show a mutex inversion between this and the control creation path: control_add pwr_lock held, takes controls_rwsem (in snd_ctl_add) get/put controls_rwsem held, takes pwr_lock to call cs_dsp. This is not completely theoretical. Although the time window is very small, it is possible for these to run in parallel and deadlock the old implementation. Signed-off-by: Richard Fitzgerald Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20221011143552.621792-4-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 8 +++--- sound/pci/hda/hda_cs_dsp_ctl.c | 59 +++++++++++++++++++++++++----------------- sound/pci/hda/hda_cs_dsp_ctl.h | 2 +- 3 files changed, 40 insertions(+), 29 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 3952f2853703..102ac4a94a9d 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -91,20 +91,18 @@ static const struct reg_sequence cs35l41_hda_mute[] = { { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute }; -static int cs35l41_control_add(struct cs_dsp_coeff_ctl *cs_ctl) +static void cs35l41_add_controls(struct cs35l41_hda *cs35l41) { - struct cs35l41_hda *cs35l41 = container_of(cs_ctl->dsp, struct cs35l41_hda, cs_dsp); struct hda_cs_dsp_ctl_info info; info.device_name = cs35l41->amp_name; info.fw_type = cs35l41->firmware_type; info.card = cs35l41->codec->card; - return hda_cs_dsp_control_add(cs_ctl, &info); + hda_cs_dsp_add_controls(&cs35l41->cs_dsp, &info); } static const struct cs_dsp_client_ops client_ops = { - .control_add = cs35l41_control_add, .control_remove = hda_cs_dsp_control_remove, }; @@ -435,6 +433,8 @@ static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41) if (ret) goto err_release; + cs35l41_add_controls(cs35l41); + ret = cs35l41_save_calibration(cs35l41); err_release: diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 75fb69185817..1622a22f96f6 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -97,7 +97,7 @@ static unsigned int wmfw_convert_flags(unsigned int in) return out; } -static int hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name) +static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name) { struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; struct snd_kcontrol_new kcontrol = {0}; @@ -107,7 +107,7 @@ static int hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char if (cs_ctl->len > ADSP_MAX_STD_CTRL_SIZE) { dev_err(cs_ctl->dsp->dev, "KControl %s: length %zu exceeds maximum %d\n", name, cs_ctl->len, ADSP_MAX_STD_CTRL_SIZE); - return -EINVAL; + return; } kcontrol.name = name; @@ -120,24 +120,21 @@ static int hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char /* Save ctl inside private_data, ctl is owned by cs_dsp, * and will be freed when cs_dsp removes the control */ kctl = snd_ctl_new1(&kcontrol, (void *)ctl); - if (!kctl) { - ret = -ENOMEM; - return ret; - } + if (!kctl) + return; ret = snd_ctl_add(ctl->card, kctl); if (ret) { dev_err(cs_ctl->dsp->dev, "Failed to add KControl %s = %d\n", kcontrol.name, ret); - return ret; + return; } dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol.name); ctl->kctl = kctl; - - return 0; } -int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ctl_info *info) +static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, + const struct hda_cs_dsp_ctl_info *info) { struct cs_dsp *cs_dsp = cs_ctl->dsp; char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -145,13 +142,10 @@ int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ct const char *region_name; int ret; - if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) - return 0; - region_name = cs_dsp_mem_region_name(cs_ctl->alg_region.type); if (!region_name) { - dev_err(cs_dsp->dev, "Unknown region type: %d\n", cs_ctl->alg_region.type); - return -EINVAL; + dev_warn(cs_dsp->dev, "Unknown region type: %d\n", cs_ctl->alg_region.type); + return; } ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %.12s %x", info->device_name, @@ -171,22 +165,39 @@ int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ct ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); if (!ctl) - return -ENOMEM; + return; ctl->cs_ctl = cs_ctl; ctl->card = info->card; cs_ctl->priv = ctl; - ret = hda_cs_dsp_add_kcontrol(ctl, name); - if (ret) { - dev_err(cs_dsp->dev, "Error (%d) adding control %s\n", ret, name); - kfree(ctl); - return ret; - } + hda_cs_dsp_add_kcontrol(ctl, name); +} - return 0; +void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info) +{ + struct cs_dsp_coeff_ctl *cs_ctl; + + /* + * pwr_lock would cause mutex inversion with ALSA control lock compared + * to the get/put functions. + * It is safe to walk the list without holding a mutex because entries + * are persistent and only cs_dsp_power_up() or cs_dsp_remove() can + * change the list. + */ + lockdep_assert_not_held(&dsp->pwr_lock); + + list_for_each_entry(cs_ctl, &dsp->ctl_list, list) { + if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) + continue; + + if (cs_ctl->priv) + continue; + + hda_cs_dsp_control_add(cs_ctl, info); + } } -EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_add, SND_HDA_CS_DSP_CONTROLS); +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_add_controls, SND_HDA_CS_DSP_CONTROLS); void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl) { diff --git a/sound/pci/hda/hda_cs_dsp_ctl.h b/sound/pci/hda/hda_cs_dsp_ctl.h index 4babc69cf2f0..2cf93359c4f2 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.h +++ b/sound/pci/hda/hda_cs_dsp_ctl.h @@ -29,7 +29,7 @@ struct hda_cs_dsp_ctl_info { extern const char * const hda_cs_dsp_fw_ids[HDA_CS_DSP_NUM_FW]; -int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ctl_info *info); +void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info); void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl); int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, const void *buf, size_t len); -- cgit v1.2.3 From 23904f7b2518e9b6bbfe2ac7bbe9e284bcdda18e Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Tue, 11 Oct 2022 15:35:51 +0100 Subject: ALSA: hda: cs35l41: Remove suspend/resume hda hooks The current code uses calls from the HDA Codec driver to determine when to suspend/resume by calling hooks via the hda_component binding. However, this means the cs35l41 driver relies on the HDA Codec driver to tell it when to suspend or resume, creating an additional external dependency, and potentially creating race conditions in the future. It is better for the cs35l41 hda driver to decide for itself when the part should be suspended or resumed. This makes supporting system suspend easier. Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20221011143552.621792-5-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 31 ++++++++++++------------------- sound/pci/hda/hda_component.h | 2 -- sound/pci/hda/patch_realtek.c | 19 +------------------ 3 files changed, 13 insertions(+), 39 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 102ac4a94a9d..89f6b4a28d3d 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -487,10 +487,10 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) struct regmap *reg = cs35l41->regmap; int ret = 0; - mutex_lock(&cs35l41->fw_mutex); - switch (action) { case HDA_GEN_PCM_ACT_OPEN: + pm_runtime_get_sync(dev); + mutex_lock(&cs35l41->fw_mutex); cs35l41->playback_started = true; if (cs35l41->firmware_running) { regmap_multi_reg_write(reg, cs35l41_hda_config_dsp, @@ -508,15 +508,21 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001); + mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_PREPARE: + mutex_lock(&cs35l41->fw_mutex); ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1); + mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLEANUP: + mutex_lock(&cs35l41->fw_mutex); regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0); + mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLOSE: + mutex_lock(&cs35l41->fw_mutex); ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) @@ -530,14 +536,16 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) } cs35l41_irq_release(cs35l41); cs35l41->playback_started = false; + mutex_unlock(&cs35l41->fw_mutex); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); break; default: dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action); break; } - mutex_unlock(&cs35l41->fw_mutex); - if (ret) dev_err(cs35l41->dev, "Regmap access fail: %d\n", ret); } @@ -618,19 +626,6 @@ static int cs35l41_runtime_resume(struct device *dev) return 0; } -static int cs35l41_hda_suspend_hook(struct device *dev) -{ - dev_dbg(dev, "Request Suspend\n"); - pm_runtime_mark_last_busy(dev); - return pm_runtime_put_autosuspend(dev); -} - -static int cs35l41_hda_resume_hook(struct device *dev) -{ - dev_dbg(dev, "Request Resume\n"); - return pm_runtime_get_sync(dev); -} - static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) { int halo_sts; @@ -863,8 +858,6 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas ret = cs35l41_create_controls(cs35l41); comps->playback_hook = cs35l41_hda_playback_hook; - comps->suspend_hook = cs35l41_hda_suspend_hook; - comps->resume_hook = cs35l41_hda_resume_hook; pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h index 1223621bd62c..534e845b9cd1 100644 --- a/sound/pci/hda/hda_component.h +++ b/sound/pci/hda/hda_component.h @@ -16,6 +16,4 @@ struct hda_component { char name[HDA_MAX_NAME_SIZE]; struct hda_codec *codec; void (*playback_hook)(struct device *dev, int action); - int (*suspend_hook)(struct device *dev); - int (*resume_hook)(struct device *dev); }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4b076912bbf4..e6c4bb5fa041 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4022,22 +4022,16 @@ static void alc5505_dsp_init(struct hda_codec *codec) static int alc269_suspend(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int i; if (spec->has_alc5505_dsp) alc5505_dsp_suspend(codec); - for (i = 0; i < HDA_MAX_COMPONENTS; i++) - if (spec->comps[i].suspend_hook) - spec->comps[i].suspend_hook(spec->comps[i].dev); - return alc_suspend(codec); } static int alc269_resume(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int i; if (spec->codec_variant == ALC269_TYPE_ALC269VB) alc269vb_toggle_power_output(codec, 0); @@ -4068,10 +4062,6 @@ static int alc269_resume(struct hda_codec *codec) if (spec->has_alc5505_dsp) alc5505_dsp_resume(codec); - for (i = 0; i < HDA_MAX_COMPONENTS; i++) - if (spec->comps[i].resume_hook) - spec->comps[i].resume_hook(spec->comps[i].dev); - return 0; } #endif /* CONFIG_PM */ @@ -6664,19 +6654,12 @@ static int comp_bind(struct device *dev) { struct hda_codec *cdc = dev_to_hda_codec(dev); struct alc_spec *spec = cdc->spec; - int ret, i; + int ret; ret = component_bind_all(dev, spec->comps); if (ret) return ret; - if (snd_hdac_is_power_on(&cdc->core)) { - codec_dbg(cdc, "Resuming after bind.\n"); - for (i = 0; i < HDA_MAX_COMPONENTS; i++) - if (spec->comps[i].resume_hook) - spec->comps[i].resume_hook(spec->comps[i].dev); - } - return 0; } -- cgit v1.2.3 From 88672826e2a465d2f4c0a50fb5ced2956f4ffcbc Mon Sep 17 00:00:00 2001 From: Stefan Binding Date: Tue, 11 Oct 2022 15:35:52 +0100 Subject: ALSA: hda: cs35l41: Support System Suspend Add support for system suspend into the CS35L41 HDA Driver. Since S4 suspend may power off the system, it is required that the driver ensure the part is safe to be shutdown before system suspend, as well as ensuring that the firmware is unloaded before shutdown. The part must then be restored on system resume, including re-downloading the firmware. Signed-off-by: Stefan Binding Link: https://lore.kernel.org/r/20221011143552.621792-6-sbinding@opensource.cirrus.com Signed-off-by: Takashi Iwai --- sound/pci/hda/cs35l41_hda.c | 160 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 24 deletions(-) (limited to 'sound') diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 89f6b4a28d3d..e5f0549bf06d 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -461,9 +461,12 @@ static void cs35l41_remove_dsp(struct cs35l41_hda *cs35l41) struct cs_dsp *dsp = &cs35l41->cs_dsp; cancel_work_sync(&cs35l41->fw_load_work); + + mutex_lock(&cs35l41->fw_mutex); cs35l41_shutdown_dsp(cs35l41); cs_dsp_remove(dsp); cs35l41->halo_initialized = false; + mutex_unlock(&cs35l41->fw_mutex); } /* Protection release cycle to get the speaker out of Safe-Mode */ @@ -570,45 +573,148 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi rx_slot); } +static void cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41) +{ + mutex_lock(&cs35l41->fw_mutex); + if (cs35l41->firmware_running) { + + regcache_cache_only(cs35l41->regmap, false); + + cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); + cs35l41_shutdown_dsp(cs35l41); + cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); + + regcache_cache_only(cs35l41->regmap, true); + regcache_mark_dirty(cs35l41->regmap); + } + mutex_unlock(&cs35l41->fw_mutex); +} + +static int cs35l41_system_suspend(struct device *dev) +{ + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + int ret; + + dev_dbg(cs35l41->dev, "System Suspend\n"); + + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { + dev_err(cs35l41->dev, "System Suspend not supported\n"); + return -EINVAL; + } + + ret = pm_runtime_force_suspend(dev); + if (ret) + return ret; + + /* Shutdown DSP before system suspend */ + cs35l41_ready_for_reset(cs35l41); + + /* + * Reset GPIO may be shared, so cannot reset here. + * However beyond this point, amps may be powered down. + */ + return 0; +} + +static int cs35l41_system_resume(struct device *dev) +{ + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + int ret; + + dev_dbg(cs35l41->dev, "System Resume\n"); + + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { + dev_err(cs35l41->dev, "System Resume not supported\n"); + return -EINVAL; + } + + if (cs35l41->reset_gpio) { + usleep_range(2000, 2100); + gpiod_set_value_cansleep(cs35l41->reset_gpio, 1); + } + + usleep_range(2000, 2100); + + ret = pm_runtime_force_resume(dev); + + mutex_lock(&cs35l41->fw_mutex); + if (!ret && cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) { + cs35l41->fw_request_ongoing = true; + schedule_work(&cs35l41->fw_load_work); + } + mutex_unlock(&cs35l41->fw_mutex); + + return ret; +} + static int cs35l41_runtime_suspend(struct device *dev) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + int ret = 0; - dev_dbg(cs35l41->dev, "Suspend\n"); + dev_dbg(cs35l41->dev, "Runtime Suspend\n"); - if (!cs35l41->firmware_running) + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { + dev_dbg(cs35l41->dev, "Runtime Suspend not supported\n"); return 0; + } - if (cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type) < 0) - return 0; + mutex_lock(&cs35l41->fw_mutex); + + if (cs35l41->playback_started) { + regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, + ARRAY_SIZE(cs35l41_hda_mute)); + cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, + CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) + regmap_write(cs35l41->regmap, CS35L41_GPIO1_CTRL1, 0x00000001); + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, + CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, + 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT); + cs35l41->playback_started = false; + } + + if (cs35l41->firmware_running) { + ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, + cs35l41->hw_cfg.bst_type); + if (ret) + goto err; + } else { + cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); + } regcache_cache_only(cs35l41->regmap, true); regcache_mark_dirty(cs35l41->regmap); - return 0; +err: + mutex_unlock(&cs35l41->fw_mutex); + + return ret; } static int cs35l41_runtime_resume(struct device *dev) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); - int ret; + int ret = 0; - dev_dbg(cs35l41->dev, "Resume.\n"); + dev_dbg(cs35l41->dev, "Runtime Resume\n"); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { - dev_dbg(cs35l41->dev, "System does not support Resume\n"); + dev_dbg(cs35l41->dev, "Runtime Resume not supported\n"); return 0; } - if (!cs35l41->firmware_running) - return 0; + mutex_lock(&cs35l41->fw_mutex); regcache_cache_only(cs35l41->regmap, false); - ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); - if (ret) { - regcache_cache_only(cs35l41->regmap, true); - return ret; + if (cs35l41->firmware_running) { + ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); + if (ret) { + dev_warn(cs35l41->dev, "Unable to exit Hibernate."); + goto err; + } } /* Test key needs to be unlocked to allow the OTP settings to re-apply */ @@ -617,13 +723,16 @@ static int cs35l41_runtime_resume(struct device *dev) cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap); if (ret) { dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret); - return ret; + goto err; } if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg); - return 0; +err: + mutex_unlock(&cs35l41->fw_mutex); + + return ret; } static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) @@ -673,8 +782,6 @@ clean_dsp: static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load) { - pm_runtime_get_sync(cs35l41->dev); - if (cs35l41->firmware_running && !load) { dev_dbg(cs35l41->dev, "Unloading Firmware\n"); cs35l41_shutdown_dsp(cs35l41); @@ -684,9 +791,6 @@ static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load) } else { dev_dbg(cs35l41->dev, "Unable to Load firmware.\n"); } - - pm_runtime_mark_last_busy(cs35l41->dev); - pm_runtime_put_autosuspend(cs35l41->dev); } static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol, @@ -702,16 +806,21 @@ static void cs35l41_fw_load_work(struct work_struct *work) { struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work); + pm_runtime_get_sync(cs35l41->dev); + mutex_lock(&cs35l41->fw_mutex); /* Recheck if playback is ongoing, mutex will block playback during firmware loading */ if (cs35l41->playback_started) - dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback\n"); + dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n"); else cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load); cs35l41->fw_request_ongoing = false; mutex_unlock(&cs35l41->fw_mutex); + + pm_runtime_mark_last_busy(cs35l41->dev); + pm_runtime_put_autosuspend(cs35l41->dev); } static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol, @@ -835,6 +944,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas pm_runtime_get_sync(dev); + mutex_lock(&cs35l41->fw_mutex); + comps->dev = dev; if (!cs35l41->acpi_subsystem_id) cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x", @@ -847,10 +958,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas if (firmware_autostart) { dev_dbg(cs35l41->dev, "Firmware Autostart.\n"); cs35l41->request_fw_load = true; - mutex_lock(&cs35l41->fw_mutex); if (cs35l41_smart_amp(cs35l41) < 0) dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\n"); - mutex_unlock(&cs35l41->fw_mutex); } else { dev_dbg(cs35l41->dev, "Firmware Autostart is disabled.\n"); } @@ -859,6 +968,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas comps->playback_hook = cs35l41_hda_playback_hook; + mutex_unlock(&cs35l41->fw_mutex); + pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -1426,6 +1537,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); const struct dev_pm_ops cs35l41_hda_pm_ops = { RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume) }; EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41); -- cgit v1.2.3 From 1013999b431b4bcdc1f5ae47dd3338122751db31 Mon Sep 17 00:00:00 2001 From: Siarhei Volkau Date: Sun, 16 Oct 2022 16:26:42 +0300 Subject: ASoC: codecs: jz4725b: add missed Line In power control bit Line In path stayed powered off during capturing or bypass to mixer. Signed-off-by: Siarhei Volkau Link: https://lore.kernel.org/r/20221016132648.3011729-2-lis8215@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4725b.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index 5201a8f6d7b6..cc7a48c96aa4 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -236,7 +236,8 @@ static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = { SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1, REG_CR1_DACSEL_OFFSET, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Line In", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1, + REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0), SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1, REG_CR1_HP_DIS_OFFSET, 1, NULL, 0), -- cgit v1.2.3 From 088777bf65b98cfa4b5378119d0a7d49a58ece44 Mon Sep 17 00:00:00 2001 From: Siarhei Volkau Date: Sun, 16 Oct 2022 16:26:43 +0300 Subject: ASoC: codecs: jz4725b: fix reported volume for Master ctl DAC volume control is the Master Playback Volume at the moment and it reports wrong levels in alsamixer and other alsa apps. The patch fixes that, as stated in manual on the jz4725b SoC (16.6.3.4 Programmable attenuation: GOD) the ctl range varies from -22.5dB to 0dB with 1.5dB step. Signed-off-by: Siarhei Volkau Link: https://lore.kernel.org/r/20221016132648.3011729-3-lis8215@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4725b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index cc7a48c96aa4..72549ee2e789 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -142,8 +142,8 @@ struct jz_icdc { struct clk *clk; }; -static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_dac_tlv, -2250, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0); static const struct snd_kcontrol_new jz4725b_codec_controls[] = { SOC_DOUBLE_TLV("Master Playback Volume", -- cgit v1.2.3 From 1538e2c8c9b7e7a656effcc6e4e7cfe8c1b405fd Mon Sep 17 00:00:00 2001 From: Siarhei Volkau Date: Sun, 16 Oct 2022 16:26:44 +0300 Subject: ASoC: codecs: jz4725b: use right control for Capture Volume Line In Bypass control is used as Master Capture at the moment this is completely incorrect. Current control routed to Mixer instead of ADC, thus can't affect Capture path. ADC control shall be used instead. ADC volume control parameters are different, so the patch fixes that as well. Manual says (16.6.3.2 Programmable input attenuation amplifier: PGATM) that gain varies in range 0dB..22.5dB with 1.5dB step. Signed-off-by: Siarhei Volkau Link: https://lore.kernel.org/r/20221016132648.3011729-4-lis8215@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4725b.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index 72549ee2e789..4363d898a7d4 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -136,13 +136,16 @@ enum { #define REG_CGR3_GO1L_OFFSET 0 #define REG_CGR3_GO1L_MASK (0x1f << REG_CGR3_GO1L_OFFSET) +#define REG_CGR10_GIL_OFFSET 0 +#define REG_CGR10_GIR_OFFSET 4 + struct jz_icdc { struct regmap *regmap; void __iomem *base; struct clk *clk; }; -static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv, 0, 150, 0); static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0); static const struct snd_kcontrol_new jz4725b_codec_controls[] = { @@ -151,11 +154,11 @@ static const struct snd_kcontrol_new jz4725b_codec_controls[] = { REG_CGR1_GODL_OFFSET, REG_CGR1_GODR_OFFSET, 0xf, 1, jz4725b_dac_tlv), - SOC_DOUBLE_R_TLV("Master Capture Volume", - JZ4725B_CODEC_REG_CGR3, - JZ4725B_CODEC_REG_CGR2, - REG_CGR2_GO1R_OFFSET, - 0x1f, 1, jz4725b_line_tlv), + SOC_DOUBLE_TLV("Master Capture Volume", + JZ4725B_CODEC_REG_CGR10, + REG_CGR10_GIL_OFFSET, + REG_CGR10_GIR_OFFSET, + 0xf, 0, jz4725b_adc_tlv), SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1, REG_CR1_DAC_MUTE_OFFSET, 1, 1), -- cgit v1.2.3 From 80852f8268769715db335a22305e81a0c4a38a84 Mon Sep 17 00:00:00 2001 From: Siarhei Volkau Date: Sun, 16 Oct 2022 16:26:45 +0300 Subject: ASoC: codecs: jz4725b: fix capture selector naming At the moment Capture source selector appears on Playback tab in the alsamixer and has a senseless name. Let's fix that. Signed-off-by: Siarhei Volkau Link: https://lore.kernel.org/r/20221016132648.3011729-5-lis8215@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4725b.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'sound') diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index 4363d898a7d4..d57c2c6a3add 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -183,7 +183,7 @@ static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum, jz4725b_codec_adc_src_texts, jz4725b_codec_adc_src_values); static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl = - SOC_DAPM_ENUM("Route", jz4725b_codec_adc_src_enum); + SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum); static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = { SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1, @@ -228,7 +228,7 @@ static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = { SND_SOC_DAPM_ADC("ADC", "Capture", JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1), - SND_SOC_DAPM_MUX("ADC Source", SND_SOC_NOPM, 0, 0, + SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0, &jz4725b_codec_adc_src_ctrl), /* Mixer */ @@ -287,11 +287,11 @@ static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = { {"Mixer", NULL, "DAC to Mixer"}, {"Mixer to ADC", NULL, "Mixer"}, - {"ADC Source", "Mixer", "Mixer to ADC"}, - {"ADC Source", "Line In", "Line In"}, - {"ADC Source", "Mic 1", "Mic 1"}, - {"ADC Source", "Mic 2", "Mic 2"}, - {"ADC", NULL, "ADC Source"}, + {"ADC Source Capture Route", "Mixer", "Mixer to ADC"}, + {"ADC Sourc Capture Routee", "Line In", "Line In"}, + {"ADC Source Capture Route", "Mic 1", "Mic 1"}, + {"ADC Source Capture Route", "Mic 2", "Mic 2"}, + {"ADC", NULL, "ADC Source Capture Route"}, {"Out Stage", NULL, "Mixer"}, {"HP Out", NULL, "Out Stage"}, -- cgit v1.2.3 From df496157a5afa1b6d1f4c46ad6549c2c346d1e59 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 19 Oct 2022 08:16:39 +0100 Subject: ASoC: codecs: jz4725b: Fix spelling mistake "Sourc" -> "Source", "Routee" -> "Route" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are two spelling mistakes in codec routing description. Fix it. Signed-off-by: Colin Ian King Reviewed-by: Philippe Mathieu-Daudé Acked-by: Paul Cercueil Link: https://lore.kernel.org/r/20221019071639.1003730-1-colin.i.king@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4725b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sound') diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index d57c2c6a3add..71ea576f7e67 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -288,7 +288,7 @@ static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = { {"Mixer to ADC", NULL, "Mixer"}, {"ADC Source Capture Route", "Mixer", "Mixer to ADC"}, - {"ADC Sourc Capture Routee", "Line In", "Line In"}, + {"ADC Source Capture Route", "Line In", "Line In"}, {"ADC Source Capture Route", "Mic 1", "Mic 1"}, {"ADC Source Capture Route", "Mic 2", "Mic 2"}, {"ADC", NULL, "ADC Source Capture Route"}, -- cgit v1.2.3