diff options
author | Ravindra Lokhande <rlokhande@nvidia.com> | 2013-01-28 23:25:06 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 12:58:52 -0700 |
commit | efd97c0dd3a11994e633e179e64a0a34eb2590b9 (patch) | |
tree | d79a5a0f3bb12e46ff567857f2cc3c2ef4cd309a | |
parent | ebd89da6f27a637443de3f15fcce5ef0a186ba88 (diff) |
ASoC: Add max97236 driver
Add driver for max97236 audio amplifier driver.
Change-Id: I7e62fa1bd6fee7fe57fde83ba649b288e784f145
Signed-off-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-on: http://git-master/r/194757
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Scott Peterson <speterson@nvidia.com>
Reviewed-by: Gaurav Sarode <gsarode@nvidia.com>
-rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/max97236.c | 173 | ||||
-rw-r--r-- | sound/soc/codecs/max97236.h | 300 |
4 files changed, 479 insertions, 0 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4079d66af0f7..2cf24f0647e6 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -51,6 +51,7 @@ config SND_SOC_ALL_CODECS select SND_SOC_MAX9850 if I2C select SND_SOC_MAX9768 if I2C select SND_SOC_MAX9877 if I2C + select SND_SOC_MAX97236 if I2C select SND_SOC_MC13783 if MFD_MC13XXX select SND_SOC_ML26124 if I2C select SND_SOC_OMAP_HDMI_CODEC if OMAP4_DSS_HDMI @@ -531,6 +532,9 @@ config SND_SOC_MAX9768 config SND_SOC_MAX9877 tristate +config SND_SOC_MAX97236 + tristate + config SND_SOC_MC13783 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f4ba144db193..484a10136e00 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -124,6 +124,7 @@ snd-soc-rt5640-objs := rt5640.o # Amp snd-soc-max9877-objs := max9877.o +snd-soc-max97236-objs := max97236.o snd-soc-tpa6130a2-objs := tpa6130a2.o obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o @@ -251,4 +252,5 @@ obj-$(CONFIG_SND_SOC_RT5640) += snd-soc-rt5640.o # Amp obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o +obj-$(CONFIG_SND_SOC_MAX97236) += snd-soc-max97236.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o diff --git a/sound/soc/codecs/max97236.c b/sound/soc/codecs/max97236.c new file mode 100644 index 000000000000..8e1a5ebd002e --- /dev/null +++ b/sound/soc/codecs/max97236.c @@ -0,0 +1,173 @@ +/* + * Max97236 Audio AMP driver + * + * Author: Ravindra Lokhande + * rlokhande@nvidia.com + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/regulator/consumer.h> + +#include <sound/core.h> +#include <sound/soc.h> + +#include "max97236.h" + +struct max97236 { + struct regmap *regmap; +}; + +static struct reg_default max97236_default_regs[] = { + { 0, 0x00 }, + { 1, 0x00 }, + { 2, 0x00 }, + { 4, 0x00 }, + { 5, 0x00 }, + { 7, 0xC0 }, + { 8, 0x40 }, + { 9, 0x00 }, + { 10, 0x00 }, + { 11, 0x90 }, + { 12, 0x00 }, + { 13, 0x00 }, + { 14, 0x00 }, + { 15, 0x00 }, + { 16, 0x00 }, + { 17, 0x00 }, + { 18, 0x00 }, + { 19, 0x00 }, + { 20, 0x00 }, + { 21, 0x00 }, + { 22, 0x00 }, + { 23, 0x00 }, + { 24, 0x00 }, + { 25, 0x20 }, + { 26, 0x05 }, + { 29, 0x00 }, + { 30, 0x00 }, +}; + +static int max97236_probe(struct snd_soc_codec *codec) +{ + struct max97236 *max97236 = snd_soc_codec_get_drvdata(codec); + int ret; + + codec->control_data = max97236->regmap; + ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); + if (ret) + return ret; + + snd_soc_write(codec, M97236_REG_1D_ENABLE1, M97236_EN1_SHDN); + snd_soc_write(codec, M97236_REG_1E_ENABLE2, M97236_EN2_LFTEN | + M97236_EN2_RGHEN | M97236_EN2_FAST | 0x10); + snd_soc_write(codec, M97236_REG_07_LEFT_VOLUME, ((M97236_LVOL_L_EQ_R | + 0x39) & (~M97236_LVOL_MUTEL))); + + return 0; +} + +static const struct regmap_config max97236_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 31, + .reg_defaults = max97236_default_regs, + .num_reg_defaults = ARRAY_SIZE(max97236_default_regs), + .cache_type = REGCACHE_RBTREE, +}; + +static struct snd_soc_codec_driver soc_codec_dev_max97236 = { + .probe = max97236_probe, +}; + +static int __devinit max97236_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct max97236 *max97236; + int err; + + max97236 = devm_kzalloc(&i2c->dev, sizeof(*max97236), GFP_KERNEL); + if (!max97236) + return -ENOMEM; + + i2c_set_clientdata(i2c, max97236); + + max97236->regmap = regmap_init_i2c(i2c, &max97236_i2c_regmap_config); + if (IS_ERR(max97236->regmap)) { + err = PTR_ERR(max97236->regmap); + dev_err(&i2c->dev, "regmap_init() failed: %d\n", err); + return err; + } + + err = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max97236, + NULL, 0); + if (err) + goto err_regmap_free; + + return 0; + + err_regmap_free: + regmap_exit(max97236->regmap); + + return err; +} + +static int __devexit max97236_i2c_remove(struct i2c_client *i2c) +{ + struct max97236 *max97236 = i2c_get_clientdata(i2c); + + snd_soc_unregister_codec(&i2c->dev); + regmap_exit(max97236->regmap); + + return 0; +} + +static const struct i2c_device_id max97236_i2c_id[] = { + { "max97236", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max97236_i2c_id); + +static struct i2c_driver max97236_i2c_driver = { + .driver = { + .name = "max97236", + .owner = THIS_MODULE, + }, + .probe = max97236_i2c_probe, + .remove = __devexit_p(max97236_i2c_remove), + .id_table = max97236_i2c_id, +}; + +static int __init max97236_init(void) +{ + return i2c_add_driver(&max97236_i2c_driver); +} +module_init(max97236_init); + +static void __exit max97236_exit(void) +{ + i2c_del_driver(&max97236_i2c_driver); +} +module_exit(max97236_exit); + +MODULE_AUTHOR("Ravindra Lokhande <rlokhande@nvidia.com>"); +MODULE_DESCRIPTION("max97236 amplifier driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/max97236.h b/sound/soc/codecs/max97236.h new file mode 100644 index 000000000000..4168a303c0b8 --- /dev/null +++ b/sound/soc/codecs/max97236.h @@ -0,0 +1,300 @@ +/* + * max97236.h - Header file for max97236 headphone amplifier + * + * Author: Ravindra Lokhande <rlokhande@nvidia.com> + * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef _MAX97236_H +#define _MAX97236_H + +#include <linux/version.h> + +/* + * MAX97236 Register Definitions + */ + +#define M97236_REG_00_STATUS1 0x00 +#define M97236_REG_01_STATUS2 0x01 +#define M97236_REG_02_STATUS3 0x02 +#define M97236_REG_03_FOR_EXPANSION 0x03 +#define M97236_REG_04_IRQ_MASK1 0x04 +#define M97236_REG_05_IRQ_MASK2 0x05 +#define M97236_REG_06_FOR_EXPANSION 0x06 +#define M97236_REG_07_LEFT_VOLUME 0x07 +#define M97236_REG_08_RIGHT_VOLUME 0x08 +#define M97236_REG_09_MICROPHONE 0x09 +#define M97236_REG_0A_FOR_EXPANSION 0x0A +#define M97236_REG_0B_VENDOR_ID_REGSITER 0x0B +#define M97236_REG_0C_FOR_EXPANSION 0x0C +#define M97236_REG_0D_FOR_EXPANSION 0x0D +#define M97236_REG_0E_FOR_EXPANSION 0x0E +#define M97236_REG_0F_FOR_EXPANSION 0x0F +#define M97236_REG_10_FOR_EXPANSION 0x10 +#define M97236_REG_11_FOR_EXPANSION 0x11 +#define M97236_REG_12_KEYSCAN_CLOCK_DIVIDER1 0x12 +#define M97236_REG_13_KEYSCAN_CLOCK_DIVIDER2 0x13 +#define M97236_REG_14_KEYSCAN_CLOCK_DIVIDER_ADC 0x14 +#define M97236_REG_15_KEYSCAN_DEBOUNCE 0x15 +#define M97236_REG_16_KEYSCAN_DELAY 0x16 +#define M97236_REG_17_PASSIVE_MBH_KEYSCAN_DATA 0x17 +#define M97236_REG_18_DC_TEST_SLEW_CONTROL 0x18 +#define M97236_REG_19_STATE_FORCING 0x19 +#define M97236_REG_1A_AC_TEST_CONTROL 0x1A +#define M97236_REG_1B_FOR_EXPANSION 0x1B +#define M97236_REG_1C_FOR_EXPANSION 0x1C +#define M97236_REG_1D_ENABLE1 0x1D +#define M97236_REG_1E_ENABLE2 0x1E + +/* + * M97236_REG_00_STATUS1 + */ +#define M97236_ST1_JKIN_MASK (1<<7) +#define M97236_ST1_JKIN_SHIFT 7 +#define M97236_ST1_JKIN_WIDTH 1 +#define M97236_ST1_DDONE_MASK (1<<6) +#define M97236_ST1_DDONE_SHIFT 6 +#define M97236_ST1_DDONE_WIDTH 1 +#define M97236_ST1_VOL_MASK (1<<5) +#define M97236_ST1_VOL_SHIFT 5 +#define M97236_ST1_VOL_WIDTH 1 +#define M97236_ST1_MIC_IN_MASK (1<<3) +#define M97236_ST1_MIC_IN_SHIFT 3 +#define M97236_ST1_MIC_IN_WIDTH 1 +#define M97236_ST1_JACKSW_MASK (1<<2) +#define M97236_ST1_JACKSW_SHIFT 2 +#define M97236_ST1_JACKSW_WIDTH 1 +#define M97236_ST1_MCSW_MASK (1<<1) +#define M97236_ST1_MCSW_SHIFT 1 +#define M97236_ST1_MCSW_WIDTH 1 +#define M97236_ST1_MBH_MASK (1<<0) +#define M97236_ST1_MBH_SHIFT 0 +#define M97236_ST1_MBH_WIDTH 1 + +/* + * M97236_REG_01_STATUS2 + */ +#define M97236_ST2_LINE_L_MASK (1<<7) +#define M97236_ST2_LINE_L_SHIFT 7 +#define M97236_ST2_LINE_L_WIDTH 1 +#define M97236_ST2_LINE_R_MASK (1<<6) +#define M97236_ST2_LINE_R_SHIFT 6 +#define M97236_ST2_LINE_R_WIDTH 1 +#define M97236_ST2_HP_L_MASK (1<<5) +#define M97236_ST2_HP_L_SHIFT 5 +#define M97236_ST2_HP_L_WIDTH 1 +#define M97236_ST2_HP_R_MASK (1<<4) +#define M97236_ST2_HP_R_SHIFT 4 +#define M97236_ST2_HP_R_WIDTH 1 +#define M97236_ST2_JACKSWINC_MASK (1<<3) +#define M97236_ST2_JACKSWINC_SHIFT 3 +#define M97236_ST2_JACKSWINC_WIDTH 1 +#define M97236_ST2_KEY_MASK (1<<2) +#define M97236_ST2_KEY_SHIFT 2 +#define M97236_ST2_KEY_WIDTH 1 + +/* + * M97236_REG_02_STATUS3 + */ +#define M97236_ST3_GND_MASK (0x3<<0) +#define M97236_ST3_GND_SHIFT 0 +#define M97236_ST3_GND_WIDTH 2 + +/* + * M97236_REG_04_IRQ_MASK1 + */ +#define M97236_IRQ_1_IJKIN_MASK (1<<7) +#define M97236_IRQ_1_IJKIN_SHIFT 7 +#define M97236_IRQ_1_IJKIN_WIDTH 1 +#define M97236_IRQ_1_IDDONE_MASK (1<<6) +#define M97236_IRQ_1_IDDONE_SHIFT 6 +#define M97236_IRQ_1_IDDONE_WIDTH 1 +#define M97236_IRQ_1_IVOL_MASK (1<<5) +#define M97236_IRQ_1_IVOL_SHIFT 5 +#define M97236_IRQ_1_IVOL_WIDTH 1 +#define M97236_IRQ_1_IMIC_MASK (1<<3) +#define M97236_IRQ_1_IMIC_SHIFT 3 +#define M97236_IRQ_1_IMIC_WIDTH 1 +#define M97236_IRQ_1_JACKSW_MASK (1<<2) +#define M97236_IRQ_1_JACKSW_SHIFT 2 +#define M97236_IRQ_1_JACKSW_WIDTH 1 +#define M97236_IRQ_1_IMCSW_MASK (1<<1) +#define M97236_IRQ_1_IMCSW_SHIFT 1 +#define M97236_IRQ_1_IMCSW_WIDTH 1 +#define M97236_IRQ_1_IMBH_MASK (1<<0) +#define M97236_IRQ_1_IMBH_SHIFT 0 +#define M97236_IRQ_1_IMBH_WIDTH 1 + +/* + * M97236_REG_05_IRQ_MASK2 + */ +#define M97236_IRQ_2_ILINE_L_MASK (1<<7) +#define M97236_IRQ_2_ILINE_L_SHIFT 7 +#define M97236_IRQ_2_ILINE_L_WIDTH 1 +#define M97236_IRQ_2_ILINE_R_MASK (1<<6) +#define M97236_IRQ_2_ILINE_R_SHIFT 6 +#define M97236_IRQ_2_ILINE_R_WIDTH 1 +#define M97236_IRQ_2_IHP_L_MASK (1<<5) +#define M97236_IRQ_2_IHP_L_SHIFT 5 +#define M97236_IRQ_2_IHP_L_WIDTH 1 +#define M97236_IRQ_2_IHP_R_MASK (1<<4) +#define M97236_IRQ_2_IHP_R_SHIFT 4 +#define M97236_IRQ_2_IHP_R_WIDTH 1 +#define M97236_IRQ_2_IJACKSW_MASK (1<<3) +#define M97236_IRQ_2_IJACKSW_SHIFT 3 +#define M97236_IRQ_2_IJACKSW_WIDTH 1 +#define M97236_IRQ_2_IKEY_MASK (1<<2) +#define M97236_IRQ_2_IKEY_SHIFT 2 +#define M97236_IRQ_2_IKEY_WIDTH 1 + +/* + * M97236_REG_07_LEFT_VOLUME + */ +#define M97236_LVOL_L_EQ_R 0x80 +#define M97236_LVOL_L_EQ_R_MASK (1<<7) +#define M97236_LVOL_L_EQ_R_SHIFT 7 +#define M97236_LVOL_L_EQ_R_WIDTH 1 + +#define M97236_LVOL_MUTEL 0x40 +#define M97236_LVOL_MUTEL_MASK (1<<6) +#define M97236_LVOL_MUTEL_SHIFT 6 +#define M97236_LVOL_MUTEL_WIDTH 1 +#define M97236_LVOL_LVOL_MASK (0x3F<<0) +#define M97236_LVOL_LVOL_SHIFT 0 +#define M97236_LVOL_LVOL_WIDTH 6 + +/* + * M97236_REG_08_RIGHT_VOLUME + */ +#define M97236_RVOL_MUTEL_MASK (1<<6) +#define M97236_RVOL_MUTEL_SHIFT 6 +#define M97236_RVOL_MUTEL_WIDTH 1 +#define M97236_RVOL_RVOL_MASK (0x3F<<0) +#define M97236_RVOL_RVOL_SHIFT 0 +#define M97236_RVOL_RVOL_WIDTH 6 + +/* + * M97236_REG_09_MICROPHONE + */ +#define M97236_MIC_GAIN_MASK (1<<6) +#define M97236_MIC_GAIN_SHIFT 6 +#define M97236_MIC_GAIN_WIDTH 1 +#define M97236_MIC_MICR_MASK (0x7<<3) +#define M97236_MIC_MICR_SHIFT 3 +#define M97236_MIC_MICR_WIDTH 3 +#define M97236_MIC_BIAS_MASK (1<<2) +#define M97236_MIC_BIAS_SHIFT 2 +#define M97236_MIC_BIAS_WIDTH 1 + +/* + * M97236_REG_0B_VENDOR_ID_REGSITER + */ +#define M97236_VID_ID_MASK (0xF<<4) +#define M97236_VID_ID_SHIFT 4 +#define M97236_VID_ID_WIDTH 4 + +/* + * M97236_REG_19_STATE_FORCING + */ +#define M97236_ST_FORCEFORCE_MASK (1<<5) +#define M97236_ST_FORCEFORCE_SHIFT 5 +#define M97236_ST_FORCEFORCE_WIDTH 1 +#define M97236_ST_FORCESTATE_MASK (0xF<<1) +#define M97236_ST_FORCESTATE_SHIFT 1 +#define M97236_ST_FORCESTATE_WIDTH 4 + +/* + * M97236_REG_1A_AC_TEST_CONTROL + */ +#define M97236_AC_TC_AC_REPEAT_MASK (0x3<<4) +#define M97236_AC_TC_AC_REPEAT_SHIFT 4 +#define M97236_AC_TC_AC_REPEAT_WIDTH 2 +#define M97236_AC_TC_PULSE_WIDTH_MASK (0x3<<2) +#define M97236_AC_TC_PULSE_WIDTH_SHIFT 2 +#define M97236_AC_TC_PULSE_WIDTH_WIDTH 2 +#define M97236_AC_TC_PULSE_AMP_MASK (0x3<<0) +#define M97236_AC_TC_PULSE_AMP_SHIFT 0 +#define M97236_AC_TC_PULSE_AMP_WIDTH 2 + +/* + * M97236_REG_1D_ENABLE1 + */ +#define M97236_EN1_SHDN 0x80 +#define M97236_EN1_SHDN_MASK (1<<7) +#define M97236_EN1_SHDN_SHIFT 7 +#define M97236_EN1_SHDN_WIDTH 1 + +#define M97236_EN1_RESET 0x40 +#define M97236_EN1_RESET_MASK (1<<6) +#define M97236_EN1_RESET_SHIFT 6 +#define M97236_EN1_RESET_WIDTH 1 + +#define M97236_EN1_MIC_BIAS 0x10 +#define M97236_EN1_MIC_BIAS_MASK (1<<4) +#define M97236_EN1_MIC_BIAS_SHIFT 4 +#define M97236_EN1_MIC_BIAS_WIDTH 1 + +#define M97236_EN1_MIC_AMP 0x8 +#define M97236_EN1_MIC_AMP_MASK (1<<3) +#define M97236_EN1_MIC_AMP_SHIFT 3 +#define M97236_EN1_MIC_AMP_WIDTH 1 + +#define M97236_EN1_KS 0x4 +#define M97236_EN1_KS_MASK (1<<2) +#define M97236_EN1_KS_SHIFT 2 +#define M97236_EN1_KS_WIDTH 1 + +/* + * M97236_REG_1E_ENABLE2 + */ +#define M97236_EN2_LFTEN 0x80 +#define M97236_EN2_LFTEN_MASK (1<<7) +#define M97236_EN2_LFTEN_SHIFT 7 +#define M97236_EN2_LFTEN_WIDTH 1 + +#define M97236_EN2_RGHEN 0x40 +#define M97236_EN2_RGHEN_MASK (1<<6) +#define M97236_EN2_RGHEN_SHIFT 6 +#define M97236_EN2_RGHEN_WIDTH 1 + +#define M97236_EN2_VSEN 0x20 +#define M97236_EN2_VSEN_MASK (1<<5) +#define M97236_EN2_VSEN_SHIFT 5 +#define M97236_EN2_VSEN_WIDTH 1 + +#define M97236_EN2_ZDEN 0x10 +#define M97236_EN2_ZDEN_MASK (1<<4) +#define M97236_EN2_ZDEN_SHIFT 4 +#define M97236_EN2_ZDEN_WIDTH 1 + +#define M97236_EN2_FAST 0x8 +#define M97236_EN2_FAST_MASK (1<<3) +#define M97236_EN2_FAST_SHIFT 3 +#define M97236_EN2_FAST_WIDTH 1 + +#define M97236_EN2_THRH 0x4 +#define M97236_EN2_THRH_MASK (1<<2) +#define M97236_EN2_THRH_SHIFT 2 +#define M97236_EN2_THRH_WIDTH 1 + +#define M97236_EN2_AUTO +#define M97236_EN2_AUTO_MASK (0x3<<0) +#define M97236_EN2_AUTO_SHIFT 0 +#define M97236_EN2_AUTO_WIDTH 2 + +#endif |