Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver
0004  *
0005  * Copyright (C) Nokia Corporation
0006  *
0007  * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/errno.h>
0012 #include <linux/device.h>
0013 #include <linux/i2c.h>
0014 #include <linux/gpio.h>
0015 #include <linux/regulator/consumer.h>
0016 #include <linux/slab.h>
0017 #include <sound/tpa6130a2-plat.h>
0018 #include <sound/soc.h>
0019 #include <sound/tlv.h>
0020 #include <linux/of.h>
0021 #include <linux/of_gpio.h>
0022 #include <linux/regmap.h>
0023 
0024 #include "tpa6130a2.h"
0025 
0026 enum tpa_model {
0027     TPA6130A2,
0028     TPA6140A2,
0029 };
0030 
0031 /* This struct is used to save the context */
0032 struct tpa6130a2_data {
0033     struct device *dev;
0034     struct regmap *regmap;
0035     struct regulator *supply;
0036     int power_gpio;
0037     enum tpa_model id;
0038 };
0039 
0040 static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable)
0041 {
0042     int ret = 0, ret2;
0043 
0044     if (enable) {
0045         ret = regulator_enable(data->supply);
0046         if (ret != 0) {
0047             dev_err(data->dev,
0048                 "Failed to enable supply: %d\n", ret);
0049             return ret;
0050         }
0051         /* Power on */
0052         if (data->power_gpio >= 0)
0053             gpio_set_value(data->power_gpio, 1);
0054 
0055         /* Sync registers */
0056         regcache_cache_only(data->regmap, false);
0057         ret = regcache_sync(data->regmap);
0058         if (ret != 0) {
0059             dev_err(data->dev,
0060                 "Failed to sync registers: %d\n", ret);
0061             regcache_cache_only(data->regmap, true);
0062             if (data->power_gpio >= 0)
0063                 gpio_set_value(data->power_gpio, 0);
0064             ret2 = regulator_disable(data->supply);
0065             if (ret2 != 0)
0066                 dev_err(data->dev,
0067                     "Failed to disable supply: %d\n", ret2);
0068             return ret;
0069         }
0070     } else {
0071         /* Powered off device does not retain registers. While device
0072          * is off, any register updates (i.e. volume changes) should
0073          * happen in cache only.
0074          */
0075         regcache_mark_dirty(data->regmap);
0076         regcache_cache_only(data->regmap, true);
0077 
0078         /* Power off */
0079         if (data->power_gpio >= 0)
0080             gpio_set_value(data->power_gpio, 0);
0081 
0082         ret = regulator_disable(data->supply);
0083         if (ret != 0) {
0084             dev_err(data->dev,
0085                 "Failed to disable supply: %d\n", ret);
0086             return ret;
0087         }
0088     }
0089 
0090     return ret;
0091 }
0092 
0093 static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w,
0094                  struct snd_kcontrol *kctrl, int event)
0095 {
0096     struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
0097     struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c);
0098 
0099     if (SND_SOC_DAPM_EVENT_ON(event)) {
0100         /* Before widget power up: turn chip on, sync registers */
0101         return tpa6130a2_power(data, true);
0102     } else {
0103         /* After widget power down: turn chip off */
0104         return tpa6130a2_power(data, false);
0105     }
0106 }
0107 
0108 /*
0109  * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
0110  * down in gain.
0111  */
0112 static const DECLARE_TLV_DB_RANGE(tpa6130_tlv,
0113     0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0),
0114     2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0),
0115     4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0),
0116     6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0),
0117     8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0),
0118     10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0),
0119     12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0),
0120     14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0),
0121     21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0),
0122     38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0)
0123 );
0124 
0125 static const struct snd_kcontrol_new tpa6130a2_controls[] = {
0126     SOC_SINGLE_TLV("Headphone Playback Volume",
0127                TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
0128                tpa6130_tlv),
0129 };
0130 
0131 static const DECLARE_TLV_DB_RANGE(tpa6140_tlv,
0132     0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0),
0133     9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0),
0134     17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0)
0135 );
0136 
0137 static const struct snd_kcontrol_new tpa6140a2_controls[] = {
0138     SOC_SINGLE_TLV("Headphone Playback Volume",
0139                TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0,
0140                tpa6140_tlv),
0141 };
0142 
0143 static int tpa6130a2_component_probe(struct snd_soc_component *component)
0144 {
0145     struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
0146 
0147     if (data->id == TPA6140A2)
0148         return snd_soc_add_component_controls(component,
0149             tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls));
0150     else
0151         return snd_soc_add_component_controls(component,
0152             tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls));
0153 }
0154 
0155 static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
0156     SND_SOC_DAPM_INPUT("LEFTIN"),
0157     SND_SOC_DAPM_INPUT("RIGHTIN"),
0158     SND_SOC_DAPM_OUTPUT("HPLEFT"),
0159     SND_SOC_DAPM_OUTPUT("HPRIGHT"),
0160 
0161     SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE,
0162              TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0),
0163     SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE,
0164              TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0),
0165     SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL,
0166              TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0),
0167     SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL,
0168              TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0),
0169 
0170     SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL,
0171                 TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event,
0172                 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0173 };
0174 
0175 static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = {
0176     { "Left PGA", NULL, "LEFTIN" },
0177     { "Right PGA", NULL, "RIGHTIN" },
0178 
0179     { "Left Mute", NULL, "Left PGA" },
0180     { "Right Mute", NULL, "Right PGA" },
0181 
0182     { "HPLEFT", NULL, "Left Mute" },
0183     { "HPRIGHT", NULL, "Right Mute" },
0184 
0185     { "Left PGA", NULL, "Power" },
0186     { "Right PGA", NULL, "Power" },
0187 };
0188 
0189 static const struct snd_soc_component_driver tpa6130a2_component_driver = {
0190     .name = "tpa6130a2",
0191     .probe = tpa6130a2_component_probe,
0192     .dapm_widgets = tpa6130a2_dapm_widgets,
0193     .num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets),
0194     .dapm_routes = tpa6130a2_dapm_routes,
0195     .num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes),
0196 };
0197 
0198 static const struct reg_default tpa6130a2_reg_defaults[] = {
0199     { TPA6130A2_REG_CONTROL, TPA6130A2_SWS },
0200     { TPA6130A2_REG_VOL_MUTE, TPA6130A2_MUTE_R | TPA6130A2_MUTE_L },
0201 };
0202 
0203 static const struct regmap_config tpa6130a2_regmap_config = {
0204     .reg_bits = 8,
0205     .val_bits = 8,
0206     .max_register = TPA6130A2_REG_VERSION,
0207     .reg_defaults = tpa6130a2_reg_defaults,
0208     .num_reg_defaults = ARRAY_SIZE(tpa6130a2_reg_defaults),
0209     .cache_type = REGCACHE_RBTREE,
0210 };
0211 
0212 static const struct i2c_device_id tpa6130a2_id[] = {
0213     { "tpa6130a2", TPA6130A2 },
0214     { "tpa6140a2", TPA6140A2 },
0215     { }
0216 };
0217 MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
0218 
0219 static int tpa6130a2_probe(struct i2c_client *client)
0220 {
0221     struct device *dev;
0222     struct tpa6130a2_data *data;
0223     struct tpa6130a2_platform_data *pdata = client->dev.platform_data;
0224     struct device_node *np = client->dev.of_node;
0225     const struct i2c_device_id *id;
0226     const char *regulator;
0227     unsigned int version;
0228     int ret;
0229 
0230     dev = &client->dev;
0231 
0232     data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
0233     if (!data)
0234         return -ENOMEM;
0235 
0236     data->dev = dev;
0237 
0238     data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config);
0239     if (IS_ERR(data->regmap))
0240         return PTR_ERR(data->regmap);
0241 
0242     if (pdata) {
0243         data->power_gpio = pdata->power_gpio;
0244     } else if (np) {
0245         data->power_gpio = of_get_named_gpio(np, "power-gpio", 0);
0246     } else {
0247         dev_err(dev, "Platform data not set\n");
0248         dump_stack();
0249         return -ENODEV;
0250     }
0251 
0252     i2c_set_clientdata(client, data);
0253 
0254     id = i2c_match_id(tpa6130a2_id, client);
0255     data->id = id->driver_data;
0256 
0257     if (data->power_gpio >= 0) {
0258         ret = devm_gpio_request(dev, data->power_gpio,
0259                     "tpa6130a2 enable");
0260         if (ret < 0) {
0261             dev_err(dev, "Failed to request power GPIO (%d)\n",
0262                 data->power_gpio);
0263             return ret;
0264         }
0265         gpio_direction_output(data->power_gpio, 0);
0266     }
0267 
0268     switch (data->id) {
0269     default:
0270         dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
0271              data->id);
0272         fallthrough;
0273     case TPA6130A2:
0274         regulator = "Vdd";
0275         break;
0276     case TPA6140A2:
0277         regulator = "AVdd";
0278         break;
0279     }
0280 
0281     data->supply = devm_regulator_get(dev, regulator);
0282     if (IS_ERR(data->supply)) {
0283         ret = PTR_ERR(data->supply);
0284         dev_err(dev, "Failed to request supply: %d\n", ret);
0285         return ret;
0286     }
0287 
0288     ret = tpa6130a2_power(data, true);
0289     if (ret != 0)
0290         return ret;
0291 
0292 
0293     /* Read version */
0294     regmap_read(data->regmap, TPA6130A2_REG_VERSION, &version);
0295     version &= TPA6130A2_VERSION_MASK;
0296     if ((version != 1) && (version != 2))
0297         dev_warn(dev, "UNTESTED version detected (%d)\n", version);
0298 
0299     /* Disable the chip */
0300     ret = tpa6130a2_power(data, false);
0301     if (ret != 0)
0302         return ret;
0303 
0304     return devm_snd_soc_register_component(&client->dev,
0305             &tpa6130a2_component_driver, NULL, 0);
0306 }
0307 
0308 #if IS_ENABLED(CONFIG_OF)
0309 static const struct of_device_id tpa6130a2_of_match[] = {
0310     { .compatible = "ti,tpa6130a2", },
0311     { .compatible = "ti,tpa6140a2" },
0312     {},
0313 };
0314 MODULE_DEVICE_TABLE(of, tpa6130a2_of_match);
0315 #endif
0316 
0317 static struct i2c_driver tpa6130a2_i2c_driver = {
0318     .driver = {
0319         .name = "tpa6130a2",
0320         .of_match_table = of_match_ptr(tpa6130a2_of_match),
0321     },
0322     .probe_new = tpa6130a2_probe,
0323     .id_table = tpa6130a2_id,
0324 };
0325 
0326 module_i2c_driver(tpa6130a2_i2c_driver);
0327 
0328 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
0329 MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver");
0330 MODULE_LICENSE("GPL");