ASoC: codec: cs42l[56,73,52]: Convert to GPIO

Merge series from "Peng Fan (OSS)" <peng.fan@oss.nxp.com>:

This patchset is separate from [1], and not merging changes in one
patch. So separate changes into three patches for each chip.
- sort headers
- Drop legacy platform support
- Convert to GPIO descriptors

of_gpio.h is deprecated, update the driver to use GPIO descriptors.
 - Use devm_gpiod_get_optional to get GPIO descriptor with default
   polarity GPIOD_OUT_LOW, set consumer name.
 - Use gpiod_set_value_cansleep to configure output value.

I not have platforms to test, just do the patches with my best efforts,
and make build pass.

[1] https://lore.kernel.org/all/20250408-asoc-gpio-v1-0-c0db9d3fd6e9@nxp.com/
This commit is contained in:
Mark Brown
2025-05-07 14:12:15 +09:00
6 changed files with 144 additions and 209 deletions

View File

@@ -1,29 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/sound/cs42l52.h -- Platform data for CS42L52
*
* Copyright (c) 2012 Cirrus Logic Inc.
*/
#ifndef __CS42L52_H
#define __CS42L52_H
struct cs42l52_platform_data {
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* MICA mode selection Differential or Single-ended */
bool mica_diff_cfg;
/* MICB mode selection Differential or Single-ended */
bool micb_diff_cfg;
/* Charge Pump Freq. Check datasheet Pg73 */
unsigned int chgfreq;
/* Reset GPIO */
unsigned int reset_gpio;
};
#endif /* __CS42L52_H */

View File

@@ -1,45 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/sound/cs42l56.h -- Platform data for CS42L56
*
* Copyright (c) 2014 Cirrus Logic Inc.
*/
#ifndef __CS42L56_H
#define __CS42L56_H
struct cs42l56_platform_data {
/* GPIO for Reset */
unsigned int gpio_nreset;
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* Analog Input 1A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1a_ref_cfg;
/* Analog Input 2A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2a_ref_cfg;
/* Analog Input 1B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1b_ref_cfg;
/* Analog Input 2B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2b_ref_cfg;
/* Charge Pump Freq. Check datasheet Pg62 */
unsigned int chgfreq;
/* HighPass Filter Right Channel Corner Frequency */
unsigned int hpfb_freq;
/* HighPass Filter Left Channel Corner Frequency */
unsigned int hpfa_freq;
/* Adaptive Power Control for LO/HP */
unsigned int adaptive_pwr;
};
#endif /* __CS42L56_H */

View File

@@ -1,19 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* linux/sound/cs42l73.h -- Platform data for CS42L73
*
* Copyright (c) 2012 Cirrus Logic Inc.
*/
#ifndef __CS42L73_H
#define __CS42L73_H
struct cs42l73_platform_data {
/* RST GPIO */
unsigned int reset_gpio;
unsigned int chgfreq;
int jack_detection;
unsigned int mclk_freq;
};
#endif /* __CS42L73_H */

View File

@@ -8,27 +8,26 @@
* Author: Brian Austin <brian.austin@cirrus.com>
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/cs42l52.h>
#include "cs42l52.h"
struct sp_config {
@@ -36,6 +35,24 @@ struct sp_config {
u32 srate;
};
struct cs42l52_platform_data {
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* MICA mode selection Differential or Single-ended */
bool mica_diff_cfg;
/* MICB mode selection Differential or Single-ended */
bool micb_diff_cfg;
/* Charge Pump Freq. Check datasheet Pg73 */
unsigned int chgfreq;
/* Reset GPIO */
struct gpio_desc *reset_gpio;
};
struct cs42l52_private {
struct regmap *regmap;
struct snd_soc_component *component;
@@ -1090,7 +1107,7 @@ static const struct regmap_config cs42l52_regmap = {
static int cs42l52_i2c_probe(struct i2c_client *i2c_client)
{
struct cs42l52_private *cs42l52;
struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
struct cs42l52_platform_data *pdata;
int ret;
unsigned int devid;
unsigned int reg;
@@ -1107,50 +1124,43 @@ static int cs42l52_i2c_probe(struct i2c_client *i2c_client)
dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
return ret;
}
if (pdata) {
cs42l52->pdata = *pdata;
} else {
pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata),
GFP_KERNEL);
if (!pdata)
return -ENOMEM;
if (i2c_client->dev.of_node) {
if (of_property_read_bool(i2c_client->dev.of_node,
"cirrus,mica-differential-cfg"))
pdata->mica_diff_cfg = true;
pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
if (of_property_read_bool(i2c_client->dev.of_node,
"cirrus,micb-differential-cfg"))
pdata->micb_diff_cfg = true;
if (i2c_client->dev.of_node) {
if (of_property_read_bool(i2c_client->dev.of_node,
"cirrus,mica-differential-cfg"))
pdata->mica_diff_cfg = true;
if (of_property_read_u32(i2c_client->dev.of_node,
"cirrus,micbias-lvl", &val32) >= 0)
pdata->micbias_lvl = val32;
if (of_property_read_bool(i2c_client->dev.of_node,
"cirrus,micb-differential-cfg"))
pdata->micb_diff_cfg = true;
if (of_property_read_u32(i2c_client->dev.of_node,
"cirrus,chgfreq-divisor", &val32) >= 0)
pdata->chgfreq = val32;
if (of_property_read_u32(i2c_client->dev.of_node,
"cirrus,micbias-lvl", &val32) >= 0)
pdata->micbias_lvl = val32;
pdata->reset_gpio =
of_get_named_gpio(i2c_client->dev.of_node,
"cirrus,reset-gpio", 0);
}
cs42l52->pdata = *pdata;
if (of_property_read_u32(i2c_client->dev.of_node,
"cirrus,chgfreq-divisor", &val32) >= 0)
pdata->chgfreq = val32;
pdata->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
"cirrus,reset",
GPIOD_OUT_LOW);
if (IS_ERR(pdata->reset_gpio))
return PTR_ERR(pdata->reset_gpio);
gpiod_set_consumer_name(pdata->reset_gpio, "CS42L52 /RST");
}
cs42l52->pdata = *pdata;
if (cs42l52->pdata.reset_gpio) {
ret = devm_gpio_request_one(&i2c_client->dev,
cs42l52->pdata.reset_gpio,
GPIOF_OUT_INIT_HIGH,
"CS42L52 /RST");
if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
cs42l52->pdata.reset_gpio, ret);
return ret;
}
gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 0);
gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 1);
gpiod_set_value_cansleep(cs42l52->pdata.reset_gpio, 1);
gpiod_set_value_cansleep(cs42l52->pdata.reset_gpio, 0);
}
i2c_set_clientdata(i2c_client, cs42l52);

View File

@@ -7,32 +7,64 @@
* Author: Brian Austin <brian.austin@cirrus.com>
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/cs42l56.h>
#include "cs42l56.h"
#define CS42L56_NUM_SUPPLIES 3
struct cs42l56_platform_data {
/* GPIO for Reset */
struct gpio_desc *gpio_nreset;
/* MICBIAS Level. Check datasheet Pg48 */
unsigned int micbias_lvl;
/* Analog Input 1A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1a_ref_cfg;
/* Analog Input 2A Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2a_ref_cfg;
/* Analog Input 1B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain1b_ref_cfg;
/* Analog Input 2B Reference 0=Single 1=Pseudo-Differential */
unsigned int ain2b_ref_cfg;
/* Charge Pump Freq. Check datasheet Pg62 */
unsigned int chgfreq;
/* HighPass Filter Right Channel Corner Frequency */
unsigned int hpfb_freq;
/* HighPass Filter Left Channel Corner Frequency */
unsigned int hpfa_freq;
/* Adaptive Power Control for LO/HP */
unsigned int adaptive_pwr;
};
static const char *const cs42l56_supply_names[CS42L56_NUM_SUPPLIES] = {
"VA",
"VCP",
@@ -1161,7 +1193,13 @@ static int cs42l56_handle_of_data(struct i2c_client *i2c_client,
if (of_property_read_u32(np, "cirrus,hpf-left-freq", &val32) >= 0)
pdata->hpfb_freq = val32;
pdata->gpio_nreset = of_get_named_gpio(np, "cirrus,gpio-nreset", 0);
pdata->gpio_nreset = devm_gpiod_get_optional(&i2c_client->dev, "cirrus,gpio-nreset",
GPIOD_OUT_LOW);
if (IS_ERR(pdata->gpio_nreset))
return PTR_ERR(pdata->gpio_nreset);
gpiod_set_consumer_name(pdata->gpio_nreset, "CS42L56 /RST");
return 0;
}
@@ -1169,8 +1207,6 @@ static int cs42l56_handle_of_data(struct i2c_client *i2c_client,
static int cs42l56_i2c_probe(struct i2c_client *i2c_client)
{
struct cs42l56_private *cs42l56;
struct cs42l56_platform_data *pdata =
dev_get_platdata(&i2c_client->dev);
int ret, i;
unsigned int devid;
unsigned int alpha_rev, metal_rev;
@@ -1188,31 +1224,17 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client)
return ret;
}
if (pdata) {
cs42l56->pdata = *pdata;
} else {
if (i2c_client->dev.of_node) {
ret = cs42l56_handle_of_data(i2c_client,
&cs42l56->pdata);
if (ret != 0)
return ret;
}
if (i2c_client->dev.of_node) {
ret = cs42l56_handle_of_data(i2c_client, &cs42l56->pdata);
if (ret != 0)
return ret;
}
if (cs42l56->pdata.gpio_nreset) {
ret = gpio_request_one(cs42l56->pdata.gpio_nreset,
GPIOF_OUT_INIT_HIGH, "CS42L56 /RST");
if (ret < 0) {
dev_err(&i2c_client->dev,
"Failed to request /RST %d: %d\n",
cs42l56->pdata.gpio_nreset, ret);
return ret;
}
gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 0);
gpio_set_value_cansleep(cs42l56->pdata.gpio_nreset, 1);
gpiod_set_value_cansleep(cs42l56->pdata.gpio_nreset, 1);
gpiod_set_value_cansleep(cs42l56->pdata.gpio_nreset, 0);
}
i2c_set_clientdata(i2c_client, cs42l56);
for (i = 0; i < ARRAY_SIZE(cs42l56->supplies); i++)

View File

@@ -8,26 +8,33 @@
* Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>
*/
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include <sound/cs42l73.h>
#include "cs42l73.h"
#include "cirrus_legacy.h"
#include "cs42l73.h"
struct cs42l73_platform_data {
/* RST GPIO */
struct gpio_desc *reset_gpio;
unsigned int chgfreq;
int jack_detection;
unsigned int mclk_freq;
};
struct sp_config {
u8 spc, mmcc, spfs;
@@ -1276,7 +1283,7 @@ static const struct regmap_config cs42l73_regmap = {
static int cs42l73_i2c_probe(struct i2c_client *i2c_client)
{
struct cs42l73_private *cs42l73;
struct cs42l73_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
struct cs42l73_platform_data *pdata;
int ret, devid;
unsigned int reg;
u32 val32;
@@ -1292,38 +1299,27 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client)
return ret;
}
if (pdata) {
cs42l73->pdata = *pdata;
} else {
pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata),
GFP_KERNEL);
if (!pdata)
return -ENOMEM;
pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
if (i2c_client->dev.of_node) {
if (of_property_read_u32(i2c_client->dev.of_node,
"chgfreq", &val32) >= 0)
pdata->chgfreq = val32;
}
pdata->reset_gpio = of_get_named_gpio(i2c_client->dev.of_node,
"reset-gpio", 0);
cs42l73->pdata = *pdata;
if (i2c_client->dev.of_node) {
if (of_property_read_u32(i2c_client->dev.of_node, "chgfreq", &val32) >= 0)
pdata->chgfreq = val32;
}
pdata->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(pdata->reset_gpio))
return PTR_ERR(pdata->reset_gpio);
gpiod_set_consumer_name(pdata->reset_gpio, "CS42L73 /RST");
cs42l73->pdata = *pdata;
i2c_set_clientdata(i2c_client, cs42l73);
if (cs42l73->pdata.reset_gpio) {
ret = devm_gpio_request_one(&i2c_client->dev,
cs42l73->pdata.reset_gpio,
GPIOF_OUT_INIT_HIGH,
"CS42L73 /RST");
if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
cs42l73->pdata.reset_gpio, ret);
return ret;
}
gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
gpiod_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
gpiod_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
}
/* initialize codec */
@@ -1360,7 +1356,7 @@ static int cs42l73_i2c_probe(struct i2c_client *i2c_client)
return 0;
err_reset:
gpio_set_value_cansleep(cs42l73->pdata.reset_gpio, 0);
gpiod_set_value_cansleep(cs42l73->pdata.reset_gpio, 1);
return ret;
}