Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: tlv320aic23: add support for SPI control mode

tlv320aic23 chip control interface may work in either I2C or SPI mode
depending on the MODE pin state. Functionality and register layout are
independent of the control mode.

Implement bus-specific parts as separate modules.

Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Signed-off-by: Mark Brown <broonie@linaro.org>

authored by

Max Filippov and committed by
Mark Brown
b3fc5725 806057cc

+147 -45
+10 -1
sound/soc/codecs/Kconfig
··· 71 71 select SND_SOC_STA529 if I2C 72 72 select SND_SOC_STAC9766 if SND_SOC_AC97_BUS 73 73 select SND_SOC_TAS5086 if I2C 74 - select SND_SOC_TLV320AIC23 if I2C 74 + select SND_SOC_TLV320AIC23_I2C if I2C 75 + select SND_SOC_TLV320AIC23_SPI if SPI_MASTER 75 76 select SND_SOC_TLV320AIC26 if SPI_MASTER 76 77 select SND_SOC_TLV320AIC32X4 if I2C 77 78 select SND_SOC_TLV320AIC3X if I2C ··· 357 356 358 357 config SND_SOC_TLV320AIC23 359 358 tristate 359 + 360 + config SND_SOC_TLV320AIC23_I2C 361 + tristate 362 + select SND_SOC_TLV320AIC23 363 + 364 + config SND_SOC_TLV320AIC23_SPI 365 + tristate 366 + select SND_SOC_TLV320AIC23 360 367 361 368 config SND_SOC_TLV320AIC26 362 369 tristate
+4
sound/soc/codecs/Makefile
··· 63 63 snd-soc-stac9766-objs := stac9766.o 64 64 snd-soc-tas5086-objs := tas5086.o 65 65 snd-soc-tlv320aic23-objs := tlv320aic23.o 66 + snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o 67 + snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o 66 68 snd-soc-tlv320aic26-objs := tlv320aic26.o 67 69 snd-soc-tlv320aic3x-objs := tlv320aic3x.o 68 70 snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o ··· 195 193 obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o 196 194 obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o 197 195 obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 196 + obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o 197 + obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o 198 198 obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 199 199 obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 200 200 obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
+59
sound/soc/codecs/tlv320aic23-i2c.c
··· 1 + /* 2 + * ALSA SoC TLV320AIC23 codec driver I2C interface 3 + * 4 + * Author: Arun KS, <arunks@mistralsolutions.com> 5 + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., 6 + * 7 + * Based on sound/soc/codecs/wm8731.c by Richard Purdie 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/i2c.h> 15 + #include <linux/module.h> 16 + #include <linux/regmap.h> 17 + #include <sound/soc.h> 18 + 19 + #include "tlv320aic23.h" 20 + 21 + static int tlv320aic23_i2c_probe(struct i2c_client *i2c, 22 + const struct i2c_device_id *i2c_id) 23 + { 24 + struct regmap *regmap; 25 + 26 + if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 27 + return -EINVAL; 28 + 29 + regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); 30 + return tlv320aic23_probe(&i2c->dev, regmap); 31 + } 32 + 33 + static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) 34 + { 35 + snd_soc_unregister_codec(&i2c->dev); 36 + return 0; 37 + } 38 + 39 + static const struct i2c_device_id tlv320aic23_id[] = { 40 + {"tlv320aic23", 0}, 41 + {} 42 + }; 43 + 44 + MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); 45 + 46 + static struct i2c_driver tlv320aic23_i2c_driver = { 47 + .driver = { 48 + .name = "tlv320aic23-codec", 49 + }, 50 + .probe = tlv320aic23_i2c_probe, 51 + .remove = __exit_p(tlv320aic23_i2c_remove), 52 + .id_table = tlv320aic23_id, 53 + }; 54 + 55 + module_i2c_driver(tlv320aic23_i2c_driver); 56 + 57 + MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver I2C"); 58 + MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); 59 + MODULE_LICENSE("GPL");
+57
sound/soc/codecs/tlv320aic23-spi.c
··· 1 + /* 2 + * ALSA SoC TLV320AIC23 codec driver SPI interface 3 + * 4 + * Author: Arun KS, <arunks@mistralsolutions.com> 5 + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., 6 + * 7 + * Based on sound/soc/codecs/wm8731.c by Richard Purdie 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/regmap.h> 16 + #include <linux/spi/spi.h> 17 + #include <sound/soc.h> 18 + 19 + #include "tlv320aic23.h" 20 + 21 + static int aic23_spi_probe(struct spi_device *spi) 22 + { 23 + int ret; 24 + struct regmap *regmap; 25 + 26 + dev_dbg(&spi->dev, "probing tlv320aic23 spi device\n"); 27 + 28 + spi->bits_per_word = 16; 29 + spi->mode = SPI_MODE_0; 30 + ret = spi_setup(spi); 31 + if (ret < 0) 32 + return ret; 33 + 34 + regmap = devm_regmap_init_spi(spi, &tlv320aic23_regmap); 35 + return tlv320aic23_probe(&spi->dev, regmap); 36 + } 37 + 38 + static int aic23_spi_remove(struct spi_device *spi) 39 + { 40 + snd_soc_unregister_codec(&spi->dev); 41 + return 0; 42 + } 43 + 44 + static struct spi_driver aic23_spi = { 45 + .driver = { 46 + .name = "tlv320aic23", 47 + .owner = THIS_MODULE, 48 + }, 49 + .probe = aic23_spi_probe, 50 + .remove = aic23_spi_remove, 51 + }; 52 + 53 + module_spi_driver(aic23_spi); 54 + 55 + MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver SPI"); 56 + MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); 57 + MODULE_LICENSE("GPL");
+11 -44
sound/soc/codecs/tlv320aic23.c
··· 23 23 #include <linux/init.h> 24 24 #include <linux/delay.h> 25 25 #include <linux/pm.h> 26 - #include <linux/i2c.h> 27 26 #include <linux/regmap.h> 28 27 #include <linux/slab.h> 29 28 #include <sound/core.h> ··· 50 51 { 9, 0x0000 }, 51 52 }; 52 53 53 - static const struct regmap_config tlv320aic23_regmap = { 54 + const struct regmap_config tlv320aic23_regmap = { 54 55 .reg_bits = 7, 55 56 .val_bits = 9, 56 57 ··· 556 557 return 0; 557 558 } 558 559 559 - static int tlv320aic23_probe(struct snd_soc_codec *codec) 560 + static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) 560 561 { 561 562 int ret; 562 563 ··· 603 604 } 604 605 605 606 static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { 606 - .probe = tlv320aic23_probe, 607 + .probe = tlv320aic23_codec_probe, 607 608 .remove = tlv320aic23_remove, 608 609 .suspend = tlv320aic23_suspend, 609 610 .resume = tlv320aic23_resume, ··· 616 617 .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), 617 618 }; 618 619 619 - /* 620 - * If the i2c layer weren't so broken, we could pass this kind of data 621 - * around 622 - */ 623 - static int tlv320aic23_codec_probe(struct i2c_client *i2c, 624 - const struct i2c_device_id *i2c_id) 620 + int tlv320aic23_probe(struct device *dev, struct regmap *regmap) 625 621 { 626 622 struct aic23 *aic23; 627 - int ret; 628 623 629 - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 630 - return -EINVAL; 624 + if (IS_ERR(regmap)) 625 + return PTR_ERR(regmap); 631 626 632 - aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL); 627 + aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); 633 628 if (aic23 == NULL) 634 629 return -ENOMEM; 635 630 636 - aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); 637 - if (IS_ERR(aic23->regmap)) 638 - return PTR_ERR(aic23->regmap); 631 + aic23->regmap = regmap; 639 632 640 - i2c_set_clientdata(i2c, aic23); 633 + dev_set_drvdata(dev, aic23); 641 634 642 - ret = snd_soc_register_codec(&i2c->dev, 643 - &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); 644 - return ret; 635 + return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, 636 + &tlv320aic23_dai, 1); 645 637 } 646 - static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) 647 - { 648 - snd_soc_unregister_codec(&i2c->dev); 649 - return 0; 650 - } 651 - 652 - static const struct i2c_device_id tlv320aic23_id[] = { 653 - {"tlv320aic23", 0}, 654 - {} 655 - }; 656 - 657 - MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); 658 - 659 - static struct i2c_driver tlv320aic23_i2c_driver = { 660 - .driver = { 661 - .name = "tlv320aic23-codec", 662 - }, 663 - .probe = tlv320aic23_codec_probe, 664 - .remove = __exit_p(tlv320aic23_i2c_remove), 665 - .id_table = tlv320aic23_id, 666 - }; 667 - 668 - module_i2c_driver(tlv320aic23_i2c_driver); 669 638 670 639 MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); 671 640 MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
+6
sound/soc/codecs/tlv320aic23.h
··· 12 12 #ifndef _TLV320AIC23_H 13 13 #define _TLV320AIC23_H 14 14 15 + struct device; 16 + struct regmap_config; 17 + 18 + extern const struct regmap_config tlv320aic23_regmap; 19 + int tlv320aic23_probe(struct device *dev, struct regmap *regmap); 20 + 15 21 /* Codec TLV320AIC23 */ 16 22 #define TLV320AIC23_LINVOL 0x00 17 23 #define TLV320AIC23_RINVOL 0x01