diff options
Diffstat (limited to 'sound/soc/codecs/cs35l32.c')
| -rw-r--r-- | sound/soc/codecs/cs35l32.c | 132 |
1 files changed, 59 insertions, 73 deletions
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 7e9806206648..0bb4bdb3deec 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * cs35l32.c -- CS35L32 ALSA SoC audio driver * * Copyright 2014 CirrusLogic, Inc. * * Author: Brian Austin <brian.austin@cirrus.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/module.h> @@ -17,13 +13,12 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/i2c.h> -#include <linux/gpio.h> #include <linux/regmap.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/gpio/consumer.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> @@ -34,6 +29,7 @@ #include <dt-bindings/sound/cs35l32.h> #include "cs35l32.h" +#include "cirrus_legacy.h" #define CS35L32_NUM_SUPPLIES 2 static const char *const cs35l32_supply_names[CS35L32_NUM_SUPPLIES] = { @@ -43,7 +39,7 @@ static const char *const cs35l32_supply_names[CS35L32_NUM_SUPPLIES] = { struct cs35l32_private { struct regmap *regmap; - struct snd_soc_codec *codec; + struct snd_soc_component *component; struct regulator_bulk_data supplies[CS35L32_NUM_SUPPLIES]; struct cs35l32_platform_data pdata; struct gpio_desc *reset_gpio; @@ -154,16 +150,16 @@ static const struct snd_soc_dapm_route cs35l32_audio_map[] = { static int cs35l32_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { - struct snd_soc_codec *codec = codec_dai->codec; + struct snd_soc_component *component = codec_dai->component; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - snd_soc_update_bits(codec, CS35L32_ADSP_CTL, + case SND_SOC_DAIFMT_CBP_CFP: + snd_soc_component_update_bits(component, CS35L32_ADSP_CTL, CS35L32_ADSP_MASTER_MASK, CS35L32_ADSP_MASTER_MASK); break; - case SND_SOC_DAIFMT_CBS_CFS: - snd_soc_update_bits(codec, CS35L32_ADSP_CTL, + case SND_SOC_DAIFMT_CBC_CFC: + snd_soc_component_update_bits(component, CS35L32_ADSP_CTL, CS35L32_ADSP_MASTER_MASK, 0); break; default: @@ -175,9 +171,9 @@ static int cs35l32_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) static int cs35l32_set_tristate(struct snd_soc_dai *dai, int tristate) { - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; - return snd_soc_update_bits(codec, CS35L32_PWRCTL2, + return snd_soc_component_update_bits(component, CS35L32_PWRCTL2, CS35L32_SDOUT_3ST, tristate << 3); } @@ -198,11 +194,11 @@ static struct snd_soc_dai_driver cs35l32_dai[] = { .formats = CS35L32_FORMATS, }, .ops = &cs35l32_ops, - .symmetric_rates = 1, + .symmetric_rate = 1, } }; -static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec, +static int cs35l32_component_set_sysclk(struct snd_soc_component *component, int clk_id, int source, unsigned int freq, int dir) { unsigned int val; @@ -224,21 +220,21 @@ static int cs35l32_codec_set_sysclk(struct snd_soc_codec *codec, return -EINVAL; } - return snd_soc_update_bits(codec, CS35L32_CLK_CTL, + return snd_soc_component_update_bits(component, CS35L32_CLK_CTL, CS35L32_MCLK_DIV2_MASK | CS35L32_MCLK_RATIO_MASK, val); } -static const struct snd_soc_codec_driver soc_codec_dev_cs35l32 = { - .set_sysclk = cs35l32_codec_set_sysclk, - - .component_driver = { - .controls = cs35l32_snd_controls, - .num_controls = ARRAY_SIZE(cs35l32_snd_controls), - .dapm_widgets = cs35l32_dapm_widgets, - .num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets), - .dapm_routes = cs35l32_audio_map, - .num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map), - }, +static const struct snd_soc_component_driver soc_component_dev_cs35l32 = { + .set_sysclk = cs35l32_component_set_sysclk, + .controls = cs35l32_snd_controls, + .num_controls = ARRAY_SIZE(cs35l32_snd_controls), + .dapm_widgets = cs35l32_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(cs35l32_dapm_widgets), + .dapm_routes = cs35l32_audio_map, + .num_dapm_routes = ARRAY_SIZE(cs35l32_audio_map), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, }; /* Current and threshold powerup sequence Pg37 in datasheet */ @@ -263,7 +259,10 @@ static const struct regmap_config cs35l32_regmap = { .volatile_reg = cs35l32_volatile_register, .readable_reg = cs35l32_readable_register, .precious_reg = cs35l32_precious_register, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, + + .use_single_read = true, + .use_single_write = true, }; static int cs35l32_handle_of_data(struct i2c_client *i2c_client, @@ -345,23 +344,17 @@ static int cs35l32_handle_of_data(struct i2c_client *i2c_client, return 0; } -static int cs35l32_i2c_probe(struct i2c_client *i2c_client, - const struct i2c_device_id *id) +static int cs35l32_i2c_probe(struct i2c_client *i2c_client) { struct cs35l32_private *cs35l32; struct cs35l32_platform_data *pdata = dev_get_platdata(&i2c_client->dev); - int ret, i; - unsigned int devid = 0; + int ret, i, devid; unsigned int reg; - - cs35l32 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs35l32_private), - GFP_KERNEL); - if (!cs35l32) { - dev_err(&i2c_client->dev, "could not allocate codec\n"); + cs35l32 = devm_kzalloc(&i2c_client->dev, sizeof(*cs35l32), GFP_KERNEL); + if (!cs35l32) return -ENOMEM; - } i2c_set_clientdata(i2c_client, cs35l32); @@ -375,13 +368,11 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client, if (pdata) { cs35l32->pdata = *pdata; } else { - pdata = devm_kzalloc(&i2c_client->dev, - sizeof(struct cs35l32_platform_data), - GFP_KERNEL); - if (!pdata) { - dev_err(&i2c_client->dev, "could not allocate pdata\n"); + pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata), + GFP_KERNEL); + if (!pdata) return -ENOMEM; - } + if (i2c_client->dev.of_node) { ret = cs35l32_handle_of_data(i2c_client, &cs35l32->pdata); @@ -413,40 +404,40 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client, /* Reset the Device */ cs35l32->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(cs35l32->reset_gpio)) - return PTR_ERR(cs35l32->reset_gpio); + if (IS_ERR(cs35l32->reset_gpio)) { + ret = PTR_ERR(cs35l32->reset_gpio); + goto err_supplies; + } gpiod_set_value_cansleep(cs35l32->reset_gpio, 1); /* initialize codec */ - ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_AB, ®); - devid = (reg & 0xFF) << 12; - - ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_CD, ®); - devid |= (reg & 0xFF) << 4; - - ret = regmap_read(cs35l32->regmap, CS35L32_DEVID_E, ®); - devid |= (reg & 0xF0) >> 4; + devid = cirrus_read_device_id(cs35l32->regmap, CS35L32_DEVID_AB); + if (devid < 0) { + ret = devid; + dev_err(&i2c_client->dev, "Failed to read device ID: %d\n", ret); + goto err_disable; + } if (devid != CS35L32_CHIP_ID) { ret = -ENODEV; dev_err(&i2c_client->dev, "CS35L32 Device ID (%X). Expected %X\n", devid, CS35L32_CHIP_ID); - return ret; + goto err_disable; } ret = regmap_read(cs35l32->regmap, CS35L32_REV_ID, ®); if (ret < 0) { dev_err(&i2c_client->dev, "Get Revision ID failed\n"); - return ret; + goto err_disable; } ret = regmap_register_patch(cs35l32->regmap, cs35l32_monitor_patch, ARRAY_SIZE(cs35l32_monitor_patch)); if (ret < 0) { dev_err(&i2c_client->dev, "Failed to apply errata patch\n"); - return ret; + goto err_disable; } dev_info(&i2c_client->dev, @@ -487,10 +478,10 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client, CS35L32_PDN_AMP); /* Clear MCLK Error Bit since we don't have the clock yet */ - ret = regmap_read(cs35l32->regmap, CS35L32_INT_STATUS_1, ®); + regmap_read(cs35l32->regmap, CS35L32_INT_STATUS_1, ®); - ret = snd_soc_register_codec(&i2c_client->dev, - &soc_codec_dev_cs35l32, cs35l32_dai, + ret = devm_snd_soc_register_component(&i2c_client->dev, + &soc_component_dev_cs35l32, cs35l32_dai, ARRAY_SIZE(cs35l32_dai)); if (ret < 0) goto err_disable; @@ -498,24 +489,21 @@ static int cs35l32_i2c_probe(struct i2c_client *i2c_client, return 0; err_disable: + gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); +err_supplies: regulator_bulk_disable(ARRAY_SIZE(cs35l32->supplies), cs35l32->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); - snd_soc_unregister_codec(&i2c_client->dev); - /* Hold down reset */ gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); - - return 0; } -#ifdef CONFIG_PM static int cs35l32_runtime_suspend(struct device *dev) { struct cs35l32_private *cs35l32 = dev_get_drvdata(dev); @@ -554,11 +542,9 @@ static int cs35l32_runtime_resume(struct device *dev) return 0; } -#endif static const struct dev_pm_ops cs35l32_runtime_pm = { - SET_RUNTIME_PM_OPS(cs35l32_runtime_suspend, cs35l32_runtime_resume, - NULL) + RUNTIME_PM_OPS(cs35l32_runtime_suspend, cs35l32_runtime_resume, NULL) }; static const struct of_device_id cs35l32_of_match[] = { @@ -569,7 +555,7 @@ MODULE_DEVICE_TABLE(of, cs35l32_of_match); static const struct i2c_device_id cs35l32_id[] = { - {"cs35l32", 0}, + {"cs35l32"}, {} }; @@ -578,7 +564,7 @@ MODULE_DEVICE_TABLE(i2c, cs35l32_id); static struct i2c_driver cs35l32_i2c_driver = { .driver = { .name = "cs35l32", - .pm = &cs35l32_runtime_pm, + .pm = pm_ptr(&cs35l32_runtime_pm), .of_match_table = cs35l32_of_match, }, .id_table = cs35l32_id, |
