From 93028b36f893720e7e28a5cc73dc8bfc9bdad7da Mon Sep 17 00:00:00 2001 From: Nikesh Oswal Date: Fri, 3 Feb 2012 20:17:20 +0530 Subject: sound: soc: codecs: update the TI codec driver for K39 Change-Id: If40c181227981696961d3c563008261e5324e807 Signed-off-by: Nikesh Oswal Reviewed-on: http://git-master/r/84528 Reviewed-by: Scott Peterson --- sound/soc/codecs/Makefile | 2 +- sound/soc/codecs/aic326x_tiload.c | 312 ++++ sound/soc/codecs/aic326x_tiload.h | 36 + sound/soc/codecs/tlv320aic326x.c | 1775 +++++++++++++++-------- sound/soc/codecs/tlv320aic326x.h | 35 +- sound/soc/codecs/tlv320aic326x_mini-dsp.c | 17 +- sound/soc/codecs/tlv320aic326x_mini-dsp.h | 4 +- sound/soc/codecs/tlv320aic326x_minidsp_config.c | 13 +- 8 files changed, 1539 insertions(+), 655 deletions(-) create mode 100644 sound/soc/codecs/aic326x_tiload.c create mode 100644 sound/soc/codecs/aic326x_tiload.h (limited to 'sound/soc/codecs') diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index b29e2ab6dd7b..2eaef5b52e08 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -36,7 +36,7 @@ snd-soc-tlv320aic23-objs := tlv320aic23.o snd-soc-tlv320aic26-objs := tlv320aic26.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic326x-objs := tlv320aic326x.o tlv320aic326x_minidsp_config.o -snd-soc-tlv320aic326x-objs += tlv320aic326x_mini-dsp.o +snd-soc-tlv320aic326x-objs += tlv320aic326x_mini-dsp.o aic326x_tiload.o snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-twl4030-objs := twl4030.o diff --git a/sound/soc/codecs/aic326x_tiload.c b/sound/soc/codecs/aic326x_tiload.c new file mode 100644 index 000000000000..00aa4d4ce7d7 --- /dev/null +++ b/sound/soc/codecs/aic326x_tiload.c @@ -0,0 +1,312 @@ +/* + * linux/sound/soc/codecs/AIC3262_tiload.c + * + * + * Copyright (C) 2010 Texas Instruments, Inc. + * + * + * + * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * History: + * + * Rev 0.1 Tiload support 16-09-2010 + * + * The Tiload programming support is added to AIC3262. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tlv320aic326x.h" +#include "aic326x_tiload.h" + +/* enable debug prints in the driver */ +#define DEBUG +//#undef DEBUG + +#ifdef DEBUG +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) +#endif + +#ifdef AIC3262_TiLoad + +/* Function prototypes */ +#ifdef REG_DUMP_aic3262 +static void aic3262_dump_page(struct i2c_client *i2c, u8 page); +#endif + +/* externs */ +extern int aic3262_change_page(struct snd_soc_codec *codec, u8 new_page); +extern int aic3262_change_book(struct snd_soc_codec *codec, u8 new_book); +extern int aic3262_write(struct snd_soc_codec *codec, u16 reg, u8 value); +int aic3262_driver_init(struct snd_soc_codec *codec); +/************** Dynamic aic3262 driver, TI LOAD support ***************/ + +static struct cdev *aic3262_cdev; +static int aic3262_major = 0; /* Dynamic allocation of Mjr No. */ +static int aic3262_opened = 0; /* Dynamic allocation of Mjr No. */ +static struct snd_soc_codec *aic3262_codec; +struct class *tiload_class; +static unsigned int magic_num = 0xE0; + +/******************************** Debug section *****************************/ + +#ifdef REG_DUMP_aic3262 +/* + *---------------------------------------------------------------------------- + * Function : aic3262_dump_page + * Purpose : Read and display one codec register page, for debugging purpose + *---------------------------------------------------------------------------- + */ +static void aic3262_dump_page(struct i2c_client *i2c, u8 page) +{ + int i; + u8 data; + u8 test_page_array[8]; + + dprintk("TiLoad DRIVER : %s\n", __FUNCTION__); + aic3262_change_page(codec, page); + + data = 0x0; + + i2c_master_send(i2c, data, 1); + i2c_master_recv(i2c, test_page_array, 8); + + printk("\n------- aic3262 PAGE %d DUMP --------\n", page); + for (i = 0; i < 8; i++) { + printk(" [ %d ] = 0x%x\n", i, test_page_array[i]); + } +} +#endif + +/* + *---------------------------------------------------------------------------- + * Function : tiload_open + * + * Purpose : open method for aic3262-tiload programming interface + *---------------------------------------------------------------------------- + */ +static int tiload_open(struct inode *in, struct file *filp) +{ + dprintk("TiLoad DRIVER : %s\n", __FUNCTION__); + if (aic3262_opened) { + printk("%s device is already opened\n", "aic3262"); + printk("%s: only one instance of driver is allowed\n", + "aic3262"); + return -1; + } + aic3262_opened++; + return 0; +} + +/* + *---------------------------------------------------------------------------- + * Function : tiload_release + * + * Purpose : close method for aic3262_tilaod programming interface + *---------------------------------------------------------------------------- + */ +static int tiload_release(struct inode *in, struct file *filp) +{ + dprintk("TiLoad DRIVER : %s\n", __FUNCTION__); + aic3262_opened--; + return 0; +} + +/* + *---------------------------------------------------------------------------- + * Function : tiload_read + * + * Purpose : read method for mini dsp programming interface + *---------------------------------------------------------------------------- + */ +static ssize_t tiload_read(struct file *file, char __user * buf, + size_t count, loff_t * offset) +{ + static char rd_data[8]; + char reg_addr; + size_t size; + #ifdef DEBUG + int i; + #endif + struct i2c_client *i2c = aic3262_codec->control_data; + + dprintk("TiLoad DRIVER : %s\n", __FUNCTION__); + if (count > 128) { + printk("Max 128 bytes can be read\n"); + count = 128; + } + + /* copy register address from user space */ + size = copy_from_user(®_addr, buf, 1); + if (size != 0) { + printk("read: copy_from_user failure\n"); + return -1; + } + /* Send the address to device thats is to be read */ + + if (i2c_master_send(i2c, ®_addr, 1) != 1) { + dprintk("Can not write register address\n"); + return -1; + } + /* read the codec device registers */ + size = i2c_master_recv(i2c, rd_data, count); +#ifdef DEBUG + printk(KERN_ERR "read size = %d, reg_addr= %x , count = %d\n", + (int)size, reg_addr, (int)count); + for (i = 0; i < (int)size; i++) { + printk(KERN_ERR "rd_data[%d]=%x\n", i, rd_data[i]); + } +#endif + if (size != count) { + printk("read %d registers from the codec\n", size); + } + + if (copy_to_user(buf, rd_data, size) != 0) { + dprintk("copy_to_user failed\n"); + return -1; + } + + return size; +} + +/* + *---------------------------------------------------------------------------- + * Function : tiload_write + * + * Purpose : write method for aic3262_tiload programming interface + *---------------------------------------------------------------------------- + */ +static ssize_t tiload_write(struct file *file, const char __user * buf, + size_t count, loff_t * offset) +{ + static char wr_data[8]; + u8 pg_no; + #ifdef DEBUG + int i; + #endif + struct i2c_client *i2c = aic3262_codec->control_data; + struct aic3262_priv *aic3262_private = snd_soc_codec_get_drvdata(aic3262_codec); + + dprintk("TiLoad DRIVER : %s\n", __FUNCTION__); + /* copy buffer from user space */ + if (copy_from_user(wr_data, buf, count)) { + printk("copy_from_user failure\n"); + return -1; + } +#ifdef DEBUG + printk(KERN_ERR "write size = %d\n", (int)count); + for (i = 0; i < (int)count; i++) { + printk(KERN_INFO "\nwr_data[%d]=%x\n", i, wr_data[i]); + } +#endif + if (wr_data[0] == 0) { + aic3262_change_page(aic3262_codec, wr_data[1]); + return count; + } + pg_no = aic3262_private->page_no; + + if ((wr_data[0] == 127) && (pg_no == 0)) { + aic3262_change_book(aic3262_codec, wr_data[1]); + return count; + } + return i2c_master_send(i2c, wr_data, count); +} + +static int tiload_ioctl( struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int num = 0; + void __user *argp = (void __user *)arg; + if (_IOC_TYPE(cmd) != aic3262_IOC_MAGIC) + return -ENOTTY; + + dprintk("TiLoad DRIVER : %s\n", __FUNCTION__); + switch (cmd) { + case aic3262_IOMAGICNUM_GET: + num = copy_to_user(argp, &magic_num, sizeof(int)); + break; + case aic3262_IOMAGICNUM_SET: + num = copy_from_user(&magic_num, argp, sizeof(int)); + break; + } + return num; +} + +/*********** File operations structure for aic3262-tiload programming *************/ +static struct file_operations aic3262_fops = { + .owner = THIS_MODULE, + .open = tiload_open, + .release = tiload_release, + .read = tiload_read, + .write = tiload_write, + .unlocked_ioctl = tiload_ioctl, +}; + +/* + *---------------------------------------------------------------------------- + * Function : aic3262_driver_init + * + * Purpose : Register a char driver for dynamic aic3262-tiload programming + *---------------------------------------------------------------------------- + */ +int aic3262_driver_init(struct snd_soc_codec *codec) +{ + int result; + + dev_t dev = MKDEV(aic3262_major, 0); + printk("TiLoad DRIVER : %s\n", __FUNCTION__); + aic3262_codec = codec; + + printk("allocating dynamic major number\n"); + + result = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME); + if (result < 0) { + printk("cannot allocate major number %d\n", aic3262_major); + return result; + } + tiload_class = class_create(THIS_MODULE, DEVICE_NAME); + aic3262_major = MAJOR(dev); + printk("allocated Major Number: %d\n", aic3262_major); + + aic3262_cdev = cdev_alloc(); + cdev_init(aic3262_cdev, &aic3262_fops); + aic3262_cdev->owner = THIS_MODULE; + aic3262_cdev->ops = &aic3262_fops; + + if (cdev_add(aic3262_cdev, dev, 1) < 0) { + dprintk("aic3262_driver: cdev_add failed \n"); + unregister_chrdev_region(dev, 1); + aic3262_cdev = NULL; + return 1; + } + printk("Registered aic3262 TiLoad driver, Major number: %d \n", + aic3262_major); + //class_device_create(tiload_class, NULL, dev, NULL, DEVICE_NAME, 0); + return 0; +} + +#endif diff --git a/sound/soc/codecs/aic326x_tiload.h b/sound/soc/codecs/aic326x_tiload.h new file mode 100644 index 000000000000..6621a4127b16 --- /dev/null +++ b/sound/soc/codecs/aic326x_tiload.h @@ -0,0 +1,36 @@ +/* + * linux/sound/soc/codecs/aic3262_tiload.h + * + * + * Copyright (C) 2012 Texas Instruments, Inc. + * + * + * + * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * History: + * + * + * + * + */ + +#ifndef _AIC3262_TILOAD_H +#define _AIC3262_TILOAD_H + +/* typedefs required for the included header files */ +typedef char *string; + +/* defines */ +#define DEVICE_NAME "tiload_node" +#define aic3262_IOC_MAGIC 0xE0 +#define aic3262_IOMAGICNUM_GET _IOR(aic3262_IOC_MAGIC, 1, int) +#define aic3262_IOMAGICNUM_SET _IOW(aic3262_IOC_MAGIC, 2, int) + +#endif diff --git a/sound/soc/codecs/tlv320aic326x.c b/sound/soc/codecs/tlv320aic326x.c index 9f1874328b28..0d51b837463a 100644 --- a/sound/soc/codecs/tlv320aic326x.c +++ b/sound/soc/codecs/tlv320aic326x.c @@ -1,7 +1,7 @@ /* * linux/sound/soc/codecs/tlv320aic3262.c * -* Copyright (C) 2011 Mistral Solutions Pvt Ltd. +* Copyright (C) 2012 Texas Instruments, Inc. * * Based on sound/soc/codecs/tlv320aic3262.c * @@ -18,16 +18,16 @@ * * History: * -* Rev 0.1 ASoC driver support Mistral 20-01-2011 +* Rev 0.1 ASoC driver support 20-01-2011 * * The AIC325x ASoC driver is ported for the codec AIC3262. -* Rev 0.2 ASoC driver support Mistral 21-03-2011 +* Rev 0.2 ASoC driver support 21-03-2011 * The AIC326x ASoC driver is updated abe changes. * -* Rev 0.3 ASoC driver support Mistral 12.09.2011 +* Rev 0.3 ASoC driver support 12.09.2011 * fixed the compilation issues for Whistler support * -* Rev 0.4 ASoC driver support Mistral 27.09.2011 +* Rev 0.4 ASoC driver support 27.09.2011 * The AIC326x driver ported for Nvidia cardhu. * * Rev 0.5 Modified to support Multiple ASI Ports 08-Nov-2011 @@ -59,6 +59,7 @@ #include #include #include +#include #include "tlv320aic326x.h" @@ -69,13 +70,20 @@ */ static u8 aic3262_reg_ctl; -u8 dac_reg = 0, adc_gain = 0, hpl = 0, hpr = 0; -u8 rec_amp = 0, rampr = 0, spk_amp = 0; +#ifdef AIC3262_TiLoad + extern int aic3262_driver_init(struct snd_soc_codec *codec); +#endif + + + /* whenever aplay/arecord is run, aic3262_hw_params() function gets called. * This function reprograms the clock dividers etc. this flag can be used to * disable this when the clock dividers are programmed by pps config file */ static int soc_static_freq_config = 1; +static struct aic3262_priv *aic3262_priv_data; +static struct i2c_client *i2c_pdev; +static struct snd_soc_codec *aic3262_codec; /* ***************************************************************************** @@ -157,7 +165,7 @@ static int aic3262_multi_i2s_asi1_mute(struct snd_soc_dai *dai, int mute); static int aic3262_multi_i2s_asi2_mute(struct snd_soc_dai *dai, int mute); static int aic3262_multi_i2s_asi3_mute(struct snd_soc_dai *dai, int mute); - +#if 0 static const char *wclk1_pincontrol[] = { "ASI1 Word Clock Input/Output", "CLKOUT output"}; static const char *dout1_pincontrol[] = { @@ -203,22 +211,7 @@ static const char *clkin[] = { "mclk1", "bclk1", "gpio1", "pll_clk", "bclk2", "gpi1", "hf_ref_clk", "hf_osc_clk", "mclk2", "gpio2", "gpi2"}; -/* List of SOC_ENUM structures for the AIC3262 PIN Control Amixer Controls */ -static const struct soc_enum aic326x_enum[] = { - SOC_ENUM_SINGLE(WCLK1_PIN_CNTL_REG, 2, 2, wclk1_pincontrol), - SOC_ENUM_SINGLE(DOUT1_PIN_CNTL_REG, 1, 7, dout1_pincontrol), - SOC_ENUM_SINGLE(DIN1_PIN_CNTL_REG, 5, 2, din1_pincontrol), - SOC_ENUM_SINGLE(WCLK2_PIN_CNTL_REG, 2, 10, wclk2_pincontrol), - SOC_ENUM_SINGLE(BCLK2_PIN_CNTL_REG, 2, 10, bclk2_pincontrol), - SOC_ENUM_SINGLE(DOUT2_PIN_CNTL_REG, 1, 8, dout2_pincontrol), - SOC_ENUM_SINGLE(DIN2_PIN_CNTL_REG, 5, 2, din2_pincontrol), - SOC_ENUM_SINGLE(WCLK3_PIN_CNTL_REG, 2, 5, wclk3_pincontrol), - SOC_ENUM_SINGLE(BCLK3_PIN_CNTL_REG, 2, 5, bclk3_pincontrol), - SOC_ENUM_SINGLE(DOUT3_PIN_CNTL_REG, 1, 5, dout3_pincontrol), - SOC_ENUM_SINGLE(DIN3_PIN_CNTL_REG, 5, 2, din3_pincontrol), - SOC_ENUM_DOUBLE(DAC_ADC_CLKIN_REG, 0, 4, 11, clkin), -}; - +#endif #ifdef DAC_INDEPENDENT_VOL /* *---------------------------------------------------------------------------- @@ -267,14 +260,14 @@ static int n_control_get(struct snd_kcontrol *kcontrol, if (!strcmp(kcontrol->id.name, "Left DAC Volume")) { mask = AIC3262_8BITS_MASK; shift = 0; - val = aic3262_read(codec, mc->reg); + val = snd_soc_read(codec, mc->reg); ucontrol->value.integer.value[0] = (val <= 48) ? (val + 127) : (val - 129); } if (!strcmp(kcontrol->id.name, "Right DAC Volume")) { mask = AIC3262_8BITS_MASK; shift = 0; - val = aic3262_read(codec, mc->reg); + val = snd_soc_read(codec, mc->reg); ucontrol->value.integer.value[0] = (val <= 48) ? (val + 127) : (val - 129); } @@ -404,8 +397,8 @@ int snd_soc_get_volsw_2r_n(struct snd_kcontrol *kcontrol, } /* Read, update the corresponding Registers */ - val = (aic3262_read(codec, reg) >> shift) & mask; - val2 = (aic3262_read(codec, reg2) >> shift) & mask; + val = (snd_soc_read(codec, reg) >> shift) & mask; + val2 = (snd_soc_read(codec, reg2) >> shift) & mask; if (!strcmp(kcontrol->id.name, "PCM Playback Volume")) { ucontrol->value.integer.value[0] = @@ -569,7 +562,7 @@ static int __new_control_get(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); u32 val; - val = aic3262_read(codec, aic3262_reg_ctl); + val = snd_soc_read(codec, aic3262_reg_ctl); ucontrol->value.integer.value[0] = val; return 0; } @@ -613,6 +606,19 @@ static int __new_control_put(struct snd_kcontrol *kcontrol, } +/* + ***************************************************************************** + * Structure Initialization + ***************************************************************************** + */ +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -6350, 50, 0); +static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -1200, 50, 0); +static const DECLARE_TLV_DB_SCALE(spk_gain_tlv, 600, 600, 0); +static const DECLARE_TLV_DB_SCALE(output_gain_tlv, -600, 100, 0); +static const DECLARE_TLV_DB_SCALE(micpga_gain_tlv, 0, 50, 0); +static const DECLARE_TLV_DB_SCALE(adc_fine_gain_tlv, -40, 10, 0); +static const DECLARE_TLV_DB_SCALE(beep_gen_volume_tlv, -6300, 100, 0); + /* ***************************************************************************** * Structure Initialization @@ -620,28 +626,32 @@ static int __new_control_put(struct snd_kcontrol *kcontrol, */ static const struct snd_kcontrol_new aic3262_snd_controls[] = { /* Output */ - #ifndef DAC_INDEPENDENT_VOL +#ifndef DAC_INDEPENDENT_VOL /* sound new kcontrol for PCM Playback volume control */ - SOC_DOUBLE_R_N("PCM Playback Volume", DAC_LVOL, DAC_RVOL, 0, 0xAf, 0), - #endif - /* sound new kcontrol for HP driver gain */ - SOC_DOUBLE_R_N("HP Driver Gain", HPL_VOL, HPR_VOL, 0, 21, 0), - /* sound new kcontrol for SPK driver gain*/ - SOC_DOUBLE("SPK Driver Gain", SPK_AMP_CNTL_R4, 0, 4, 5, 0), - /* Reveiver driver Gain volume*/ - SOC_DOUBLE_R_N("REC Driver Volume", - REC_AMP_CNTL_R5, RAMPR_VOL, 0, 36, 0), - /* sound new kcontrol for PGA capture volume */ - SOC_DOUBLE_R_N("PGA Capture Volume", LADC_VOL, RADC_VOL, 0, 0x3F, - 0), - SOC_DOUBLE("ADC Fine Gain ", ADC_FINE_GAIN, 4, 0, 4, 1), - SOC_DOUBLE_R("PGA MIC Volume", MICL_PGA, MICR_PGA, 0, 95, 0), - - SOC_DOUBLE_R("LO to REC Volume", RAMP_CNTL_R1, RAMP_CNTL_R2, 0, 116, 1), - SOC_DOUBLE_R_N("LO to HP Volume", - HP_AMP_CNTL_R2, HP_AMP_CNTL_R3, 0, 117, 0), - SOC_DOUBLE_R("LO to SPK Volume", - SPK_AMP_CNTL_R2, SPK_AMP_CNTL_R3, 0, 116, 1), + + SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", + DAC_LVOL, DAC_RVOL, 8,0xffffff81, 0x30, dac_vol_tlv), +#endif + /*HP Driver Gain Control*/ + SOC_DOUBLE_R_SX_TLV("HeadPhone Driver Amplifier Volume", + HPL_VOL, HPR_VOL, 6, 0xfffffffa, 0xe, output_gain_tlv), + + /*LO Driver Gain Control*/ + SOC_DOUBLE_TLV("Speaker Amplifier Volume", + SPK_AMP_CNTL_R4, 4, 0, 5, 0, spk_gain_tlv), + + SOC_DOUBLE_R_SX_TLV("Receiver Amplifier Volume", + REC_AMP_CNTL_R5, RAMPR_VOL, 6, 0xfffffffa, 0x1d, output_gain_tlv), + + SOC_DOUBLE_R_SX_TLV("PCM Capture Volume", + LADC_VOL, RADC_VOL, 7,0xffffff68, 0x24, adc_vol_tlv), + + + SOC_DOUBLE_R_TLV ("MicPGA Volume Control", + MICL_PGA, MICR_PGA, 0, 0x5F, 0, micpga_gain_tlv), + SOC_DOUBLE_TLV("PCM Capture Fine Gain Volume", + ADC_FINE_GAIN, 4, 0, 5, 1, adc_fine_gain_tlv), + SOC_DOUBLE("ADC channel mute", ADC_FINE_GAIN, 7, 3, 1, 0), SOC_DOUBLE("DAC MUTE", DAC_MVOL_CONF, 2, 3, 1, 1), @@ -649,22 +659,21 @@ static const struct snd_kcontrol_new aic3262_snd_controls[] = { /* sound new kcontrol for Programming the registers from user space */ SOC_SINGLE_AIC3262("Program Registers"), - SOC_SINGLE("RESET", RESET_REG, 0 , 1, 0), + SOC_SINGLE("RESET", RESET_REG, 0,1,0), SOC_SINGLE("DAC VOL SOFT STEPPING", DAC_MVOL_CONF, 0, 2, 0), - #ifdef DAC_INDEPENDENT_VOL - SOC_SINGLE_N("Left DAC Volume", DAC_LVOL, 0, 0xAF, 0), - SOC_SINGLE_N("Right DAC Volume", DAC_RVOL, 0, 0xAF, 0), - #endif +#ifdef DAC_INDEPENDENT_VOL + /*SOC_SINGLE_N("Left DAC Volume", DAC_LVOL, 0, 0xAF, 0), + SOC_SINGLE_N("Right DAC Volume", DAC_RVOL, 0, 0xAF, 0),*/ +#endif SOC_SINGLE("DAC AUTO MUTE CONTROL", DAC_MVOL_CONF, 4, 7, 0), SOC_SINGLE("RIGHT MODULATOR SETUP", DAC_MVOL_CONF, 7, 1, 0), SOC_SINGLE("ADC Volume soft stepping", ADC_CHANNEL_POW, 0, 3, 0), - SOC_DOUBLE_R_N("MA Volume", - LADC_PGA_MAL_VOL, RADC_PGA_MAR_VOL, 0, 42, 0), + SOC_DOUBLE_R("MICPGA enable/disable",MICL_PGA,MICR_PGA,7, 1, 0), SOC_SINGLE("Mic Bias ext independent enable", MIC_BIAS_CNTL, 7, 1, 0), SOC_SINGLE("MICBIAS_EXT ON", MIC_BIAS_CNTL, 6, 1, 0), @@ -691,81 +700,36 @@ static const struct snd_kcontrol_new aic3262_snd_controls[] = { SOC_DOUBLE_R("AGC_GAIN_HYSTERESIS", LAGC_CNTL, RAGC_CNTL, 0, 3, 0), SOC_DOUBLE_R("AGC_HYSTERESIS", LAGC_CNTL_R2, RAGC_CNTL_R2, 6, 3, 0), - SOC_DOUBLE_R("AGC_NOISE_THRESHOLD", - LAGC_CNTL_R2, RAGC_CNTL_R2, 1, 31, 1), + SOC_DOUBLE_R("AGC_NOISE_THRESHOLD", LAGC_CNTL_R2, + RAGC_CNTL_R2, 1, 31, 1), SOC_DOUBLE_R("AGC_MAX_GAIN", LAGC_CNTL_R3, RAGC_CNTL_R3, 0, 116, 0), SOC_DOUBLE_R("AGC_ATCK_TIME", LAGC_CNTL_R4, RAGC_CNTL_R4, 3, 31, 0), SOC_DOUBLE_R("AGC_ATCK_SCALE_FACTOR", - LAGC_CNTL_R4, RAGC_CNTL_R4, 0, 7, 0), + LAGC_CNTL_R4, RAGC_CNTL_R4, 0, 7, 0), SOC_DOUBLE_R("AGC_DECAY_TIME", LAGC_CNTL_R5, RAGC_CNTL_R5, 3, 31, 0), SOC_DOUBLE_R("AGC_DECAY_SCALE_FACTOR", - LAGC_CNTL_R5, RAGC_CNTL_R5, 0, 7, 0), - SOC_DOUBLE_R("AGC_NOISE_DEB_TIME", - LAGC_CNTL_R6, RAGC_CNTL_R6, 0, 31, 0), - - SOC_DOUBLE_R("AGC_SGL_DEB_TIME", - LAGC_CNTL_R7, RAGC_CNTL_R7, 0, 0x0F, 0), - SOC_SINGLE("DAC PRB Selection", DAC_PRB, 0, 25, 0), - - SOC_SINGLE("INTERRUPT FLAG - Read only", 46, 0, 255, 0), - SOC_SINGLE("INTERRUPT STICKY FLAG - Read only", 44, 0, 255, 0), - SOC_SINGLE("INT1 CONTROL", 48, 0, 255, 0), - SOC_SINGLE("GPIO1 CONTROL", (PAGE_4 + 86), 0, 255, 0), - SOC_SINGLE("HP_DEPOP", HP_DEPOP, 0, 255, 0), + LAGC_CNTL_R5, RAGC_CNTL_R5, 0, 7, 0), + SOC_DOUBLE_R("AGC_NOISE_DEB_TIME", LAGC_CNTL_R6, + RAGC_CNTL_R6, 0, 31, 0), - #if defined(FULL_IN_CNTL) + SOC_DOUBLE_R("AGC_SGL_DEB_TIME", LAGC_CNTL_R7, + RAGC_CNTL_R7, 0, 0x0F, 0), - SOC_SINGLE("IN1L_2_LMPGA_P_CTL", LMIC_PGA_PIN, 6, 3, 0), - SOC_SINGLE("IN2L_2_LMPGA_P_CTL", LMIC_PGA_PIN, 4, 3, 0), - SOC_SINGLE("IN3L_2_LMPGA_P_CTL", LMIC_PGA_PIN, 2, 3, 0), - SOC_SINGLE("IN1R_2_LMPGA_P_CTL", LMIC_PGA_PIN, 0, 3, 0), + SOC_SINGLE("DAC PRB Selection",DAC_PRB, 0, 25, 0), - SOC_SINGLE("IN4L_2_LMPGA_P_CTL", LMIC_PGA_PM_IN4, 5, 1, 0), - SOC_SINGLE("IN4R_2_LMPGA_M_CTL", LMIC_PGA_PM_IN4, 4, 1, 0), - - SOC_SINGLE("CM1_2_LMPGA_M_CTL", LMIC_PGA_MIN, 6, 3, 0), - SOC_SINGLE("IN2R_2_LMPGA_M_CTL", LMIC_PGA_MIN, 4, 3, 0), - SOC_SINGLE("IN3R_2_LMPGA_M_CTL", LMIC_PGA_MIN, 2, 3, 0), - SOC_SINGLE("CM2_2_LMPGA_M_CTL", LMIC_PGA_MIN, 0, 3, 0), - - SOC_SINGLE("IN1R_2_RMPGA_P_CTL", RMIC_PGA_PIN, 6, 3, 0), - SOC_SINGLE("IN2R_2_RMPGA_P_CTL", RMIC_PGA_PIN, 4, 3, 0), - SOC_SINGLE("IN3R_2_RMPGA_P_CTL", RMIC_PGA_PIN, 2, 3, 0), - SOC_SINGLE("IN2L_2_RMPGA_P_CTL", RMIC_PGA_PIN, 0, 3, 0), - - SOC_SINGLE("IN4R_2_RMPGA_P_CTL", RMIC_PGA_PM_IN4, 5, 1, 0), - SOC_SINGLE("IN4L_2_RMPGA_M_CTL", RMIC_PGA_PM_IN4, 4, 1, 0), - - SOC_SINGLE("CM1_2_RMPGA_M_CTL", RMIC_PGA_MIN, 6, 3, 0), - SOC_SINGLE("IN1L_2_RMPGA_M_CTL", RMIC_PGA_MIN, 4, 3, 0), - SOC_SINGLE("IN3L_2_RMPGA_M_CTL", RMIC_PGA_MIN, 2, 3, 0), - SOC_SINGLE("CM2_2_RMPGA_M_CTL", RMIC_PGA_MIN, 0, 3, 0), - - #endif - - SOC_DOUBLE("MA_EN_CNTL", MA_CNTL, 3, 2, 1, 0), - SOC_DOUBLE("IN1 LO DIRECT BYPASS", MA_CNTL, 5, 4, 1, 0), + SOC_SINGLE("INTERRUPT FLAG - Read only", 46, 0, 255,0), + SOC_SINGLE("INTERRUPT STICKY FLAG - Read only", 44, 0, 255,0), + SOC_SINGLE("INT1 CONTROL", 48, 0, 255,0), + SOC_SINGLE("GPIO1 CONTROL", GPIO1_IO_CNTL, 0, 255,0), + SOC_SINGLE("HP_DEPOP", HP_DEPOP, 0, 255,0), SOC_DOUBLE("IN1 LO BYPASS VOLUME" , LINE_AMP_CNTL_R2, 3, 0, 3, 1), - SOC_DOUBLE("MA LO BYPASS EN", LINE_AMP_CNTL_R2, 7, 6, 1, 0), - - /* Pin control Macros */ - SOC_ENUM("DOUT1 Pin Control", aic326x_enum[DOUT1_ENUM]), - SOC_ENUM("DIN1 Pin Control", aic326x_enum[DIN1_ENUM]), - SOC_ENUM("WCLK2 Pin Control", aic326x_enum[WCLK2_ENUM]), - SOC_ENUM("BCLK2 Pin Control", aic326x_enum[BCLK2_ENUM]), - SOC_ENUM("DOUT2 Pin Control", aic326x_enum[DOUT2_ENUM]), - SOC_ENUM("DIN2 Pin Control", aic326x_enum[DIN2_ENUM]), - SOC_ENUM("WCLK3 Pin Control", aic326x_enum[WCLK3_ENUM]), - SOC_ENUM("BCLK3 Pin Control", aic326x_enum[BCLK3_ENUM]), - SOC_ENUM("DOUT3 Pin Control", aic326x_enum[DOUT3_ENUM]), - SOC_ENUM("DIN3 Pin Control", aic326x_enum[DIN3_ENUM]), - SOC_ENUM("DAC CLK IN", aic326x_enum[CLKIN_ENUM]), - SOC_ENUM("ADC CLK IN", aic326x_enum[CLKIN_ENUM]), + }; + /* the sturcture contains the different values for mclk */ static const struct aic3262_rate_divs aic3262_divs[] = { /* @@ -883,19 +847,19 @@ static void aic3262_multi_i2s_dump_regs(struct snd_soc_dai *dai) DBG(KERN_INFO "#Page0 REGS..\n"); for (counter = 0; counter < 85; counter++) { DBG(KERN_INFO "#%2d -> 0x%x\n", counter, - aic3262_read(codec, counter)); + snd_soc_read(codec, counter)); } DBG(KERN_INFO "#Page1 REGS..\n"); for (counter = 128; counter < 176; counter++) { DBG(KERN_INFO "#%2d -> 0x%x\n", (counter % 128), - aic3262_read(codec, counter)); + snd_soc_read(codec, counter)); } DBG(KERN_INFO "#Page4 REGS..\n"); for (counter = 512; counter < 631; counter++) { DBG(KERN_INFO "#%2d -> 0x%x\n", - (counter % 128), aic3262_read(codec, counter)); + (counter % 128), snd_soc_read(codec, counter)); } for (counter = 0; counter < MAX_ASI_COUNT; counter++) { @@ -969,19 +933,11 @@ static int aic3262_multi_i2s_asi1_mute(struct snd_soc_dai *dai, int mute) DBG(KERN_INFO "#%s : mute %d started\n", __func__, mute); - if (mute) { + if (mute && !aic3262->asiCtxt[0].port_muted ) { DBG(KERN_INFO "Mute if part\n"); - if (!aic3262->asiCtxt[0].port_muted) { - dac_reg = aic3262_read(codec, DAC_MVOL_CONF); - adc_gain = aic3262_read(codec, ADC_FINE_GAIN); - hpl = aic3262_read(codec, HPL_VOL); - hpr = aic3262_read(codec, HPR_VOL); - rec_amp = aic3262_read(codec, REC_AMP_CNTL_R5); - rampr = aic3262_read(codec, RAMPR_VOL); - spk_amp = aic3262_read(codec, SPK_AMP_CNTL_R4); - } - DBG(KERN_INFO "spk_reg = %2x\n\n", spk_amp); + + snd_soc_update_bits(codec, DAC_MVOL_CONF, DAC_LR_MUTE_MASK,DAC_LR_MUTE); /* First check if both Playback and Recording is going on * this interface. @@ -989,49 +945,29 @@ static int aic3262_multi_i2s_asi1_mute(struct snd_soc_dai *dai, int mute) if (aic3262->asiCtxt[0].asi_active > 1) { DBG("#%s Cannot Mute the ASI Now..\n", __func__); } else if (!(aic3262->asiCtxt[1].playback_mode) && - !(aic3262->asiCtxt[2].playback_mode)) { + !(aic3262->asiCtxt[2].playback_mode)) { /* Before Muting, please check if any other * ASI is active. if so, we cannot simply mute the * DAC and ADC Registers. */ - aic3262_write(codec, DAC_MVOL_CONF, - ((dac_reg & 0xF3) | 0x0C)); - aic3262_write(codec, ADC_FINE_GAIN, - ((adc_gain & 0x77) | 0x88)); - aic3262_write(codec, HPL_VOL, 0xB9); - aic3262_write(codec, HPR_VOL, 0xB9); - aic3262_write(codec, REC_AMP_CNTL_R5, 0x39); - aic3262_write(codec, RAMPR_VOL, 0x39); - aic3262_write(codec, SPK_AMP_CNTL_R4, 0x00); + DBG("#%s None of the ASI's are active now..\n", __func__); + snd_soc_write(codec, DAC_MVOL_CONF, + ((aic3262->dac_reg & 0xF3) | 0x0C)); + snd_soc_write(codec, ADC_FINE_GAIN, + ((aic3262->adc_gain & 0x77) | 0x88)); + snd_soc_write(codec, HPL_VOL, 0xB9); + snd_soc_write(codec, HPR_VOL, 0xB9); + snd_soc_write(codec, REC_AMP_CNTL_R5, 0x39); + snd_soc_write(codec, RAMPR_VOL, 0x39); + snd_soc_write(codec, SPK_AMP_CNTL_R4, 0x00); aic3262->asiCtxt[0].port_muted = 1; - } else { - DBG(KERN_INFO - "#%s: Other ASI Active. Cannot MUTE Codec..\n", - __func__); } } else { DBG(KERN_INFO "Mute else part\n"); - aic3262_write(codec, DAC_MVOL_CONF, (dac_reg & 0xF3)); - mdelay(5); - aic3262_write(codec, ADC_FINE_GAIN, (adc_gain & 0x77)); - mdelay(5); - aic3262_write(codec, HPL_VOL, hpl); - mdelay(5); - aic3262_write(codec, HPR_VOL, hpr); - mdelay(5); - aic3262_write(codec, REC_AMP_CNTL_R5, rec_amp); - mdelay(5); - aic3262_write(codec, RAMPR_VOL, rampr); - mdelay(5); - aic3262_write(codec, SPK_AMP_CNTL_R4, spk_amp); - mdelay(5); - - /* Basic hack */ - aic3262_write(codec, LINE_AMP_CNTL_R1, 0xc3); - aic3262_write(codec, HP_AMP_CNTL_R1, 0x33); - - aic3262->asiCtxt[0].port_muted = 0; - aic3262_multi_i2s_dump_regs(dai); + snd_soc_update_bits(codec, DAC_MVOL_CONF, + DAC_LR_MUTE_MASK, 0x0); + + /*aic3262_multi_i2s_dump_regs(dai);*/ } DBG(KERN_INFO "#%s : mute %d ended\n", __func__, mute); @@ -1042,7 +978,7 @@ static int aic3262_multi_i2s_asi1_mute(struct snd_soc_dai *dai, int mute) /* *---------------------------------------------------------------------------- * Function : aic3262_multi_i2s_asi2_maic3262_asi3_clk_configute -* Purpose : This function is to mute or unmute the left and right DAC +* Purpose : This function is to mute or unmute the left and right DAC * *---------------------------------------------------------------------------- */ @@ -1053,19 +989,9 @@ static int aic3262_multi_i2s_asi2_mute(struct snd_soc_dai *dai, int mute) DBG(KERN_INFO "#%s : mute %d started\n", __func__, mute); - if (mute) { + if (mute && !aic3262->asiCtxt[1].port_muted ) { DBG(KERN_INFO "Mute if part\n"); - - if (!aic3262->asiCtxt[1].port_muted) { - dac_reg = aic3262_read(codec, DAC_MVOL_CONF); - adc_gain = aic3262_read(codec, ADC_FINE_GAIN); - hpl = aic3262_read(codec, HPL_VOL); - hpr = aic3262_read(codec, HPR_VOL); - rec_amp = aic3262_read(codec, REC_AMP_CNTL_R5); - rampr = aic3262_read(codec, RAMPR_VOL); - spk_amp = aic3262_read(codec, SPK_AMP_CNTL_R4); - DBG(KERN_INFO "spk_reg = %2x\n\n", spk_amp); - } + snd_soc_update_bits(codec, DAC_MVOL_CONF, DAC_LR_MUTE_MASK,DAC_LR_MUTE); /* First check if both Playback and Recording is going on * this interface. @@ -1073,58 +999,39 @@ static int aic3262_multi_i2s_asi2_mute(struct snd_soc_dai *dai, int mute) if (aic3262->asiCtxt[1].asi_active > 1) { DBG("#%s Cannot Mute the ASI Now..\n", __func__); } else if (!(aic3262->asiCtxt[0].playback_mode) && - !(aic3262->asiCtxt[2].playback_mode)) { + !(aic3262->asiCtxt[2].playback_mode)) { /* Before Muting, please check if any other * ASI is active. if so, we cannot simply mute the * DAC and ADC Registers. */ - aic3262_write(codec, DAC_MVOL_CONF, - ((dac_reg & 0xF3) | 0x0C)); - aic3262_write(codec, ADC_FINE_GAIN, - ((adc_gain & 0x77) | 0x88)); - aic3262_write(codec, HPL_VOL, 0xB9); - aic3262_write(codec, HPR_VOL, 0xB9); - aic3262_write(codec, REC_AMP_CNTL_R5, 0x39); - aic3262_write(codec, RAMPR_VOL, 0x39); - aic3262_write(codec, SPK_AMP_CNTL_R4, 0x00); + snd_soc_write(codec, DAC_MVOL_CONF, + ((aic3262->dac_reg & 0xF3) | 0x0C)); + snd_soc_write(codec, ADC_FINE_GAIN, + ((aic3262->adc_gain & 0x77) | 0x88)); + snd_soc_write(codec, HPL_VOL, 0xB9); + snd_soc_write(codec, HPR_VOL, 0xB9); + snd_soc_write(codec, REC_AMP_CNTL_R5, 0x39); + snd_soc_write(codec, RAMPR_VOL, 0x39); + snd_soc_write(codec, SPK_AMP_CNTL_R4, 0x00); aic3262->asiCtxt[1].port_muted = 1; - } else { - DBG("#%s: Other ASI Active. Cannot MUTE Codec..\n", - __func__); } } else { DBG(KERN_INFO "Mute else part\n"); - aic3262_write(codec, DAC_MVOL_CONF, (dac_reg & 0xF3)); - mdelay(5); - aic3262_write(codec, ADC_FINE_GAIN, (adc_gain & 0x77)); - mdelay(5); - aic3262_write(codec, HPL_VOL, hpl); - mdelay(5); - aic3262_write(codec, HPR_VOL, hpr); - mdelay(5); - aic3262_write(codec, REC_AMP_CNTL_R5, rec_amp); - mdelay(5); - aic3262_write(codec, RAMPR_VOL, rampr); - mdelay(5); - aic3262_write(codec, SPK_AMP_CNTL_R4, spk_amp); - mdelay(5); - - /* Basic hack */ - aic3262_write(codec, LINE_AMP_CNTL_R1, 0xc3); - aic3262_write(codec, HP_AMP_CNTL_R1, 0x33); - - aic3262->asiCtxt[1].port_muted = 0; - aic3262_multi_i2s_dump_regs(dai); + snd_soc_update_bits(codec, DAC_MVOL_CONF, + DAC_LR_MUTE_MASK, 0x0); + + /*aic3262_multi_i2s_dump_regs(dai);*/ } DBG(KERN_INFO "#%s : mute %d ended\n", __func__, mute); return 0; } + /* *---------------------------------------------------------------------------- * Function : aic3262_multi_i2s_asi3_mute -* Purpose : This function is to mute or unmute the left and right DAC +* Purpose : This function is to mute or unmute the left and right DAC * *---------------------------------------------------------------------------- */ @@ -1135,19 +1042,9 @@ static int aic3262_multi_i2s_asi3_mute(struct snd_soc_dai *dai, int mute) DBG(KERN_INFO "#%s : mute %d started\n", __func__, mute); - if (mute) { + if (mute && !aic3262->asiCtxt[2].port_muted) { DBG("Mute if part\n"); - - if (!aic3262->asiCtxt[2].port_muted) { - dac_reg = aic3262_read(codec, DAC_MVOL_CONF); - adc_gain = aic3262_read(codec, ADC_FINE_GAIN); - hpl = aic3262_read(codec, HPL_VOL); - hpr = aic3262_read(codec, HPR_VOL); - rec_amp = aic3262_read(codec, REC_AMP_CNTL_R5); - rampr = aic3262_read(codec, RAMPR_VOL); - spk_amp = aic3262_read(codec, SPK_AMP_CNTL_R4); - } - DBG("spk_reg = %2x\n\n", spk_amp); + snd_soc_update_bits(codec, DAC_MVOL_CONF, DAC_LR_MUTE_MASK,DAC_LR_MUTE); /* First check if both Playback and Recording is going on * this interface. @@ -1155,48 +1052,29 @@ static int aic3262_multi_i2s_asi3_mute(struct snd_soc_dai *dai, int mute) if (aic3262->asiCtxt[2].asi_active > 1) { DBG("#%s Cannot Mute the ASI Now..\n", __func__); } else if (!(aic3262->asiCtxt[0].playback_mode) && - !(aic3262->asiCtxt[1].playback_mode)) { + !(aic3262->asiCtxt[1].playback_mode)) { /* Before Muting, please check if any other * ASI is active. if so, we cannot simply mute the * DAC and ADC Registers. */ - aic3262_write(codec, DAC_MVOL_CONF, - ((dac_reg & 0xF3) | 0x0C)); - aic3262_write(codec, ADC_FINE_GAIN, - ((adc_gain & 0x77) | 0x88)); - aic3262_write(codec, HPL_VOL, 0xB9); - aic3262_write(codec, HPR_VOL, 0xB9); - aic3262_write(codec, REC_AMP_CNTL_R5, 0x39); - aic3262_write(codec, RAMPR_VOL, 0x39); - aic3262_write(codec, SPK_AMP_CNTL_R4, 0x00); + snd_soc_write(codec, DAC_MVOL_CONF, + ((aic3262->dac_reg & 0xF3) | 0x0C)); + snd_soc_write(codec, ADC_FINE_GAIN, + ((aic3262->adc_gain & 0x77) | 0x88)); + snd_soc_write(codec, HPL_VOL, 0xB9); + snd_soc_write(codec, HPR_VOL, 0xB9); + snd_soc_write(codec, REC_AMP_CNTL_R5, 0x39); + snd_soc_write(codec, RAMPR_VOL, 0x39); + snd_soc_write(codec, SPK_AMP_CNTL_R4, 0x00); aic3262->asiCtxt[2].port_muted = 1; - } else { - DBG("#%s: Other ASI Active. Cannot MUTE Codec..\n", - __func__); } } else { DBG("Mute else part\n"); - aic3262_write(codec, DAC_MVOL_CONF, (dac_reg & 0xF3)); - mdelay(5); - aic3262_write(codec, ADC_FINE_GAIN, (adc_gain & 0x77)); - mdelay(5); - aic3262_write(codec, HPL_VOL, hpl); - mdelay(5); - aic3262_write(codec, HPR_VOL, hpr); - mdelay(5); - aic3262_write(codec, REC_AMP_CNTL_R5, rec_amp); - mdelay(5); - aic3262_write(codec, RAMPR_VOL, rampr); - mdelay(5); - aic3262_write(codec, SPK_AMP_CNTL_R4, spk_amp); - mdelay(5); - - /* Basic hack */ - aic3262_write(codec, LINE_AMP_CNTL_R1, 0xc3); - aic3262_write(codec, HP_AMP_CNTL_R1, 0x33); - - aic3262->asiCtxt[2].port_muted = 0; - aic3262_multi_i2s_dump_regs(dai); + snd_soc_update_bits(codec, DAC_MVOL_CONF, + DAC_LR_MUTE_MASK, 0x0); + + /*aic3262_multi_i2s_dump_regs(dai);*/ + } DBG(KERN_INFO "#%s : mute %d ended\n", __func__, mute); @@ -1258,8 +1136,8 @@ static int aic3262_multi_i2s_asi1_set_dai_fmt(struct snd_soc_dai *codec_dai, /* Read the B0_P4_R4 and B0_P4_R10 Registers to configure the * ASI1 Bus and Clock Formats depending on the PCM Format. */ - iface_reg = aic3262_read(codec, ASI1_BUS_FMT); - clk_reg = aic3262_read(codec, ASI1_BWCLK_CNTL_REG); + iface_reg = snd_soc_read(codec, ASI1_BUS_FMT); + clk_reg = snd_soc_read(codec, ASI1_BWCLK_CNTL_REG); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1311,7 +1189,7 @@ static int aic3262_multi_i2s_asi1_set_dai_fmt(struct snd_soc_dai *codec_dai, __func__, codec_dai->id); iface_reg = (iface_reg & 0x1f) | 0x80; /* voice call need data offset in 1 bitclock */ - aic3262_write(codec, ASI1_LCH_OFFSET, 1); + snd_soc_write(codec, ASI1_LCH_OFFSET, 1); break; default: printk(KERN_ERR @@ -1325,21 +1203,21 @@ static int aic3262_multi_i2s_asi1_set_dai_fmt(struct snd_soc_dai *codec_dai, /* Configure B0_P4_R65_D[5:2] to 001 This configures the * WCLK1 Pin to ASI1 */ - regvalue = aic3262_read(codec, WCLK1_PIN_CNTL_REG); - aic3262_write(codec, WCLK1_PIN_CNTL_REG, (regvalue | BIT2)); + regvalue = snd_soc_read(codec, WCLK1_PIN_CNTL_REG); + snd_soc_write(codec, WCLK1_PIN_CNTL_REG, (regvalue | BIT2)); /* Configure B0_P4_R68_d[6:5] = 01 and B0_P4_R67_D[4:1] to 0001 * to ensure that the DIN1 and DOUT1 Pins are configured * correctly */ - regvalue = aic3262_read(codec, DIN1_PIN_CNTL_REG); - aic3262_write(codec, DIN1_PIN_CNTL_REG, (regvalue | BIT5)); - regvalue = aic3262_read(codec, DOUT1_PIN_CNTL_REG); - aic3262_write(codec, DOUT1_PIN_CNTL_REG, (regvalue | BIT1)); + regvalue = snd_soc_read(codec, DIN1_PIN_CNTL_REG); + snd_soc_write(codec, DIN1_PIN_CNTL_REG, (regvalue | BIT5)); + regvalue = snd_soc_read(codec, DOUT1_PIN_CNTL_REG); + snd_soc_write(codec, DOUT1_PIN_CNTL_REG, (regvalue | BIT1)); - aic3262_write(codec, ASI1_BWCLK_CNTL_REG, clk_reg); + snd_soc_write(codec, ASI1_BWCLK_CNTL_REG, clk_reg); - aic3262_write(codec, ASI1_BUS_FMT, iface_reg); + snd_soc_write(codec, ASI1_BUS_FMT, iface_reg); return 0; } @@ -1366,8 +1244,8 @@ static int aic3262_multi_i2s_asi2_set_dai_fmt(struct snd_soc_dai *codec_dai, /* Read the B0_P4_R17 and B0_P4_R26 Registers to configure the * ASI1 Bus and Clock Formats depending on the PCM Format. */ - iface_reg = aic3262_read(codec, ASI2_BUS_FMT); - clk_reg = aic3262_read(codec, ASI2_BWCLK_CNTL_REG); + iface_reg = snd_soc_read(codec, ASI2_BUS_FMT); + clk_reg = snd_soc_read(codec, ASI2_BWCLK_CNTL_REG); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1420,7 +1298,7 @@ static int aic3262_multi_i2s_asi2_set_dai_fmt(struct snd_soc_dai *codec_dai, __func__, codec_dai->id); iface_reg = (iface_reg & 0x1f) | 0x80; /* voice call need data offset in 1 bitclock */ - aic3262_write(codec, ASI2_LCH_OFFSET, 1); + snd_soc_write(codec, ASI2_LCH_OFFSET, 1); break; default: printk(KERN_ERR "#%s:Invalid DAI interface format\n", __func__); @@ -1435,25 +1313,25 @@ static int aic3262_multi_i2s_asi2_set_dai_fmt(struct snd_soc_dai *codec_dai, * WCLK2 Pin to ASI2 */ - regvalue = aic3262_read(codec, WCLK2_PIN_CNTL_REG); - aic3262_write(codec, WCLK2_PIN_CNTL_REG, (regvalue | BIT2)); + regvalue = snd_soc_read(codec, WCLK2_PIN_CNTL_REG); + snd_soc_write(codec, WCLK2_PIN_CNTL_REG, (regvalue | BIT2)); - regvalue = aic3262_read(codec, BCLK2_PIN_CNTL_REG); - aic3262_write(codec, BCLK2_PIN_CNTL_REG, (regvalue | BIT2)); + regvalue = snd_soc_read(codec, BCLK2_PIN_CNTL_REG); + snd_soc_write(codec, BCLK2_PIN_CNTL_REG, (regvalue | BIT2)); /* Configure B0_P4_R72_d[6:5] = 01 and B0_P4_R71_D[4:1] to 0001 * to ensure that the DIN2 and DOUT2 Pins are configured * correctly */ - regvalue = aic3262_read(codec, DIN2_PIN_CNTL_REG); - aic3262_write(codec, DIN2_PIN_CNTL_REG, (regvalue | BIT5)); + regvalue = snd_soc_read(codec, DIN2_PIN_CNTL_REG); + snd_soc_write(codec, DIN2_PIN_CNTL_REG, (regvalue | BIT5)); - regvalue = aic3262_read(codec, DOUT2_PIN_CNTL_REG); - aic3262_write(codec, DOUT2_PIN_CNTL_REG, (regvalue | BIT5 | BIT1)); + regvalue = snd_soc_read(codec, DOUT2_PIN_CNTL_REG); + snd_soc_write(codec, DOUT2_PIN_CNTL_REG, (regvalue | BIT5 | BIT1)); - aic3262_write(codec, ASI2_BWCLK_CNTL_REG, clk_reg); + snd_soc_write(codec, ASI2_BWCLK_CNTL_REG, clk_reg); - aic3262_write(codec, ASI2_BUS_FMT, iface_reg); + snd_soc_write(codec, ASI2_BUS_FMT, iface_reg); return 0; } @@ -1479,8 +1357,8 @@ static int aic3262_multi_i2s_asi3_set_dai_fmt(struct snd_soc_dai *codec_dai, /* Read the B0_P4_R33 and B0_P4_R42 Registers to configure the * ASI1 Bus and Clock Formats depending on the PCM Format. */ - iface_reg = aic3262_read(codec, ASI3_BUS_FMT); - clk_reg = aic3262_read(codec, ASI3_BWCLK_CNTL_REG); + iface_reg = snd_soc_read(codec, ASI3_BUS_FMT); + clk_reg = snd_soc_read(codec, ASI3_BWCLK_CNTL_REG); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1531,7 +1409,7 @@ static int aic3262_multi_i2s_asi3_set_dai_fmt(struct snd_soc_dai *codec_dai, __func__, codec_dai->id); iface_reg = (iface_reg & 0x1f) | 0x80; /* voice call need data offset in 1 bitclock */ - aic3262_write(codec, ASI3_LCH_OFFSET, 1); + snd_soc_write(codec, ASI3_LCH_OFFSET, 1); break; default: printk(KERN_ERR @@ -1545,24 +1423,24 @@ static int aic3262_multi_i2s_asi3_set_dai_fmt(struct snd_soc_dai *codec_dai, /* Configure B0_P4_R73_D[5:2] to 0001 This configures the * WCLK1 Pin to ASI1 */ - regvalue = aic3262_read(codec, WCLK3_PIN_CNTL_REG); - aic3262_write(codec, WCLK3_PIN_CNTL_REG, (regvalue | BIT2)); + regvalue = snd_soc_read(codec, WCLK3_PIN_CNTL_REG); + snd_soc_write(codec, WCLK3_PIN_CNTL_REG, (regvalue | BIT2)); - regvalue = aic3262_read(codec, BCLK3_PIN_CNTL_REG); - aic3262_write(codec, BCLK3_PIN_CNTL_REG, (regvalue | BIT2)); + regvalue = snd_soc_read(codec, BCLK3_PIN_CNTL_REG); + snd_soc_write(codec, BCLK3_PIN_CNTL_REG, (regvalue | BIT2)); /* Configure B0_P4_R76_d[6:5] = 01 and B0_P4_R75_D[4:1] to 0001 * to ensure that the DIN1 and DOUT1 Pins are configured * correctly */ - regvalue = aic3262_read(codec, DIN3_PIN_CNTL_REG); - aic3262_write(codec, DIN3_PIN_CNTL_REG, (regvalue | BIT5)); - regvalue = aic3262_read(codec, DOUT3_PIN_CNTL_REG); - aic3262_write(codec, DOUT3_PIN_CNTL_REG, (regvalue | BIT1)); + regvalue = snd_soc_read(codec, DIN3_PIN_CNTL_REG); + snd_soc_write(codec, DIN3_PIN_CNTL_REG, (regvalue | BIT5)); + regvalue = snd_soc_read(codec, DOUT3_PIN_CNTL_REG); + snd_soc_write(codec, DOUT3_PIN_CNTL_REG, (regvalue | BIT1)); - aic3262_write(codec, ASI3_BWCLK_CNTL_REG, clk_reg); + snd_soc_write(codec, ASI3_BWCLK_CNTL_REG, clk_reg); - aic3262_write(codec, ASI3_BUS_FMT, iface_reg); + snd_soc_write(codec, ASI3_BUS_FMT, iface_reg); return 0; } @@ -1600,9 +1478,6 @@ static int aic3262_multi_i2s_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, int source, unsigned int freq_in, unsigned int freq_out) { - /*u16 reg, enable; - int offset; - struct snd_soc_codec *codec = codec_dai->codec;*/ printk(KERN_INFO "%s: DAI ID %d PLL_ID %d InFreq %d OutFreq %d\n", __func__, pll_id, codec_dai->id, freq_in, freq_out); @@ -1630,35 +1505,36 @@ static int aic3262_asi1_clk_config(struct snd_soc_codec *codec, DBG(KERN_INFO "%s: Invoked\n", __func__); - if (aic3262->asiCtxt[0].master == 1) { - DBG(KERN_INFO - "#%s: Codec Master on ASI1 Port. Enabling BCLK WCLK Divider.\n", - __func__); - bclk_N_value = aic3262->asiCtxt[0].bclk_div; - aic3262_write(codec, ASI1_BCLK_N, (bclk_N_value | 0x80)); - - wclk_N_value = aic3262_read(codec, ASI1_WCLK_N); - aic3262_write(codec, ASI1_WCLK_N, (wclk_N_value | 0xA0)); - } /* Configure the BCLK and WCLK Output Mux Options */ - regval = aic3262_read(codec, ASI1_BWCLK_OUT_CNTL); + regval = snd_soc_read(codec, ASI1_BWCLK_OUT_CNTL); regval &= ~(AIC3262_ASI_BCLK_MUX_MASK | AIC3262_ASI_WCLK_MUX_MASK); regval |= (aic3262->asiCtxt[0].bclk_output << AIC3262_ASI_BCLK_MUX_SHIFT); regval |= aic3262->asiCtxt[0].wclk_output; - aic3262_write(codec, ASI1_BWCLK_OUT_CNTL, regval); + snd_soc_write(codec, ASI1_BWCLK_OUT_CNTL, regval); /* Configure the corresponding miniDSP Data Ports */ - minidspD_data = aic3262_read(codec, MINIDSP_PORT_CNTL_REG); + minidspD_data = snd_soc_read(codec, MINIDSP_PORT_CNTL_REG); minidspD_data &= ~(BIT5 | BIT4); - aic3262_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data); + snd_soc_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data); - minidspA_data = aic3262_read(codec, ASI1_ADC_INPUT_CNTL); + minidspA_data = snd_soc_read(codec, ASI1_ADC_INPUT_CNTL); minidspA_data &= ~(BIT2 | BIT1 | BIT0); minidspA_data |= aic3262->asiCtxt[0].adc_input; - aic3262_write(codec, ASI1_ADC_INPUT_CNTL, minidspA_data); + snd_soc_write(codec, ASI1_ADC_INPUT_CNTL, minidspA_data); + + if (aic3262->asiCtxt[0].master == 1) { + DBG(KERN_INFO + "#%s: Codec Master on ASI1 Port. Enabling BCLK WCLK Divider.\n", + __func__); + bclk_N_value = aic3262->asiCtxt[0].bclk_div; + snd_soc_write(codec, ASI1_BCLK_N, (bclk_N_value | 0x80)); + + wclk_N_value = snd_soc_read(codec, ASI1_WCLK_N); + snd_soc_write(codec, ASI1_WCLK_N, (wclk_N_value | 0xA0)); + } return 0; } @@ -1682,34 +1558,35 @@ static int aic3262_asi2_clk_config(struct snd_soc_codec *codec, DBG(KERN_INFO "%s: Invoked\n", __func__); - if (aic3262->asiCtxt[1].master == 1) { - DBG(KERN_INFO - "#%s: Codec Master on ASI2 Port. Enabling BCLK WCLK Divider.\n", - __func__); - bclk_N_value = aic3262->asiCtxt[1].bclk_div; - aic3262_write(codec, ASI2_BCLK_N, (bclk_N_value | 0x80)); - wclk_N_value = aic3262_read(codec, ASI2_WCLK_N); - aic3262_write(codec, ASI2_WCLK_N, (wclk_N_value | 0xA0)); - } /* Configure the BCLK and WCLK Output Mux Options */ - regval = aic3262_read(codec, ASI2_BWCLK_OUT_CNTL); + regval = snd_soc_read(codec, ASI2_BWCLK_OUT_CNTL); regval &= ~(AIC3262_ASI_BCLK_MUX_MASK | AIC3262_ASI_WCLK_MUX_MASK); regval |= (aic3262->asiCtxt[1].bclk_output << AIC3262_ASI_BCLK_MUX_SHIFT); regval |= aic3262->asiCtxt[1].wclk_output; - aic3262_write(codec, ASI2_BWCLK_OUT_CNTL, regval); + snd_soc_write(codec, ASI2_BWCLK_OUT_CNTL, regval); /* Configure the corresponding miniDSP Data Ports */ - minidspD_data = aic3262_read(codec, MINIDSP_PORT_CNTL_REG); + minidspD_data = snd_soc_read(codec, MINIDSP_PORT_CNTL_REG); minidspD_data |= (BIT2); - aic3262_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data); + snd_soc_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data); - minidspA_data = aic3262_read(codec, ASI2_ADC_INPUT_CNTL); + minidspA_data = snd_soc_read(codec, ASI2_ADC_INPUT_CNTL); minidspA_data &= ~(BIT2 | BIT1 | BIT0); minidspA_data |= aic3262->asiCtxt[1].adc_input; - aic3262_write(codec, ASI2_ADC_INPUT_CNTL, minidspA_data); + snd_soc_write(codec, ASI2_ADC_INPUT_CNTL, minidspA_data); + + if (aic3262->asiCtxt[1].master == 1) { + DBG(KERN_INFO + "#%s: Codec Master on ASI2 Port. Enabling BCLK WCLK Divider.\n", + __func__); + bclk_N_value = aic3262->asiCtxt[1].bclk_div; + snd_soc_write(codec, ASI2_BCLK_N, (bclk_N_value | 0x80)); + wclk_N_value = snd_soc_read(codec, ASI2_WCLK_N); + snd_soc_write(codec, ASI2_WCLK_N, (wclk_N_value | 0xA0)); + } return 0; } @@ -1733,34 +1610,34 @@ static int aic3262_asi3_clk_config(struct snd_soc_codec *codec, DBG(KERN_INFO "%s:\n", __func__); - if (aic3262->asiCtxt[2].master == 1) { - DBG(KERN_INFO - "#%s: Codec Master on ASI3 Port. Enabling BCLK WCLK Divider.\n", - __func__); - bclk_N_value = aic3262->asiCtxt[2].bclk_div; - aic3262_write(codec, ASI2_BCLK_N, (bclk_N_value | 0x80)); - - wclk_N_value = aic3262_read(codec, ASI3_WCLK_N); - aic3262_write(codec, ASI3_WCLK_N, (wclk_N_value | 0xA0)); - } /* Configure the BCLK and WCLK Output Mux Options */ - regval = aic3262_read(codec, ASI3_BWCLK_OUT_CNTL); + regval = snd_soc_read(codec, ASI3_BWCLK_OUT_CNTL); regval &= ~(AIC3262_ASI_BCLK_MUX_MASK | AIC3262_ASI_WCLK_MUX_MASK); regval |= (aic3262->asiCtxt[2].bclk_output << AIC3262_ASI_BCLK_MUX_SHIFT); regval |= aic3262->asiCtxt[2].wclk_output; - aic3262_write(codec, ASI3_BWCLK_OUT_CNTL, regval); + snd_soc_write(codec, ASI3_BWCLK_OUT_CNTL, regval); - minidspD_data = aic3262_read(codec, MINIDSP_PORT_CNTL_REG); + minidspD_data = snd_soc_read(codec, MINIDSP_PORT_CNTL_REG); minidspD_data |= (BIT1); - aic3262_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data); + snd_soc_write(codec, MINIDSP_PORT_CNTL_REG, minidspD_data); - minidspA_data = aic3262_read(codec, ASI3_ADC_INPUT_CNTL); + minidspA_data = snd_soc_read(codec, ASI3_ADC_INPUT_CNTL); minidspA_data &= ~(BIT2 | BIT1 | BIT0); minidspA_data |= aic3262->asiCtxt[2].adc_input; - aic3262_write(codec, ASI3_ADC_INPUT_CNTL, minidspA_data); + snd_soc_write(codec, ASI3_ADC_INPUT_CNTL, minidspA_data); + if (aic3262->asiCtxt[2].master == 1) { + DBG(KERN_INFO + "#%s: Codec Master on ASI3 Port. Enabling BCLK WCLK Divider.\n", + __func__); + bclk_N_value = aic3262->asiCtxt[2].bclk_div; + snd_soc_write(codec, ASI2_BCLK_N, (bclk_N_value | 0x80)); + + wclk_N_value = snd_soc_read(codec, ASI3_WCLK_N); + snd_soc_write(codec, ASI3_WCLK_N, (wclk_N_value | 0xA0)); + } return 0; } @@ -1807,7 +1684,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, /* Configure the PLL J, R D values only if none of the ASI * Interfaces are Active. */ - /*if (!(AIC3262_MULTI_ASI_ACTIVE(aic3262))) {*/ + if (1) { DBG(KERN_INFO "#%s: None of the ASIs active yet...\n", __func__); @@ -1815,58 +1692,58 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, /* Setting P & R values are set to 1 and 1 at init*/ /* J value */ - aic3262_write(codec, PLL_J_REG, aic3262_divs[i].pll_j); + snd_soc_write(codec, PLL_J_REG, aic3262_divs[i].pll_j); /* MSB & LSB for D value */ - aic3262_write(codec, PLL_D_MSB, (aic3262_divs[i].pll_d >> 8)); - aic3262_write(codec, PLL_D_LSB, + snd_soc_write(codec, PLL_D_MSB, (aic3262_divs[i].pll_d >> 8)); + snd_soc_write(codec, PLL_D_LSB, (aic3262_divs[i].pll_d & AIC3262_8BITS_MASK)); /* NDAC divider value */ - data = aic3262_read(codec, NDAC_DIV_POW_REG); + data = snd_soc_read(codec, NDAC_DIV_POW_REG); DBG(KERN_INFO "# reading NDAC = %d , NDAC_DIV_POW_REG = %x\n", aic3262_divs[i].ndac, data); - aic3262_write(codec, NDAC_DIV_POW_REG, + snd_soc_write(codec, NDAC_DIV_POW_REG, ((data & 0x80)|(aic3262_divs[i].ndac))); DBG(KERN_INFO "# writing NDAC = %d , NDAC_DIV_POW_REG = %x\n", aic3262_divs[i].ndac, ((data & 0x80)|(aic3262_divs[i].ndac))); /* MDAC divider value */ - data = aic3262_read(codec, MDAC_DIV_POW_REG); + data = snd_soc_read(codec, MDAC_DIV_POW_REG); DBG(KERN_INFO "# reading MDAC = %d , MDAC_DIV_POW_REG = %x\n", aic3262_divs[i].mdac, data); - aic3262_write(codec, MDAC_DIV_POW_REG, + snd_soc_write(codec, MDAC_DIV_POW_REG, ((data & 0x80)|(aic3262_divs[i].mdac))); DBG(KERN_INFO "# writing MDAC = %d , MDAC_DIV_POW_REG = %x\n", aic3262_divs[i].mdac, ((data & 0x80)|(aic3262_divs[i].mdac))); /* DOSR MSB & LSB values */ - aic3262_write(codec, DOSR_MSB_REG, aic3262_divs[i].dosr >> 8); + snd_soc_write(codec, DOSR_MSB_REG, aic3262_divs[i].dosr >> 8); DBG(KERN_INFO "# writing DOSR_MSB_REG = %d\n", (aic3262_divs[i].dosr >> 8)); - aic3262_write(codec, DOSR_LSB_REG, + snd_soc_write(codec, DOSR_LSB_REG, aic3262_divs[i].dosr & AIC3262_8BITS_MASK); DBG(KERN_INFO "# writing DOSR_LSB_REG = %d\n", (aic3262_divs[i].dosr & AIC3262_8BITS_MASK)); /* NADC divider value */ - data = aic3262_read(codec, NADC_DIV_POW_REG); - aic3262_write(codec, NADC_DIV_POW_REG, + data = snd_soc_read(codec, NADC_DIV_POW_REG); + snd_soc_write(codec, NADC_DIV_POW_REG, ((data & 0x80)|(aic3262_divs[i].nadc))); DBG(KERN_INFO "# writing NADC_DIV_POW_REG = %d\n", aic3262_divs[i].nadc); /* MADC divider value */ - data = aic3262_read(codec, MADC_DIV_POW_REG); - aic3262_write(codec, MADC_DIV_POW_REG, + data = snd_soc_read(codec, MADC_DIV_POW_REG); + snd_soc_write(codec, MADC_DIV_POW_REG, ((data & 0x80)|(aic3262_divs[i].madc))); DBG(KERN_INFO "# writing MADC_DIV_POW_REG = %d\n", aic3262_divs[i].madc); /* AOSR value */ - aic3262_write(codec, AOSR_REG, aic3262_divs[i].aosr); + snd_soc_write(codec, AOSR_REG, aic3262_divs[i].aosr); DBG(KERN_INFO "# writing AOSR = %d\n", aic3262_divs[i].aosr); } else { DBG(KERN_INFO "#Atleast 1 ASI Active. Cannot Program PLL..\n"); @@ -1884,7 +1761,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, /* Read the DAC Control Register and configure it * as per the ASIContext Structure Settings. */ - dacpath = aic3262_read(codec, ASI1_DAC_OUT_CNTL); + dacpath = snd_soc_read(codec, ASI1_DAC_OUT_CNTL); dacpath &= ~(AIC3262_ASI_LDAC_PATH_MASK | AIC3262_ASI_RDAC_PATH_MASK); dacpath |= (aic3262->asiCtxt[0].left_dac_output @@ -1892,7 +1769,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, dacpath |= (aic3262->asiCtxt[0].right_dac_output << AIC3262_ASI_RDAC_PATH_SHIFT); - aic3262_write(codec, ASI1_DAC_OUT_CNTL, dacpath); + snd_soc_write(codec, ASI1_DAC_OUT_CNTL, dacpath); aic3262->asiCtxt[0].playback_mode = 1; aic3262->asiCtxt[0].bclk_div = @@ -1901,11 +1778,11 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, /* For Recording, Configure the DOUT Pin as per * ASIContext Structure Settings. */ - adcpath = aic3262_read(codec, ASI1_DATA_OUT); + adcpath = snd_soc_read(codec, ASI1_DATA_OUT); adcpath &= ~(AIC3262_ASI_DOUT_MASK); adcpath |= aic3262->asiCtxt[0].dout_option; - aic3262_write(codec, ASI1_DATA_OUT, adcpath); + snd_soc_write(codec, ASI1_DATA_OUT, adcpath); aic3262->asiCtxt[0].capture_mode = 1; } @@ -1923,7 +1800,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, /* Read the DAC Control Register and configure it * as per theASIContext Structure Settings. */ - dacpath = aic3262_read(codec, ASI2_DAC_OUT_CNTL); + dacpath = snd_soc_read(codec, ASI2_DAC_OUT_CNTL); dacpath &= ~(AIC3262_ASI_LDAC_PATH_MASK | AIC3262_ASI_RDAC_PATH_MASK); dacpath |= (aic3262->asiCtxt[1].left_dac_output @@ -1931,7 +1808,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, dacpath |= (aic3262->asiCtxt[1].right_dac_output << AIC3262_ASI_RDAC_PATH_SHIFT); - aic3262_write(codec, ASI2_DAC_OUT_CNTL, dacpath); + snd_soc_write(codec, ASI2_DAC_OUT_CNTL, dacpath); aic3262->asiCtxt[1].playback_mode = 1; aic3262->asiCtxt[1].bclk_div = @@ -1940,10 +1817,10 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, /* For Recording, Configure the DOUT Pin as per * ASIContext Structure Settings. */ - adcpath = aic3262_read(codec, ASI2_DATA_OUT); + adcpath = snd_soc_read(codec, ASI2_DATA_OUT); adcpath &= ~(AIC3262_ASI_DOUT_MASK); adcpath |= aic3262->asiCtxt[1].dout_option; - aic3262_write(codec, ASI2_DATA_OUT, adcpath); + snd_soc_write(codec, ASI2_DATA_OUT, adcpath); aic3262->asiCtxt[1].capture_mode = 1; } @@ -1960,14 +1837,14 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, /* Read the DAC Control Register and configure * it as per the ASIContext Structure Settings. */ - dacpath = aic3262_read(codec, ASI3_DAC_OUT_CNTL); + dacpath = snd_soc_read(codec, ASI3_DAC_OUT_CNTL); dacpath &= ~(AIC3262_ASI_LDAC_PATH_MASK | AIC3262_ASI_RDAC_PATH_MASK); dacpath |= (aic3262->asiCtxt[2].left_dac_output << AIC3262_ASI_LDAC_PATH_SHIFT); dacpath |= (aic3262->asiCtxt[2].right_dac_output << AIC3262_ASI_RDAC_PATH_SHIFT); - aic3262_write(codec, + snd_soc_write(codec, ASI3_DAC_OUT_CNTL, dacpath); aic3262->asiCtxt[2].playback_mode = 1; @@ -1980,7 +1857,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, */ adcpath &= ~(AIC3262_ASI_DOUT_MASK); adcpath |= aic3262->asiCtxt[2].dout_option; - aic3262_write(codec, ASI3_DATA_OUT, adcpath); + snd_soc_write(codec, ASI3_DATA_OUT, adcpath); aic3262->asiCtxt[2].capture_mode = 1; } @@ -1994,7 +1871,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, __func__, (regoffset/128), (regoffset % 128)); /* Read the correspondig ASI DAI Interface Register */ - data = aic3262_read(codec, regoffset); + data = snd_soc_read(codec, regoffset); data = data & 0xe7; @@ -2024,10 +1901,10 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, } /* configure the respective Registers for the above configuration */ - aic3262_write(codec, regoffset, data); + snd_soc_write(codec, regoffset, data); for (j = 0; j < NO_FEATURE_REGS; j++) { - aic3262_write(codec, + snd_soc_write(codec, aic3262_divs[i].codec_specific_regs[j].reg_offset, aic3262_divs[i].codec_specific_regs[j].reg_val); } @@ -2070,7 +1947,7 @@ static int aic3262_multi_i2s_hw_params(struct snd_pcm_substream *substream, * We can use this function to disable the DAC and ADC specific inputs from the * individual ASI Ports of the Audio Codec. */ -static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream, +static int aic3262_multi_i2s_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; @@ -2113,11 +1990,11 @@ static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream, * going on this ASI Interface */ - value = aic3262_read(codec, ASI1_BCLK_N); - aic3262_write(codec, ASI1_BCLK_N, (value & 0x7f)); + value = snd_soc_read(codec, ASI1_BCLK_N); + snd_soc_write(codec, ASI1_BCLK_N, (value & 0x7f)); - value = aic3262_read(codec, ASI1_WCLK_N); - aic3262_write(codec, ASI1_WCLK_N, (value & 0x7f)); + value = snd_soc_read(codec, ASI1_WCLK_N); + snd_soc_write(codec, ASI1_WCLK_N, (value & 0x7f)); } dacregoffset = ASI1_DAC_OUT_CNTL; @@ -2128,11 +2005,11 @@ static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream, * the Bit Clock Divider and Word Clock Dividers */ if (aic3262->asiCtxt[1].master == 1) { - value = aic3262_read(codec, ASI2_BCLK_N); - aic3262_write(codec, ASI2_BCLK_N, (value & 0x7f)); + value = snd_soc_read(codec, ASI2_BCLK_N); + snd_soc_write(codec, ASI2_BCLK_N, (value & 0x7f)); - value = aic3262_read(codec, ASI2_WCLK_N); - aic3262_write(codec, ASI2_WCLK_N, (value & 0x7f)); + value = snd_soc_read(codec, ASI2_WCLK_N); + snd_soc_write(codec, ASI2_WCLK_N, (value & 0x7f)); } dacregoffset = ASI2_DAC_OUT_CNTL; adcregoffset = ASI2_ADC_INPUT_CNTL; @@ -2142,11 +2019,11 @@ static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream, * the Bit Clock Divider and Word Clock Dividers */ if (aic3262->asiCtxt[2].master == 1) { - value = aic3262_read(codec, ASI3_BCLK_N); - aic3262_write(codec, ASI3_BCLK_N, (value & 0x7f)); + value = snd_soc_read(codec, ASI3_BCLK_N); + snd_soc_write(codec, ASI3_BCLK_N, (value & 0x7f)); - value = aic3262_read(codec, ASI3_WCLK_N); - aic3262_write(codec, ASI3_WCLK_N, (value & 0x7f)); + value = snd_soc_read(codec, ASI3_WCLK_N); + snd_soc_write(codec, ASI3_WCLK_N, (value & 0x7f)); } dacregoffset = ASI3_DAC_OUT_CNTL; adcregoffset = ASI3_ADC_INPUT_CNTL; @@ -2162,8 +2039,8 @@ static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream, DBG(KERN_INFO "#%s: Disabling Pg %d Reg %d DAC Inputs ..\n", __func__, (dacregoffset/128), (dacregoffset % 128)); - dacpath = aic3262_read(codec, dacregoffset); - aic3262_write(codec, dacregoffset, (dacpath & ~(BIT6 | BIT4))); + dacpath = snd_soc_read(codec, dacregoffset); + snd_soc_write(codec, dacregoffset, (dacpath & ~(BIT6 | BIT4))); aic3262->asiCtxt[dai->id - 1].playback_mode = 0; } else { @@ -2171,8 +2048,8 @@ static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream, DBG(KERN_INFO "#%s: Disabling Pg %d Reg %d for ADC Inputs..\n", __func__, (adcregoffset/128), (adcregoffset % 128)); - adcpath = aic3262_read(codec, adcregoffset); - aic3262_write(codec, adcregoffset, + adcpath = snd_soc_read(codec, adcregoffset); + snd_soc_write(codec, adcregoffset, (adcpath & ~(BIT2 | BIT1 | BIT0))); aic3262->asiCtxt[dai->id - 1].capture_mode = 0; @@ -2184,21 +2061,21 @@ static int aic3262_multi_i2s_hw_free(struct snd_pcm_substream *substream, switch (dai->id) { case 1: if (aic3262->asiCtxt[0].pcm_format == SND_SOC_DAIFMT_DSP_B) { - aic3262_write(codec, ASI1_LCH_OFFSET, 0x00); - aic3262_write(codec, ASI1_RCH_OFFSET, 0x00); + snd_soc_write(codec, ASI1_LCH_OFFSET, 0x00); + snd_soc_write(codec, ASI1_RCH_OFFSET, 0x00); } break; case 2: if (aic3262->asiCtxt[1].pcm_format == SND_SOC_DAIFMT_DSP_B) { - aic3262_write(codec, ASI2_LCH_OFFSET, 0x00); - aic3262_write(codec, ASI2_RCH_OFFSET, 0x00); + snd_soc_write(codec, ASI2_LCH_OFFSET, 0x00); + snd_soc_write(codec, ASI2_RCH_OFFSET, 0x00); } break; case 3: if (aic3262->asiCtxt[2].pcm_format == SND_SOC_DAIFMT_DSP_B) { - aic3262_write(codec, ASI3_LCH_OFFSET, 0x00); - aic3262_write(codec, ASI3_RCH_OFFSET, 0x00); + snd_soc_write(codec, ASI3_LCH_OFFSET, 0x00); + snd_soc_write(codec, ASI3_RCH_OFFSET, 0x00); } break; } @@ -2230,7 +2107,7 @@ struct snd_soc_dai_ops aic3262_multi_i2s_dai_ops = { .set_fmt = aic3262_multi_i2s_set_dai_fmt, .set_pll = aic3262_multi_i2s_set_dai_pll, .set_sysclk = aic3262_multi_i2s_set_dai_sysclk, - .hw_free = aic3262_multi_i2s_hw_free, + .shutdown = aic3262_multi_i2s_shutdown, }; @@ -2528,8 +2405,8 @@ static const struct aic3262_configs aic3262_reg_init[] = { {0, LMIC_PGA_MIN, 0x40}, /*CM to LMICPGA-M*/ {0, RMIC_PGA_PIN, 0x55}, /*IN1_R select - - 10k -RMIC_PGA_P*/ {0, RMIC_PGA_MIN, 0x40}, /*CM to RMICPGA_M*/ - {0, (PAGE_1 + 0x79), 33}, /*LMIC-PGA-POWERUP-DELAY - default*/ - {0, (PAGE_1 + 0x7a), 1}, /*FIXMELATER*/ + {0, MIC_PWR_DLY , 33}, /*LMIC-PGA-POWERUP-DELAY - default*/ + {0, REF_PWR_DLY, 1}, /*FIXMELATER*/ {0, ADC_CHANNEL_POW, 0xc2}, /*ladc, radc ON , SOFT STEP disabled*/ @@ -2576,55 +2453,394 @@ static const struct aic3262_configs aic3262_reg_init[] = { static int reg_init_size = sizeof(aic3262_reg_init) / sizeof(struct aic3262_configs); -static const struct snd_kcontrol_new aic3262_snd_controls2[] = { +static const unsigned int adc_ma_tlv[] = { +TLV_DB_RANGE_HEAD(4), + 0, 29, TLV_DB_SCALE_ITEM(-1450, 500, 0), + 30, 35, TLV_DB_SCALE_ITEM(-2060, 1000, 0), + 36, 38, TLV_DB_SCALE_ITEM(-2660, 2000, 0), + 39, 40, TLV_DB_SCALE_ITEM(-3610, 5000, 0), +}; +static const DECLARE_TLV_DB_SCALE(lo_hp_tlv, -7830, 50, 0); + +static const struct snd_kcontrol_new mal_pga_mixer_controls[] = { + SOC_DAPM_SINGLE("IN1L Switch", MA_CNTL, 5, 1, 0), + SOC_DAPM_SINGLE_TLV("Left MicPGA Volume", LADC_PGA_MAL_VOL, 0, + 0x3f, 1, adc_ma_tlv), - SOC_DOUBLE_R("IN1 MPGA Route", LMIC_PGA_PIN, RMIC_PGA_PIN, 6, 3, 0), - SOC_DOUBLE_R("IN2 MPGA Route", LMIC_PGA_PIN, RMIC_PGA_PIN, 4, 3, 0), - SOC_DOUBLE_R("IN3 MPGA Route", LMIC_PGA_PIN, RMIC_PGA_PIN, 2, 3, 0), - SOC_DOUBLE_R("IN4 MPGA Route", - LMIC_PGA_PM_IN4, RMIC_PGA_PM_IN4, 5, 1, 0), }; + +static const struct snd_kcontrol_new mar_pga_mixer_controls[] = { + SOC_DAPM_SINGLE("IN1R Switch", MA_CNTL, 4, 1, 0), + SOC_DAPM_SINGLE_TLV("Right MicPGA Volume", RADC_PGA_MAR_VOL, 0, + 0x3f, 1, adc_ma_tlv), +}; + +/* Left HPL Mixer */ +static const struct snd_kcontrol_new hpl_output_mixer_controls[] = { + SOC_DAPM_SINGLE("MAL Switch", HP_AMP_CNTL_R1, 7, 1, 0), + SOC_DAPM_SINGLE("LDAC Switch", HP_AMP_CNTL_R1, 5, 1, 0), + SOC_DAPM_SINGLE_TLV("LOL-B1 Volume", HP_AMP_CNTL_R2, 0, + 0x7f, 1, lo_hp_tlv), +}; + +/* Right HPR Mixer */ +static const struct snd_kcontrol_new hpr_output_mixer_controls[] = { + SOC_DAPM_SINGLE_TLV("LOR-B1 Volume", HP_AMP_CNTL_R3, 0, + 0x7f, 1, lo_hp_tlv), + SOC_DAPM_SINGLE("LDAC Switch", HP_AMP_CNTL_R1, 2, 1, 0), + SOC_DAPM_SINGLE("RDAC Switch", HP_AMP_CNTL_R1, 4, 1, 0), + SOC_DAPM_SINGLE("MAR Switch", HP_AMP_CNTL_R1, 6, 1, 0), +}; + +/* Left LOL Mixer */ +static const struct snd_kcontrol_new lol_output_mixer_controls[] = { + SOC_DAPM_SINGLE("MAL Switch", LINE_AMP_CNTL_R2, 7, 1, 0), + SOC_DAPM_SINGLE("IN1L-B Switch", LINE_AMP_CNTL_R2, 3, 1,0), + SOC_DAPM_SINGLE("LDAC Switch", LINE_AMP_CNTL_R1, 7, 1, 0), + SOC_DAPM_SINGLE("RDAC Switch", LINE_AMP_CNTL_R1, 5, 1, 0), +}; + +/* Right LOR Mixer */ +static const struct snd_kcontrol_new lor_output_mixer_controls[] = { + SOC_DAPM_SINGLE("LOL Switch", LINE_AMP_CNTL_R1, 2, 1, 0), + SOC_DAPM_SINGLE("RDAC Switch", LINE_AMP_CNTL_R1, 6, 1, 0), + SOC_DAPM_SINGLE("MAR Switch", LINE_AMP_CNTL_R2, 6, 1, 0), + SOC_DAPM_SINGLE("IN1R-B Switch", LINE_AMP_CNTL_R2, 0, 1,0), +}; + +/* Left SPKL Mixer */ +static const struct snd_kcontrol_new spkl_output_mixer_controls[] = { + SOC_DAPM_SINGLE("MAL Switch", SPK_AMP_CNTL_R1, 7, 1, 0), + SOC_DAPM_SINGLE_TLV("LOL Volume", SPK_AMP_CNTL_R2, 0, 0x7f,1, + lo_hp_tlv), + SOC_DAPM_SINGLE("SPR_IN Switch", SPK_AMP_CNTL_R1, 2, 1, 0), +}; + +/* Right SPKR Mixer */ +static const struct snd_kcontrol_new spkr_output_mixer_controls[] = { + SOC_DAPM_SINGLE_TLV("LOR Volume", SPK_AMP_CNTL_R3, 0, 0x7f, 1, + lo_hp_tlv), + SOC_DAPM_SINGLE("MAR Switch", SPK_AMP_CNTL_R1, 6, 1, 0), +}; + +/* REC Mixer */ +static const struct snd_kcontrol_new rec_output_mixer_controls[] = { + SOC_DAPM_SINGLE_TLV("LOL-B2 Volume", RAMP_CNTL_R1, 0, 0x7f,1, + lo_hp_tlv), + SOC_DAPM_SINGLE_TLV("IN1L Volume", IN1L_SEL_RM, 0, 0x7f, 1, lo_hp_tlv), + SOC_DAPM_SINGLE_TLV("IN1R Volume", IN1R_SEL_RM, 0, 0x7f, 1, lo_hp_tlv), + SOC_DAPM_SINGLE_TLV("LOR-B2 Volume", RAMP_CNTL_R2, 0,0x7f, 1,lo_hp_tlv), +}; + +/* Left Input Mixer */ +static const struct snd_kcontrol_new left_input_mixer_controls[] = { + SOC_DAPM_SINGLE("IN1L Switch", LMIC_PGA_PIN, 6, 1, 0), + SOC_DAPM_SINGLE("IN2L Switch", LMIC_PGA_PIN, 4, 1, 0), + SOC_DAPM_SINGLE("IN3L Switch", LMIC_PGA_PIN, 2, 1, 0), + SOC_DAPM_SINGLE("IN4L Switch", LMIC_PGA_PM_IN4, 5, 1, 0), + SOC_DAPM_SINGLE("IN1R Switch", LMIC_PGA_PIN, 0, 1, 0), + SOC_DAPM_SINGLE("IN2R Switch", LMIC_PGA_MIN, 4, 1, 0), + SOC_DAPM_SINGLE("IN3R Switch", LMIC_PGA_MIN, 2, 1, 0), + SOC_DAPM_SINGLE("IN4R Switch", LMIC_PGA_PM_IN4, 4, 1, 0), + SOC_DAPM_SINGLE("CM2L Switch", LMIC_PGA_MIN, 0, 1, 0), + SOC_DAPM_SINGLE("CM1L Switch", LMIC_PGA_MIN, 6, 1, 0), +}; + +/* Right Input Mixer */ +static const struct snd_kcontrol_new right_input_mixer_controls[] = { + SOC_DAPM_SINGLE("IN1R Switch", RMIC_PGA_PIN, 6, 1, 0), + SOC_DAPM_SINGLE("IN2R Switch", RMIC_PGA_PIN, 4, 1, 0), + SOC_DAPM_SINGLE("IN3R Switch", RMIC_PGA_PIN, 2, 1, 0), + SOC_DAPM_SINGLE("IN4R Switch", RMIC_PGA_PM_IN4, 5, 1, 0), + SOC_DAPM_SINGLE("IN2L Switch", RMIC_PGA_PIN, 0, 1, 0), + SOC_DAPM_SINGLE("IN1L Switch", RMIC_PGA_MIN, 4, 1, 0), + SOC_DAPM_SINGLE("IN3L Switch", RMIC_PGA_MIN, 2, 1, 0), + SOC_DAPM_SINGLE("IN4L Switch", RMIC_PGA_PM_IN4, 4, 1, 0), + SOC_DAPM_SINGLE("CM1R Switch", RMIC_PGA_MIN, 6, 1, 0), + SOC_DAPM_SINGLE("CM2R Switch", RMIC_PGA_MIN, 0, 1, 0), +}; + + +static const char *asi1lin_text[] = { + "Off", "ASI1 Left In","ASI1 Right In","ASI1 MonoMix In" +}; + +SOC_ENUM_SINGLE_DECL(asi1lin_enum, ASI1_DAC_OUT_CNTL, 6, asi1lin_text); + +static const struct snd_kcontrol_new asi1lin_control = + SOC_DAPM_ENUM("ASI1LIN Route", asi1lin_enum); + + +static const char *asi1rin_text[] = { + "Off", "ASI1 Right In","ASI1 Left In","ASI1 MonoMix In" +}; + +SOC_ENUM_SINGLE_DECL(asi1rin_enum, ASI1_DAC_OUT_CNTL, 4, asi1rin_text); + +static const struct snd_kcontrol_new asi1rin_control = + SOC_DAPM_ENUM("ASI1RIN Route", asi1rin_enum); + +static const char *asi2lin_text[] = { + "Off", "ASI2 Left In","ASI2 Right In","ASI2 MonoMix In" +}; + +SOC_ENUM_SINGLE_DECL(asi2lin_enum, ASI2_DAC_OUT_CNTL, 6, asi2lin_text); +static const struct snd_kcontrol_new asi2lin_control = + SOC_DAPM_ENUM("ASI2LIN Route", asi2lin_enum); + +static const char *asi2rin_text[] = { + "Off", "ASI2 Right In","ASI2 Left In","ASI2 MonoMix In" +}; + + +SOC_ENUM_SINGLE_DECL(asi2rin_enum, ASI2_DAC_OUT_CNTL, 4, asi2rin_text); + +static const struct snd_kcontrol_new asi2rin_control = + SOC_DAPM_ENUM("ASI2RIN Route", asi2rin_enum); + +static const char *asi3lin_text[] = { + "Off", "ASI3 Left In","ASI3 Right In","ASI3 MonoMix In" +}; + + +SOC_ENUM_SINGLE_DECL(asi3lin_enum, ASI3_DAC_OUT_CNTL, 6, asi3lin_text); +static const struct snd_kcontrol_new asi3lin_control = + SOC_DAPM_ENUM("ASI3LIN Route", asi3lin_enum); + + +static const char *asi3rin_text[] = { + "Off", "ASI3 Right In","ASI3 Left In","ASI3 MonoMix In" +}; + + +SOC_ENUM_SINGLE_DECL(asi3rin_enum, ASI3_DAC_OUT_CNTL, 4, asi3rin_text); +static const struct snd_kcontrol_new asi3rin_control = + SOC_DAPM_ENUM("ASI3RIN Route", asi3rin_enum); + + +static const char *dacminidspin1_text[] = { + "ASI1 In", "ASI2 In","ASI3 In","ADC MiniDSP Out" +}; + +SOC_ENUM_SINGLE_DECL(dacminidspin1_enum, MINIDSP_PORT_CNTL_REG, 4, dacminidspin1_text); +static const struct snd_kcontrol_new dacminidspin1_control = + SOC_DAPM_ENUM("DAC MiniDSP IN1 Route", dacminidspin1_enum); + +static const char *asi1out_text[] = { + "Off", + "ASI1 Out", + "ASI1In Bypass", + "ASI2In Bypass", + "ASI3In Bypass", +}; +SOC_ENUM_SINGLE_DECL(asi1out_enum, ASI1_ADC_INPUT_CNTL, 0, asi1out_text); +static const struct snd_kcontrol_new asi1out_control = + SOC_DAPM_ENUM("ASI1OUT Route", asi1out_enum); + +static const char *asi2out_text[] = { + "Off", + "ASI1 Out", + "ASI1In Bypass", + "ASI2In Bypass", + "ASI3In Bypass", + "ASI2 Out", +}; +SOC_ENUM_SINGLE_DECL(asi2out_enum, ASI2_ADC_INPUT_CNTL, 0, asi2out_text); +static const struct snd_kcontrol_new asi2out_control = + SOC_DAPM_ENUM("ASI2OUT Route", asi2out_enum); +static const char *asi3out_text[] = { + "Off", + "ASI1 Out", + "ASI1In Bypass", + "ASI2In Bypass", + "ASI3In Bypass", + "ASI3 Out", +}; +SOC_ENUM_SINGLE_DECL(asi3out_enum, ASI3_ADC_INPUT_CNTL, 0, asi3out_text); +static const struct snd_kcontrol_new asi3out_control = + SOC_DAPM_ENUM("ASI3OUT Route", asi3out_enum); + +static const char *asi1bclk_text[] = { + "DAC_CLK", + "DAC_MOD_CLK", + "ADC_CLK", + "ADC_MOD_CLK", +}; + +static int aic326x_hp_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + return 0; +} +static int pll_power_on_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + if (event == SND_SOC_DAPM_POST_PMU) + { + mdelay(10); + } + return 0; +} static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = { - SND_SOC_DAPM_DAC("Left DAC", "Playback", PASI_DAC_DP_SETUP, 7, 0), - SND_SOC_DAPM_DAC("Right DAC", "Playback", PASI_DAC_DP_SETUP, 6, 0), + /* TODO: Can we switch these off ? */ + SND_SOC_DAPM_AIF_IN("ASI1IN", "ASI1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("ASI2IN", "ASI2 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("ASI3IN", "ASI3 Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_DAC("Left DAC", NULL, PASI_DAC_DP_SETUP, 7, 0), + SND_SOC_DAPM_DAC("Right DAC", NULL, PASI_DAC_DP_SETUP, 6, 0), + - SND_SOC_DAPM_SWITCH_N("LDAC_2_HPL", HP_AMP_CNTL_R1, 5, 0), - SND_SOC_DAPM_SWITCH_N("RDAC_2_HPR", HP_AMP_CNTL_R1, 4, 0), + /* dapm widget (path domain) for HPL Output Mixer */ + SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0, + &hpl_output_mixer_controls[0], + ARRAY_SIZE(hpl_output_mixer_controls)), - SND_SOC_DAPM_PGA("HPL Driver", HP_AMP_CNTL_R1, 1, 0, NULL, 0), - SND_SOC_DAPM_PGA("HPR Driver", HP_AMP_CNTL_R1, 0, 0, NULL, 0), + /* dapm widget (path domain) for HPR Output Mixer */ + SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0, + &hpr_output_mixer_controls[0], + ARRAY_SIZE(hpr_output_mixer_controls)), - SND_SOC_DAPM_SWITCH_N("LDAC_2_LOL", LINE_AMP_CNTL_R1, 7, 0), - SND_SOC_DAPM_SWITCH_N("RDAC_2_LOR", LINE_AMP_CNTL_R1, 6, 0), + + SND_SOC_DAPM_PGA_E("HPL Driver", HP_AMP_CNTL_R1, 1, 0, NULL, 0, + aic326x_hp_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_PGA_E("HPR Driver", HP_AMP_CNTL_R1, 0, 0, NULL, 0, + aic326x_hp_event, SND_SOC_DAPM_POST_PMU), + + + /* dapm widget (path domain) for LOL Output Mixer */ + SND_SOC_DAPM_MIXER("LOL Output Mixer", SND_SOC_NOPM, 0, 0, + &lol_output_mixer_controls[0], + ARRAY_SIZE(lol_output_mixer_controls)), + + /* dapm widget (path domain) for LOR Output Mixer mixer */ + SND_SOC_DAPM_MIXER("LOR Output Mixer", SND_SOC_NOPM, 0, 0, + &lor_output_mixer_controls[0], + ARRAY_SIZE(lor_output_mixer_controls)), SND_SOC_DAPM_PGA("LOL Driver", LINE_AMP_CNTL_R1, 1, 0, NULL, 0), SND_SOC_DAPM_PGA("LOR Driver", LINE_AMP_CNTL_R1, 0, 0, NULL, 0), + + /* dapm widget (path domain) for SPKL Output Mixer */ + SND_SOC_DAPM_MIXER("SPKL Output Mixer", SND_SOC_NOPM, 0, 0, + &spkl_output_mixer_controls[0], + ARRAY_SIZE(spkl_output_mixer_controls)), + + /* dapm widget (path domain) for SPKR Output Mixer */ + SND_SOC_DAPM_MIXER("SPKR Output Mixer", SND_SOC_NOPM, 0, 0, + &spkr_output_mixer_controls[0], + ARRAY_SIZE(spkr_output_mixer_controls)), + SND_SOC_DAPM_PGA("SPKL Driver", SPK_AMP_CNTL_R1, 1, 0, NULL, 0), SND_SOC_DAPM_PGA("SPKR Driver", SPK_AMP_CNTL_R1, 0, 0, NULL, 0), - SND_SOC_DAPM_PGA("RECL Driver", REC_AMP_CNTL_R5, 7, 0, NULL, 0), - SND_SOC_DAPM_PGA("RECR Driver", REC_AMP_CNTL_R5, 6, 0, NULL, 0), - - SND_SOC_DAPM_ADC("Left ADC", "Capture", ADC_CHANNEL_POW, 7, 0), - SND_SOC_DAPM_ADC("Right ADC", "Capture", ADC_CHANNEL_POW, 6, 0), - - SND_SOC_DAPM_SWITCH("IN1L Route", - LMIC_PGA_PIN, 6, 0, &aic3262_snd_controls2[0]), - SND_SOC_DAPM_SWITCH("IN2L Route", - LMIC_PGA_PIN, 4, 0, &aic3262_snd_controls2[1]), - SND_SOC_DAPM_SWITCH("IN3L Route", - LMIC_PGA_PIN, 2, 0, &aic3262_snd_controls2[2]), - SND_SOC_DAPM_SWITCH("IN4L Route", - LMIC_PGA_PM_IN4, 5, 0, &aic3262_snd_controls2[3]), - SND_SOC_DAPM_SWITCH("IN1R Route", - RMIC_PGA_PIN, 6, 0, &aic3262_snd_controls2[4]), - SND_SOC_DAPM_SWITCH("IN2R Route", - RMIC_PGA_PIN, 4, 0, &aic3262_snd_controls2[5]), - SND_SOC_DAPM_SWITCH("IN3R Route", - RMIC_PGA_PIN, 2, 0, &aic3262_snd_controls2[6]), - SND_SOC_DAPM_SWITCH("IN4R Route", - RMIC_PGA_PM_IN4, 5, 0, &aic3262_snd_controls2[7]), + + /* dapm widget (path domain) for SPKR Output Mixer */ + SND_SOC_DAPM_MIXER("REC Output Mixer", SND_SOC_NOPM, 0, 0, + &rec_output_mixer_controls[0], + ARRAY_SIZE(rec_output_mixer_controls)), + + SND_SOC_DAPM_PGA("RECP Driver", REC_AMP_CNTL_R5, 7, 0, NULL, 0), + SND_SOC_DAPM_PGA("RECM Driver", REC_AMP_CNTL_R5, 6, 0, NULL, 0), + + + SND_SOC_DAPM_MUX("ASI1LIN Route", + SND_SOC_NOPM, 0, 0, &asi1lin_control), + SND_SOC_DAPM_MUX("ASI1RIN Route", + SND_SOC_NOPM, 0, 0, &asi1rin_control), + SND_SOC_DAPM_MUX("ASI2LIN Route", + SND_SOC_NOPM, 0, 0, &asi2lin_control), + SND_SOC_DAPM_MUX("ASI2RIN Route", + SND_SOC_NOPM, 0, 0, &asi2rin_control), + SND_SOC_DAPM_MUX("ASI3LIN Route", + SND_SOC_NOPM, 0, 0, &asi3lin_control), + SND_SOC_DAPM_MUX("ASI3RIN Route", + SND_SOC_NOPM, 0, 0, &asi3rin_control), + + SND_SOC_DAPM_PGA("ASI1LIN", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI1RIN", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI2LIN", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI2RIN", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI3LIN", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI3RIN", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_PGA("ASI1LOUT", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI1ROUT", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI2LOUT", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI2ROUT", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI3LOUT", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI3ROUT", SND_SOC_NOPM, 0, 0, NULL, 0), + + SND_SOC_DAPM_PGA("ASI1MonoMixIN", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI2MonoMixIN", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI3MonoMixIN", SND_SOC_NOPM, 0, 0, NULL, 0), + /* TODO: Can we switch the ASIxIN off? */ + SND_SOC_DAPM_PGA("ASI1IN Port", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI2IN Port", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ASI3IN Port", SND_SOC_NOPM, 0, 0, NULL, 0), + + + SND_SOC_DAPM_MUX("DAC MiniDSP IN1 Route", + SND_SOC_NOPM, 0, 0, &dacminidspin1_control), + + + SND_SOC_DAPM_PGA("CM", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("CM1L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("CM2L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("CM1R", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("CM2R", SND_SOC_NOPM, 0, 0, NULL, 0), + + /* TODO: Can we switch these off ? */ + SND_SOC_DAPM_AIF_OUT("ASI1OUT","ASI1 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("ASI2OUT", "ASI2 Capture",0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("ASI3OUT", "ASI3 Capture",0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_MUX("ASI1OUT Route", + SND_SOC_NOPM, 0, 0, &asi1out_control), + SND_SOC_DAPM_MUX("ASI2OUT Route", + SND_SOC_NOPM, 0, 0, &asi2out_control), + SND_SOC_DAPM_MUX("ASI3OUT Route", + SND_SOC_NOPM, 0, 0, &asi3out_control), + + /* TODO: Will be used during MINIDSP programming */ + /* TODO: Can we switch them off? */ + SND_SOC_DAPM_PGA("ADC MiniDSP OUT1", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC MiniDSP OUT2", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("ADC MiniDSP OUT3", SND_SOC_NOPM, 0, 0, NULL, 0), + + + SND_SOC_DAPM_ADC("Left ADC", NULL, ADC_CHANNEL_POW, 7, 0), + SND_SOC_DAPM_ADC("Right ADC", NULL, ADC_CHANNEL_POW, 6, 0), + + + SND_SOC_DAPM_PGA("Left MicPGA",MICL_PGA, 7, 1, NULL, 0), + SND_SOC_DAPM_PGA("Right MicPGA",MICR_PGA, 7, 1, NULL, 0), + + SND_SOC_DAPM_PGA("MAL PGA", MA_CNTL, 3, 0, NULL, 0), + SND_SOC_DAPM_PGA("MAR PGA", MA_CNTL, 2, 0, NULL, 0), + + + /* dapm widget for MAL PGA Mixer*/ + SND_SOC_DAPM_MIXER("MAL PGA Mixer", SND_SOC_NOPM, 0, 0, + &mal_pga_mixer_controls[0], + ARRAY_SIZE(mal_pga_mixer_controls)), + + /* dapm widget for MAR PGA Mixer*/ + SND_SOC_DAPM_MIXER("MAR PGA Mixer", SND_SOC_NOPM, 0, 0, + &mar_pga_mixer_controls[0], + ARRAY_SIZE(mar_pga_mixer_controls)), + + /* dapm widget for Left Input Mixer*/ + SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0, + &left_input_mixer_controls[0], + ARRAY_SIZE(left_input_mixer_controls)), + + /* dapm widget for Right Input Mixer*/ + SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0, + &right_input_mixer_controls[0], + ARRAY_SIZE(right_input_mixer_controls)), + SND_SOC_DAPM_OUTPUT("HPL"), SND_SOC_DAPM_OUTPUT("HPR"), @@ -2632,60 +2848,282 @@ static const struct snd_soc_dapm_widget aic3262_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("LOR"), SND_SOC_DAPM_OUTPUT("SPKL"), SND_SOC_DAPM_OUTPUT("SPKR"), - SND_SOC_DAPM_OUTPUT("RECL"), - SND_SOC_DAPM_OUTPUT("RECR"), + SND_SOC_DAPM_OUTPUT("RECP"), + SND_SOC_DAPM_OUTPUT("RECM"), SND_SOC_DAPM_INPUT("IN1L"), SND_SOC_DAPM_INPUT("IN2L"), SND_SOC_DAPM_INPUT("IN3L"), SND_SOC_DAPM_INPUT("IN4L"), - SND_SOC_DAPM_INPUT("IN1R"), SND_SOC_DAPM_INPUT("IN2R"), SND_SOC_DAPM_INPUT("IN3R"), SND_SOC_DAPM_INPUT("IN4R"), + + + SND_SOC_DAPM_MICBIAS("Mic Bias Ext", MIC_BIAS_CNTL, 6, 0), + SND_SOC_DAPM_MICBIAS("Mic Bias Int", MIC_BIAS_CNTL, 2, 0), + SND_SOC_DAPM_SUPPLY("PLLCLK",PLL_PR_POW_REG,7,0,pll_power_on_event, + SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_SUPPLY("NDAC",NDAC_DIV_POW_REG,7,0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MDAC",MDAC_DIV_POW_REG,7,0, NULL, 0), + SND_SOC_DAPM_SUPPLY("NADC",NADC_DIV_POW_REG,7,0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MADC",MADC_DIV_POW_REG,7,0, NULL, 0), + + }; -static const struct snd_soc_dapm_route aic3262_dapm_routes[] = { - {"LDAC_2_HPL", NULL, "Left DAC"}, - {"HPL Driver", NULL, "LDAC_2_HPL"}, - {"HPL", NULL, "HPL Driver"}, - {"RDAC_2_HPR", NULL, "Right DAC"}, - {"HPR Driver", NULL, "RDAC_2_HPR"}, - {"HPR", NULL, "HPR Driver"}, - - {"LDAC_2_LOL", NULL, "Left DAC"}, - {"LOL Driver", NULL, "LDAC_2_LOL"}, - {"LOL", NULL, "LOL Driver"}, - {"RDAC_2_LOR", NULL, "Right DAC"}, - {"LOR Driver", NULL, "RDAC_2_LOR"}, - {"LOR", NULL, "LOR Driver"}, - - {"SPKL Driver", NULL, "LOL"}, - {"SPKL", NULL, "SPKL Driver"}, - {"SPKR Driver", NULL, "LOR"}, - {"SPKR", NULL, "SPKR Driver"}, - - {"RECL Driver", NULL, "LOL"}, - {"RECL", NULL, "RECL Driver"}, - {"RECR Driver", NULL, "LOR"}, - {"RECR", NULL, "RECR Driver"}, - - {"Left ADC", "IN1L Route", "IN1L"}, - {"Left ADC", "IN2L Route", "IN2L"}, - {"Left ADC", "IN3L Route", "IN3L"}, - {"Left ADC", "IN4L Route", "IN4L"}, - - {"Right ADC", "IN1R Route", "IN1R"}, - {"Right ADC", "IN2R Route", "IN2R"}, - {"Right ADC", "IN3R Route", "IN3R"}, - {"Right ADC", "IN4R Route", "IN4R"}, -/* - {"LOL Driver", NULL, "IN1L"}, - {"LOR Driver", NULL, "IN1R"}, -*/ +static const struct snd_soc_dapm_route aic3262_dapm_routes[] ={ +/* TODO: Do we need only DACCLK for ASIIN's and ADCCLK for ASIOUT??? */ +/* Clock portion */ + {"NDAC", NULL, "PLLCLK"}, + {"MDAC", NULL, "NDAC"}, + {"ASI1IN", NULL , "NDAC"}, + {"ASI1IN", NULL , "NADC"}, + {"ASI1IN", NULL , "MDAC"}, + {"ASI1IN", NULL , "MADC"}, + + {"ASI1OUT", NULL , "NDAC"}, + {"ASI1OUT", NULL , "NADC"}, + {"ASI1OUT", NULL , "MDAC"}, + {"ASI1OUT", NULL , "MADC"}, + +#ifdef AIC3262_ASI1_MASTER + {"ASI1IN", NULL , "ASI1_BCLK"}, + {"ASI1OUT", NULL , "ASI1_BCLK"}, + {"ASI1IN", NULL , "ASI1_WCLK"}, + {"ASI1OUT", NULL , "ASI1_WCLK"}, +#else + +#endif + {"ASI2IN", NULL , "NDAC"}, + {"ASI2IN", NULL , "NADC"}, + {"ASI2IN", NULL , "MDAC"}, + {"ASI2IN", NULL , "MADC"}, + + {"ASI2OUT", NULL , "NDAC"}, + {"ASI2OUT", NULL , "NADC"}, + {"ASI2OUT", NULL , "MDAC"}, + {"ASI2OUT", NULL , "MADC"}, + +#ifdef AIC3262_ASI2_MASTER + {"ASI2IN", NULL , "ASI2_BCLK"}, + {"ASI2OUT", NULL , "ASI2_BCLK"}, + {"ASI2IN", NULL , "ASI2_WCLK"}, + {"ASI2OUT", NULL , "ASI2_WCLK"}, +#else + +#endif + {"ASI3IN", NULL , "NDAC"}, + {"ASI3IN", NULL , "NADC"}, + {"ASI3IN", NULL , "MDAC"}, + {"ASI3IN", NULL , "MADC"}, + + {"ASI3OUT", NULL , "NDAC"}, + {"ASI3OUT", NULL , "NADC"}, + {"ASI3OUT", NULL , "MDAC"}, + {"ASI3OUT", NULL , "MADC"}, + +#ifdef AIC3262_ASI3_MASTER + {"ASI3IN", NULL , "ASI3_BCLK"}, + {"ASI3OUT", NULL , "ASI3_BCLK"}, + {"ASI3IN", NULL , "ASI3_WCLK"}, + {"ASI3OUT", NULL , "ASI3_WCLK"}, +#else +#endif +/* Playback (DAC) Portion */ + {"HPL Output Mixer","LDAC Switch","Left DAC"}, + {"HPL Output Mixer","MAL Switch","MAL PGA"}, + {"HPL Output Mixer","LOL-B1 Volume","LOL"}, + + {"HPR Output Mixer","LOR-B1 Volume","LOR"}, + {"HPR Output Mixer","LDAC Switch","Left DAC"}, + {"HPR Output Mixer","RDAC Switch","Right DAC"}, + {"HPR Output Mixer","MAR Switch","MAR PGA"}, + + {"HPL Driver",NULL,"HPL Output Mixer"}, + {"HPR Driver",NULL,"HPR Output Mixer"}, + + {"HPL",NULL,"HPL Driver"}, + {"HPR",NULL,"HPR Driver"}, + + {"LOL Output Mixer","MAL Switch","MAL PGA"}, + {"LOL Output Mixer","IN1L-B Switch","IN1L"}, + {"LOL Output Mixer","LDAC Switch","Left DAC"}, + {"LOL Output Mixer","RDAC Switch","Right DAC"}, + + {"LOR Output Mixer","LOL Switch","LOL"}, + {"LOR Output Mixer","RDAC Switch","Right DAC"}, + {"LOR Output Mixer","MAR Switch","MAR PGA"}, + {"LOR Output Mixer","IN1R-B Switch","IN1R"}, + + {"LOL Driver",NULL,"LOL Output Mixer"}, + {"LOR Driver",NULL,"LOR Output Mixer"}, + + {"LOL",NULL,"LOL Driver"}, + {"LOR",NULL,"LOR Driver"}, + + {"REC Output Mixer","LOL-B2 Volume","LOL"}, + {"REC Output Mixer","IN1L Volume","IN1L"}, + {"REC Output Mixer","IN1R Volume","IN1R"}, + {"REC Output Mixer","LOR-B2 Volume","LOR"}, + + {"RECP Driver",NULL,"REC Output Mixer"}, + {"RECM Driver",NULL,"REC Output Mixer"}, + + {"RECP",NULL,"RECP Driver"}, + {"RECM",NULL,"RECM Driver"}, + + {"SPKL Output Mixer","MAL Switch","MAL PGA"}, + {"SPKL Output Mixer","LOL Volume","LOL"}, + {"SPKL Output Mixer","SPR_IN Switch","SPKR Output Mixer"}, + + {"SPKR Output Mixer", "LOR Volume","LOR"}, + {"SPKR Output Mixer", "MAR Switch","MAR PGA"}, + + + {"SPKL Driver",NULL,"SPKL Output Mixer"}, + {"SPKR Driver",NULL,"SPKR Output Mixer"}, + + {"SPKL",NULL,"SPKL Driver"}, + {"SPKR",NULL,"SPKR Driver"}, +/* ASI Input routing */ + {"ASI1LIN", NULL, "ASI1IN"}, + {"ASI1RIN", NULL, "ASI1IN"}, + {"ASI2LIN", NULL, "ASI2IN"}, + {"ASI2RIN", NULL, "ASI2IN"}, + {"ASI3LIN", NULL, "ASI3IN"}, + {"ASI3RIN", NULL, "ASI3IN"}, + + {"ASI1MonoMixIN", NULL, "ASI1IN"}, + {"ASI2MonoMixIN", NULL, "ASI2IN"}, + {"ASI3MonoMixIN", NULL, "ASI3IN"}, + + {"ASI1LIN Route","ASI1 Left In","ASI1LIN"}, + {"ASI1LIN Route","ASI1 Right In","ASI1RIN"}, + {"ASI1LIN Route","ASI1 MonoMix In","ASI1MonoMixIN"}, + + {"ASI1RIN Route", "ASI1 Right In","ASI1RIN"}, + {"ASI1RIN Route","ASI1 Left In","ASI1LIN"}, + {"ASI1RIN Route","ASI1 MonoMix In","ASI1MonoMixIN"}, + + + {"ASI2LIN Route","ASI2 Left In","ASI2LIN"}, + {"ASI2LIN Route","ASI2 Right In","ASI2RIN"}, + {"ASI2LIN Route","ASI2 MonoMix In","ASI2MonoMixIN"}, + + {"ASI2RIN Route","ASI2 Right In","ASI2RIN"}, + {"ASI2RIN Route","ASI2 Left In","ASI2LIN"}, + {"ASI2RIN Route","ASI2 MonoMix In","ASI2MonoMixIN"}, + + + {"ASI3LIN Route","ASI3 Left In","ASI3LIN"}, + {"ASI3LIN Route","ASI3 Right In","ASI3RIN"}, + {"ASI3LIN Route","ASI3 MonoMix In","ASI3MonoMixIN"}, + + {"ASI3RIN Route","ASI3 Right In","ASI3RIN"}, + {"ASI3RIN Route","ASI3 Left In","ASI3LIN"}, + {"ASI3RIN Route","ASI3 MonoMix In","ASI3MonoMixIN"}, + + {"ASI1IN Port", NULL, "ASI1LIN Route"}, + {"ASI1IN Port", NULL, "ASI1RIN Route"}, + {"ASI2IN Port", NULL, "ASI2LIN Route"}, + {"ASI2IN Port", NULL, "ASI2RIN Route"}, + {"ASI3IN Port", NULL, "ASI3LIN Route"}, + {"ASI3IN Port", NULL, "ASI3RIN Route"}, + + {"DAC MiniDSP IN1 Route", "ASI1 In","ASI1IN Port"}, + {"DAC MiniDSP IN1 Route","ASI2 In","ASI2IN Port"}, + {"DAC MiniDSP IN1 Route","ASI3 In","ASI3IN Port"}, + {"DAC MiniDSP IN1 Route","ADC MiniDSP Out","ADC MiniDSP OUT1"}, + + {"Left DAC", "NULL", "DAC MiniDSP IN1 Route"}, + {"Right DAC", "NULL", "DAC MiniDSP IN1 Route"}, + + +/* Mixer Amplifier */ + + {"MAL PGA Mixer", "IN1L Switch","IN1L"}, + {"MAL PGA Mixer", "Left MicPGA Volume","Left MicPGA"}, + + {"MAL PGA", NULL, "MAL PGA Mixer"}, + + + {"MAR PGA Mixer", "IN1R Switch","IN1R"}, + {"MAR PGA Mixer", "Right MicPGA Volume","Right MicPGA"}, + + {"MAR PGA", NULL, "MAR PGA Mixer"}, + + +/* Capture (ADC) portions */ + /* Left Positive PGA input */ + {"Left Input Mixer","IN1L Switch","IN1L"}, + {"Left Input Mixer","IN2L Switch","IN2L"}, + {"Left Input Mixer","IN3L Switch","IN3L"}, + {"Left Input Mixer","IN4L Switch","IN4L"}, + {"Left Input Mixer","IN1R Switch","IN1R"}, + /* Left Negative PGA input */ + {"Left Input Mixer","IN2R Switch","IN2R"}, + {"Left Input Mixer","IN3R Switch","IN3R"}, + {"Left Input Mixer","IN4R Switch","IN4R"}, + {"Left Input Mixer","CM2L Switch","CM2L"}, + {"Left Input Mixer","CM1L Switch","CM1L"}, + + /* Right Positive PGA Input */ + {"Right Input Mixer","IN1R Switch","IN1R"}, + {"Right Input Mixer","IN2R Switch","IN2R"}, + {"Right Input Mixer","IN3R Switch","IN3R"}, + {"Right Input Mixer","IN4R Switch","IN4R"}, + {"Right Input Mixer","IN2L Switch","IN2L"}, + + /* Right Negative PGA Input */ + {"Right Input Mixer","IN1L Switch","IN1L"}, + {"Right Input Mixer","IN3L Switch","IN3L"}, + {"Right Input Mixer","IN4L Switch","IN4L"}, + {"Right Input Mixer","CM1R Switch","CM1R"}, + {"Right Input Mixer","CM2R Switch","CM2R"}, + + {"CM1L", NULL, "CM"}, + {"CM2L", NULL, "CM"}, + {"CM1R", NULL, "CM"}, + {"CM1R", NULL, "CM"}, + + {"Left MicPGA",NULL,"Left Input Mixer"}, + {"Right MicPGA",NULL,"Right Input Mixer"}, + + {"Left ADC", NULL, "Left MicPGA"}, + {"Right ADC", NULL, "Right MicPGA"}, + +/* ASI Output Routing */ + {"ADC MiniDSP OUT1", NULL, "Left ADC"}, + {"ADC MiniDSP OUT1", NULL, "Right ADC"}, + + {"ASI1OUT Route", "ASI1 Out","ADC MiniDSP OUT1"},// Port 1 + {"ASI1OUT Route", "ASI1In Bypass","ASI1IN Port"}, + {"ASI1OUT Route", "ASI2In Bypass","ASI2IN Port"}, + {"ASI1OUT Route", "ASI3In Bypass","ASI3IN Port"}, + + {"ASI2OUT Route", "ASI1 Out","ADC MiniDSP OUT1"},// Port 1 + {"ASI2OUT Route", "ASI1In Bypass","ASI1IN Port"}, + {"ASI2OUT Route", "ASI2In Bypass","ASI2IN Port"}, + {"ASI2OUT Route", "ASI3In Bypass","ASI3IN Port"}, + {"ASI2OUT Route", "ASI2 Out","ADC MiniDSP OUT2"},// Port 2 + + {"ASI3OUT Route", "ASI1 Out","ADC MiniDSP OUT1"},// Port 1 + {"ASI3OUT Route", "ASI1In Bypass","ASI1IN Port"}, + {"ASI3OUT Route", "ASI2In Bypass","ASI2IN Port"}, + {"ASI3OUT Route", "ASI3In Bypass","ASI3IN Port"}, + {"ASI3OUT Route", "ASI3 Out","ADC MiniDSP OUT3"},// Port 3 + + {"ASI1OUT",NULL,"ASI1OUT Route"}, + {"ASI2OUT",NULL,"ASI2OUT Route"}, + {"ASI3OUT",NULL,"ASI3OUT Route"}, + }; + +#define AIC3262_DAPM_ROUTE_NUM (sizeof(aic3262_dapm_routes)/sizeof(struct snd_soc_dapm_route)) + /* ***************************************************************************** * Function Definitions @@ -2785,25 +3223,52 @@ void aic3262_write_reg_cache(struct snd_soc_codec *codec, * *---------------------------------------------------------------------------- */ + u8 aic3262_read(struct snd_soc_codec *codec, u16 reg) { struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec); u8 value; u8 page = reg / 128; - + u16 *cache = codec->reg_cache; + u16 cmd; + u8 buffer[2]; + int rc; reg = reg % 128; - if (aic3262->page_no != page) + if (reg >= AIC3262_CACHEREGNUM) { + return 0; + } + + if (aic3262->control_type == SND_SOC_I2C) { + if (aic3262->page_no != page) { aic3262_change_page(codec, page); + } + i2c_master_send(codec->control_data, (char *)®, 1); + i2c_master_recv(codec->control_data, &value, 1); + /*DBG("r %2x %02x\r\n", reg, value); */ + } else if (aic3262->control_type == SND_SOC_SPI) { + u16 value; + + /* Do SPI transfer; first 16bits are command; remaining is + * register contents */ + cmd = AIC3262_READ_COMMAND_WORD(reg); + buffer[0] = (cmd >> 8) & 0xff; + buffer[1] = cmd & 0xff; + //rc = spi_write_then_read(aic3262->spi, buffer, 2, buffer, 2); + + if (rc) { + dev_err(&aic3262->spi->dev, "AIC26 reg read error\n"); + return -EIO; + } + value = (buffer[0] << 8) | buffer[1]; + } else { + printk(KERN_ERR "Unknown Interface Type in aic3262_read\n"); + } -#if defined(LOCAL_REG_ACCESS) - i2c_master_send(codec->control_data, (char *)®, 1); - i2c_master_recv(codec->control_data, &value, 1); -#else - value = snd_soc_read(codec, reg); -#endif - /*DBG("r %2x %02x\r\n", reg, value);*/ + /* Update the cache before returning with the value */ + cache[reg] = value; return value; + } /* @@ -2930,44 +3395,6 @@ static inline int aic3262_get_divs(int mclk, int rate) return -EINVAL; } -/* - *---------------------------------------------------------------------------- - * Function : aic3262_add_controls - * Purpose : This function is to add non dapm kcontrols. The different - * controls are in "aic3262_snd_controls" table. - * The following different controls are supported - * # PCM Playback volume control - * # PCM Playback Volume - * # HP Driver Gain - * # HP DAC Playback Switch - * # PGA Capture Volume - * # Program Registers - * - *---------------------------------------------------------------------------- - */ -static int aic3262_add_controls(struct snd_soc_codec *codec) -{ - int err; - - DBG("%s++\n", __func__); - - err = snd_soc_add_controls(codec, aic3262_snd_controls, - ARRAY_SIZE(aic3262_snd_controls)); - if (err < 0) { - printk(KERN_ERR "Invalid control\n"); - return err; - } - - err = snd_soc_add_controls(codec, aic3262_snd_controls2, - ARRAY_SIZE(aic3262_snd_controls2)); - if (err < 0) { - printk(KERN_ERR "Invalid control\n"); - return err; - } - - return 0; -} - /* *---------------------------------------------------------------------------- * Function : aic3262_add_widgets @@ -3002,7 +3429,7 @@ static int aic3262_add_widgets(struct snd_soc_codec *codec) snd_soc_dapm_add_routes(dapm, aic3262_dapm_routes, ARRAY_SIZE(aic3262_dapm_routes)); DBG("#Completed adding DAPM routes\n"); - /*snd_soc_dapm_new_widgets(codec);*/ + snd_soc_dapm_new_widgets(dapm); DBG("#Completed updating dapm\n"); return 0; } @@ -3028,7 +3455,7 @@ int reg_def_conf(struct snd_soc_codec *codec) /* Configure the Codec with the default Initialization Values */ for (i = 0; i < reg_init_size; i++) { - ret = aic3262_write(codec, aic3262_reg_init[i].reg_offset, + ret = snd_soc_write(codec, aic3262_reg_init[i].reg_offset, aic3262_reg_init[i].reg_val); if (ret) break; @@ -3083,132 +3510,48 @@ int i2c_verify_book0(struct snd_soc_codec *codec) * *---------------------------------------------------------------------------- */ + static int aic3262_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) + enum snd_soc_bias_level level) { - u8 value; struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec); - - DBG(KERN_INFO "#%s: Codec Active %d[%d]\n", - __func__, codec->active, aic3262->active_count); + u8 value; switch (level) { /* full On */ case SND_SOC_BIAS_ON: - DBG(KERN_INFO "#aic3262 codec : set_bias_on started\n"); - case SND_SOC_BIAS_PREPARE: - /* all power is driven by DAPM system */ - DBG(KERN_INFO "#aic3262 codec : set_bias_prepare started\n"); - - /* Switch on PLL */ - value = aic3262_read(codec, PLL_PR_POW_REG); - aic3262_write(codec, PLL_PR_POW_REG, ((value | 0x80))); - - /* Switch on NDAC Divider */ - value = aic3262_read(codec, NDAC_DIV_POW_REG); - aic3262_write(codec, NDAC_DIV_POW_REG, - ((value & 0x7f) | (0x80))); - - /* Switch on MDAC Divider */ - value = aic3262_read(codec, MDAC_DIV_POW_REG); - aic3262_write(codec, MDAC_DIV_POW_REG, - ((value & 0x7f) | (0x80))); - - /* Switch on NADC Divider */ - value = aic3262_read(codec, NADC_DIV_POW_REG); - aic3262_write(codec, NADC_DIV_POW_REG, - ((value & 0x7f) | (0x80))); - - /* Switch on MADC Divider */ - value = aic3262_read(codec, MADC_DIV_POW_REG); - aic3262_write(codec, MADC_DIV_POW_REG, - ((value & 0x7f) | (0x80))); + /* all power is driven by DAPM system */ + dev_dbg(codec->dev, "set_bias_on\n"); + break; - aic3262_write(codec, ADC_CHANNEL_POW, 0xc2); - aic3262_write(codec, ADC_FINE_GAIN, 0x00); + /* partial On */ + case SND_SOC_BIAS_PREPARE: - DBG("#aic3262 codec : set_bias_on complete\n"); + dev_dbg(codec->dev, "set_bias_prepare\n"); break; - - /* Off, with power */ + /* Off, with power */ case SND_SOC_BIAS_STANDBY: /* * all power is driven by DAPM system, * so output power is safe if bypass was set */ + dev_dbg(codec->dev, "set_bias_stby\n"); - DBG("#aic3262 codec : set_bias_stby inside if condn\n"); - - if (!aic3262->active_count) { - /* Switch off NDAC Divider */ - value = aic3262_read(codec, NDAC_DIV_POW_REG); - aic3262_write(codec, NDAC_DIV_POW_REG, - (value & 0x7f)); - - /* Switch off MDAC Divider */ - value = aic3262_read(codec, MDAC_DIV_POW_REG); - aic3262_write(codec, MDAC_DIV_POW_REG, - (value & 0x7f)); - - /* Switch off NADC Divider */ - value = aic3262_read(codec, NADC_DIV_POW_REG); - aic3262_write(codec, NADC_DIV_POW_REG, - (value & 0x7f)); - - /* Switch off MADC Divider */ - value = aic3262_read(codec, MADC_DIV_POW_REG); - aic3262_write(codec, MADC_DIV_POW_REG, - (value & 0x7f)); - - /* Switch off PLL */ - value = aic3262_read(codec, PLL_PR_POW_REG); - aic3262_write(codec, PLL_PR_POW_REG, (value & 0x7f)); - - DBG("#%s: set_bias_stby complete\n", __func__); - } else - DBG(KERN_INFO - "#%s: Another Stream Active. No STANDBY\n", __func__); break; - - /* Off, without power */ + /* Off, without power */ case SND_SOC_BIAS_OFF: - /* force all power off */ - - /* Switch off PLL */ - value = aic3262_read(codec, PLL_PR_POW_REG); - aic3262_write(codec, - PLL_PR_POW_REG, (value & ~(0x01 << 7))); - - /* Switch off NDAC Divider */ - value = aic3262_read(codec, NDAC_DIV_POW_REG); - aic3262_write(codec, NDAC_DIV_POW_REG, - (value & ~(0x01 << 7))); - - /* Switch off MDAC Divider */ - value = aic3262_read(codec, MDAC_DIV_POW_REG); - aic3262_write(codec, MDAC_DIV_POW_REG, - (value & ~(0x01 << 7))); - - /* Switch off NADC Divider */ - value = aic3262_read(codec, NADC_DIV_POW_REG); - aic3262_write(codec, NADC_DIV_POW_REG, - (value & ~(0x01 << 7))); - - /* Switch off MADC Divider */ - value = aic3262_read(codec, MADC_DIV_POW_REG); - aic3262_write(codec, MADC_DIV_POW_REG, - (value & ~(0x01 << 7))); - value = aic3262_read(codec, ASI1_BCLK_N); + dev_dbg(codec->dev, "set_bias_off\n"); break; } - codec->dapm.bias_level = level; - DBG(KERN_INFO "#aic3262 codec : set_bias exiting\n"); + codec->dapm.bias_level=level; + return 0; } + /* *---------------------------------------------------------------------------- * Function : aic3262_suspend @@ -3302,18 +3645,20 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data) unsigned int value; unsigned int micbits, hsbits = 0; - DBG("%s++\n", __func__); + //DBG("%s++\n", __func__); + + pr_err("@@@@In Intrp\n"); aic3262_change_page(codec, 0); /* Read the Jack Status Register*/ - value = aic3262_read(codec, STICKY_FLAG2); + value = snd_soc_read(codec, STICKY_FLAG2); DBG(KERN_INFO "reg44 0x%x\n", value); - value = aic3262_read(codec, INT_FLAG2); + value = snd_soc_read(codec, INT_FLAG2); DBG("reg46 0x%x\n", value); - value = aic3262_read(codec, DAC_FLAG_R1); + value = snd_soc_read(codec, DAC_FLAG_R1); DBG("reg37 0x%x\n", value); micbits = value & DAC_FLAG_MIC_MASKBITS; @@ -3322,14 +3667,13 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data) hsbits = value & DAC_FLAG_HS_MASKBITS; DBG("hsbits 0x%x\n", hsbits); - /* sleep for debounce time */ - /*msleep(aic3262->pdata->debounce_time_ms);*/ /* No Headphone or Headset*/ if (!micbits && !hsbits) { DBG("no headset/headphone\n"); snd_soc_jack_report(aic3262->headset_jack, 0, SND_JACK_HEADSET); + pr_err("@@@@NO HP or HS\n"); } /* Headphone Detected */ @@ -3337,6 +3681,7 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data) DBG("headphone\n"); snd_soc_jack_report(aic3262->headset_jack, SND_JACK_HEADPHONE, SND_JACK_HEADSET); + pr_err("@@@@HP detected\n"); } /* Headset Detected - only with capless */ @@ -3344,6 +3689,7 @@ static irqreturn_t aic3262_jack_handler(int irq, void *data) DBG("headset\n"); snd_soc_jack_report(aic3262->headset_jack, SND_JACK_HEADSET, SND_JACK_HEADSET); + pr_err("@@@@HS detected\n"); } DBG("%s--\n", __func__); @@ -3419,7 +3765,6 @@ static void aic3262_asi_default_config(struct snd_soc_codec *codec) aic3262->asiCtxt[2].right_dac_output = DAC_PATH_LEFT; aic3262->asiCtxt[2].adc_input = ADC_PATH_MINIDSP_3; aic3262->asiCtxt[2].dout_option = ASI2_INPUT; - return; } @@ -3432,6 +3777,7 @@ static void aic3262_asi_default_config(struct snd_soc_codec *codec) * *---------------------------------------------------------------------------- */ + static int aic3262_probe(struct snd_soc_codec *codec) { struct aic3262_priv *aic3262 = snd_soc_codec_get_drvdata(codec); @@ -3470,8 +3816,11 @@ static int aic3262_probe(struct snd_soc_codec *codec) if (ret != 0) { printk(KERN_ERR "Failed to init TI codec: %d\n", ret); return ret; + } else { + pr_err("@@@@@@@@@@TI codec successfully init\n"); } + if (aic3262->irq) { /* audio interrupt */ ret = request_threaded_irq(aic3262->irq, NULL, @@ -3497,10 +3846,24 @@ static int aic3262_probe(struct snd_soc_codec *codec) /* off, with power on */ aic3262_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - aic3262_add_controls(codec); + ret = snd_soc_add_controls(codec, aic3262_snd_controls, + ARRAY_SIZE(aic3262_snd_controls)); + if(ret) + { + printk(KERN_INFO "%s failed\n", __func__); + } + aic3262_add_widgets(codec); /*TODO*/ - aic3262_write(codec, MIC_BIAS_CNTL, 0x66); + snd_soc_write(codec, MIC_BIAS_CNTL, 0x66); + +#ifdef AIC3262_TiLoad + ret = aic3262_driver_init(codec); + if (ret < 0) + printk(KERN_ERR + "\nAIC3262 CODEC: aic3262_probe :TiLoad Initialization failed\n"); +#endif + #ifdef CONFIG_MINI_DSP /* Program MINI DSP for ADC and DAC */ @@ -3517,6 +3880,8 @@ static int aic3262_probe(struct snd_soc_codec *codec) return ret; } + + /* *---------------------------------------------------------------------------- * Function : aic3262_remove @@ -3581,6 +3946,7 @@ static __devinit int aic3262_codec_probe(struct i2c_client *i2c, struct aic3262_priv *aic3262; + pr_err("@@@@@@@@@TI codec probe\n") DBG(KERN_INFO "#%s: Entered\n", __func__); aic3262 = kzalloc(sizeof(struct aic3262_priv), GFP_KERNEL); @@ -3645,7 +4011,7 @@ static __devexit int aic3262_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id tlv320aic3262_id[] = { - {"tlv320aic3262", 0}, + {"aic3262-codec", 0}, {} }; MODULE_DEVICE_TABLE(i2c, tlv320aic3262_id); @@ -3661,18 +4027,149 @@ static struct i2c_driver tlv320aic3262_i2c_driver = { }; #endif /*#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)*/ +#if defined(CONFIG_SPI_MASTER) +static int aic3262_spi_write(struct spi_device *spi, const char *data, int len) +{ + struct spi_transfer t; + struct spi_message m; + u8 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} + +/* + * This function forces any delayed work to be queued and run. + */ +static int run_delayed_work(struct delayed_work *dwork) +{ + int ret; + + /* cancel any work waiting to be queued. */ + ret = cancel_delayed_work(dwork); + + /* if there was any work waiting then we run it now and + * wait for it's completion */ + if (ret) { + schedule_delayed_work(dwork, 0); + flush_scheduled_work(); + } + return ret; +} +static int __devinit aic3262_spi_probe(struct spi_device *spi) +{ + int ret; + struct snd_soc_codec *codec; + struct aic3262_priv *aic3262; + printk(KERN_INFO "%s entering\n",__func__); + aic3262 = kzalloc(sizeof(struct aic3262_priv), GFP_KERNEL); + + if (!aic3262) { + printk(KERN_ERR "#%s: Unable to Allocate Priv struct..\n", + __func__); + return -ENOMEM; + } + codec = &aic3262->codec; + codec->control_data = spi; + aic3262->control_type = SND_SOC_SPI; + codec->hw_write = (hw_write_t)aic3262_spi_write; + codec->dev = &spi->dev; + + aic3262->pdata = spi->dev.platform_data; + + /* The Configuration Support will be by default to 3 which + * holds the MAIN Patch Configuration. + */ + aic3262->current_dac_config[0] = -1; + aic3262->current_dac_config[1] = -1; + aic3262->current_adc_config[0] = -1; + aic3262->current_adc_config[1] = -1; + + aic3262->mute_codec = 1; + + aic3262->page_no = 0; + aic3262->book_no = 0; + aic3262->active_count = 0; + aic3262->dac_clkin_option = 3; + aic3262->adc_clkin_option = 3; + dev_set_drvdata(&spi->dev, aic3262); + spi_set_drvdata(spi, aic3262); + ret = snd_soc_register_codec(&spi->dev, + &soc_codec_dev_aic3262, + tlv320aic3262_dai, ARRAY_SIZE(tlv320aic3262_dai)); + + if (ret < 0) { + printk(KERN_INFO "%s codec registeration failed\n",__func__); + kfree(aic3262); + } + else { + printk(KERN_INFO "%s registered\n",__func__); + } + printk(KERN_INFO "#%s: Done ret %d\n", __func__, ret); + return ret; +} + +static int __devexit aic3262_spi_remove(struct spi_device *spi) +{ + struct aic3262_priv *aic3262 = dev_get_drvdata(&spi->dev); + aic3262_set_bias_level(&aic3262->codec, SND_SOC_BIAS_OFF); + snd_soc_unregister_codec(&spi->dev); + kfree(aic3262); + aic3262_codec = NULL; + return 0; + +} + +static const struct spi_device_id tlv320aic3262_id[] = { + {"aic3262-codec", 0}, + {} +}; +static struct spi_driver aic3262_spi_driver = { + .driver = { + .name = "aic3262-codec", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = aic3262_spi_probe, + .remove = __devexit_p(aic3262_spi_remove), + .id_table = tlv320aic3262_id, +}; +#endif static int __init tlv320aic3262_modinit(void) { int ret = 0; + printk(KERN_INFO "In %s\n",__func__); #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) ret = i2c_add_driver(&tlv320aic3262_i2c_driver); if (ret != 0) printk(KERN_ERR "Failed to register aic326x i2c driver %d\n", ret); + + pr_err("@@@@@@@@@TI modinit register I2C driver\n"); +#endif +#if defined(CONFIG_SPI_MASTER) + printk(KERN_INFO "Inside config_spi_master\n"); + ret = spi_register_driver(&aic3262_spi_driver); + if (ret != 0) + printk(KERN_ERR "Failed to register aic3262 SPI driver: %d\n", ret); #endif return ret; } + module_init(tlv320aic3262_modinit); static void __exit tlv320aic3262_exit(void) diff --git a/sound/soc/codecs/tlv320aic326x.h b/sound/soc/codecs/tlv320aic326x.h index 259ecb110787..d81b34f8eb34 100644 --- a/sound/soc/codecs/tlv320aic326x.h +++ b/sound/soc/codecs/tlv320aic326x.h @@ -2,7 +2,7 @@ * linux/sound/soc/codecs/tlv320aic3262.h * * - * Copyright (C) 2011 Mistral Solutions Pvt Ltd. + * Copyright (C) 2012 Texas Instruments, Inc. * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,7 +13,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * History: - * Rev 0.1 ASoC driver support Mistral 20-01-2011 + * Rev 0.1 ASoC driver support 20-01-2011 * * The AIC3262 ASoC driver is ported for the codec AIC3262. * @@ -40,6 +40,10 @@ result some issue with cache. Common code doesnot support page, so fix that before commenting this line*/ #define LOCAL_REG_ACCESS 1 +/* Macro to enable the inclusion of tiload kernel driver */ +#define AIC3262_TiLoad + + /* Macro enables or disables support for miniDSP in the driver */ /* Enable the AIC3262_TiLoad macro first before enabling these macros */ #define CONFIG_MINI_DSP @@ -63,7 +67,7 @@ page, so fix that before commenting this line*/ #define AIC3262_MULTI_I2S 1 /* Driver Debug Messages Enabled */ -/*#define DEBUG*/ +//#define DEBUG #ifdef DEBUG #define DBG(x...) printk(x) @@ -115,6 +119,7 @@ page, so fix that before commenting this line*/ /* Total number of ASI Ports */ #define MAX_ASI_COUNT 3 + /* AIC3262 register space */ /* Updated from 256 to support Page 3 registers */ #define AIC3262_CACHEREGNUM 1024 @@ -246,7 +251,10 @@ page, so fix that before commenting this line*/ #define INT1_SEL_L (PAGE_1 + 34) #define RAMP_CNTL_R1 (PAGE_1 + 36) #define RAMP_CNTL_R2 (PAGE_1 + 37) -#define INT1_SEL_RM (PAGE_1 + 39) +//#define INT1_SEL_RM (PAGE_1 + 39) +#define IN1L_SEL_RM (PAGE_1 + 39) +#define IN1R_SEL_RM (PAGE_1 + 39) + #define REC_AMP_CNTL_R5 (PAGE_1 + 40) #define RAMPR_VOL (PAGE_1 + 41) #define RAMP_TIME_CNTL (PAGE_1 + 42) @@ -304,6 +312,7 @@ page, so fix that before commenting this line*/ #define ASI3_ADC_INPUT_CNTL (PAGE_4 + 39) #define ASI3_DAC_OUT_CNTL (PAGE_4 + 40) #define ASI3_BWCLK_CNTL_REG (PAGE_4 + 42) +#define ASI3_BCLK_N_CNTL (PAGE_4 + 43) #define ASI3_BCLK_N (PAGE_4 + 44) #define ASI3_WCLK_N (PAGE_4 + 45) #define ASI3_BWCLK_OUT_CNTL (PAGE_4 + 46) @@ -413,12 +422,21 @@ enum ASI_DAC_OUTPUT_OPTION { DAC_PATH_RIGHT, /* 02 DAC Datapath Right Data */ }; +#define AIC3262_READ_COMMAND_WORD(addr) ((1 << 15) | (addr << 5)) +#define AIC3262_WRITE_COMMAND_WORD(addr) ((0 << 15) | (addr << 5)) + /* Shift the above options by so many bits */ #define AIC3262_ASI_LDAC_PATH_SHIFT 6 #define AIC3262_ASI_LDAC_PATH_MASK (BIT5 | BIT4) #define AIC3262_ASI_RDAC_PATH_SHIFT 4 #define AIC3262_ASI_RDAC_PATH_MASK (BIT7 | BIT6) + +#define DAC_LR_MUTE_MASK 0xc +#define DAC_LR_MUTE 0xc +#define ENABLE_CLK_MASK 0x80 +#define ENABLE_CLK 0x80 + /* ASI specific ADC Input Control Options */ enum ASI_ADC_INPUT_OPTION { ADC_PATH_OFF = 0, /* 00 ASI Digital Output Disabled */ @@ -509,6 +527,7 @@ struct aic3262_asi_data { struct aic3262_priv { enum snd_soc_control_type control_type; struct aic326x_pdata *pdata; + struct snd_soc_codec codec; u32 sysclk; s32 master; u8 book_no; @@ -524,6 +543,14 @@ struct aic3262_priv { u8 dac_clkin_option; u8 adc_clkin_option; int irq; + u8 dac_reg; + u8 adc_gain; + u8 hpl; + u8 hpr; + u8 rec_amp; + u8 rampr; + u8 spk_amp; + struct spi_device *spi; struct snd_soc_jack *headset_jack; #if defined(LOCAL_REG_ACCESS) void *control_data; diff --git a/sound/soc/codecs/tlv320aic326x_mini-dsp.c b/sound/soc/codecs/tlv320aic326x_mini-dsp.c index 4d9c4de7e59a..feefe7dd8f4d 100644 --- a/sound/soc/codecs/tlv320aic326x_mini-dsp.c +++ b/sound/soc/codecs/tlv320aic326x_mini-dsp.c @@ -1,7 +1,7 @@ /* * linux/sound/soc/codecs/tlv320aic326x_mini-dsp.c * - * Copyright (C) 2011 Mistral Solutions Pvt Ltd. + * Copyright (C) 2012 Texas Instruments, Inc. * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,10 +16,10 @@ * * History: * - * Rev 0.1 Added the miniDSP Support Mistral 01-03-2011 + * Rev 0.1 Added the miniDSP Support 01-03-2011 * * Rev 0.2 Updated the code-base for miniDSP switching and - * mux control update. Mistral 21-03-2011 + * mux control update. 21-03-2011 * * Rev 0.3 Updated the code-base to support Multi-Configuration feature * of PPS GDE @@ -192,6 +192,7 @@ void update_kcontrols(struct snd_soc_codec *codec, int process_flow) val1 = i2c_smbus_read_byte_data(codec->control_data, cntl[i].control_base); snd_mux_controls[i].private_value = 0; + aic3262_change_book(codec,0); } } @@ -236,6 +237,7 @@ int byte_i2c_array_transfer(struct snd_soc_codec *codec, return -EIO; } } + aic3262_change_book(codec,0); return 0; } @@ -434,7 +436,7 @@ set_minidsp_mode(struct snd_soc_codec *codec, int new_mode) DBG("%s: switch mode start\n", __func__); aic3262_reset_cache(codec); - reg_def_conf(codec); + /*reg_def_conf(codec);*/ if (new_mode == 0) { @@ -830,7 +832,9 @@ int aic3262_minidsp_program(struct snd_soc_codec *codec) DBG("#Verifying book 0\n"); i2c_verify_book0(codec); #endif + aic3262_change_book(codec,0); set_minidsp_mode1(codec, 1); + aic3262_change_book(codec,0); #ifdef DEBUG DBG("#verifying book 0\n"); i2c_verify_book0(codec); @@ -882,12 +886,14 @@ static int m_control_get(struct snd_kcontrol *kcontrol, val1 = i2c_smbus_read_byte_data(codec->control_data, 1); ucontrol->value.integer.value[0] = ((val1>>1)&0x01); DBG(KERN_INFO "control get : mode=%d\n", aic3262->process_flow); + aic3262_change_book(codec,0); } if (!strcmp(kcontrol->id.name, "ADC Adaptive mode Enable")) { aic3262_change_book(codec, 40); val1 = i2c_smbus_read_byte_data(codec->control_data, 1); ucontrol->value.integer.value[0] = ((val1>>1)&0x01); DBG(KERN_INFO "control get : mode=%d\n", dmode); + aic3262_change_book(codec,0); } return 0; @@ -939,6 +945,7 @@ static int m_control_put(struct snd_kcontrol *kcontrol, aic3262_change_book(codec, 80); val1 = i2c_smbus_read_byte_data(codec->control_data, 1); aic3262_write(codec, 1, (val1&0xfb)|(val<<1)); + aic3262_change_book(codec,0); } amode = val; } @@ -950,6 +957,7 @@ static int m_control_put(struct snd_kcontrol *kcontrol, aic3262_change_book(codec, 40); val1 = i2c_smbus_read_byte_data(codec->control_data, 1); aic3262_write(codec, 1, (val1&0xfb)|(val<<1)); + aic3262_change_book(codec,0); } dmode = val; } @@ -1234,6 +1242,7 @@ static int minidsp_mux_ctrl_mixer_controls(struct snd_soc_codec *codec, snd_mux_controls[i].name); } } + aic3262_change_book(codec, 0); return 0; } diff --git a/sound/soc/codecs/tlv320aic326x_mini-dsp.h b/sound/soc/codecs/tlv320aic326x_mini-dsp.h index 394fa5954dde..bbc781776089 100644 --- a/sound/soc/codecs/tlv320aic326x_mini-dsp.h +++ b/sound/soc/codecs/tlv320aic326x_mini-dsp.h @@ -14,10 +14,10 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * History: - * Rev 0.1 Added the multiconfig support Mistral 17-08-2011 + * Rev 0.1 Added the multiconfig support 17-08-2011 * * Rev 0.2 Migrated for aic3262 nVidia - * Mistral 21-10-2011 + * 21-10-2011 */ #ifndef _TLV320AIC3262_MINI_DSP_H diff --git a/sound/soc/codecs/tlv320aic326x_minidsp_config.c b/sound/soc/codecs/tlv320aic326x_minidsp_config.c index 07b762aeedbc..ee8ca71dc7f8 100644 --- a/sound/soc/codecs/tlv320aic326x_minidsp_config.c +++ b/sound/soc/codecs/tlv320aic326x_minidsp_config.c @@ -1,7 +1,7 @@ /* * linux/sound/soc/codecs/tlv320aic326x_minidsp_config.c * - * Copyright (C) 2011 Mistral Solutions Pvt Ltd. + * Copyright (C) 2012 Texas Instruments, Inc. * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,10 +16,10 @@ * * History: * - * Rev 0.1 Added the multiconfig support Mistral 17-08-2011 + * Rev 0.1 Added the multiconfig support 17-08-2011 * * Rev 0.2 Migrated for aic3262 nVidia - * Mistral 21-10-2011 + * 21-10-2011 */ /* @@ -66,7 +66,7 @@ * LOCAL STATIC DECLARATIONS ***************************************************************************** */ -static int multibyte_coeff_change(struct snd_soc_codec *codec, int); +int multibyte_coeff_change(struct snd_soc_codec *codec, int); static int m_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); @@ -350,7 +350,7 @@ void config_multibyte_for_mode(struct snd_soc_codec *codec, int mode) * miniDSP_D and miniDSP_A Coefficient arrays. *--------------------------------------------------------------------------- */ -static int multibyte_coeff_change(struct snd_soc_codec *codec, int bk) +int multibyte_coeff_change(struct snd_soc_codec *codec, int bk) { u8 value[2], swap_reg_pre, swap_reg_post; @@ -399,6 +399,9 @@ static int multibyte_coeff_change(struct snd_soc_codec *codec, int bk) swap_reg_pre, swap_reg_post); } + aic3262_change_book(codec, 0); + return 0; + err: return 0; } -- cgit v1.2.3