12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868 |
- diff --git a/drivers/mfd/ac200.c b/drivers/mfd/ac200.c
- index 570573790..5d759eb1e 100644
- --- a/drivers/mfd/ac200.c
- +++ b/drivers/mfd/ac200.c
- @@ -41,6 +41,7 @@ static const struct regmap_range_cfg ac200_range_cfg[] = {
- };
-
- static const struct regmap_config ac200_regmap_config = {
- + .name = "ac200",
- .reg_bits = 8,
- .val_bits = 16,
- .ranges = ac200_range_cfg,
- @@ -75,6 +76,10 @@ static const struct mfd_cell ac200_cells[] = {
- .resources = ephy_resource,
- .of_compatible = "x-powers,ac200-ephy",
- },
- + {
- + .name = "acx00-codec",
- + .of_compatible = "x-powers,ac200-codec",
- + },
- };
-
- static int ac200_i2c_probe(struct i2c_client *i2c,
- diff --git a/drivers/pwm/pwm-sun4i.c b/drivers/pwm/pwm-sun4i.c
- index 0ad261ffa..7a654de46 100644
- --- a/drivers/pwm/pwm-sun4i.c
- +++ b/drivers/pwm/pwm-sun4i.c
- @@ -175,7 +175,7 @@ static int sun4i_pwm_calculate(struct sun4i_pwm_chip *sun4i_pwm,
- clk_rate = clk_get_rate(sun4i_pwm->clk);
-
- *bypass = sun4i_pwm->data->has_direct_mod_clk_output &&
- - state->enabled &&
- +// state->enabled &&
- (state->period * clk_rate >= NSEC_PER_SEC) &&
- (state->period * clk_rate < 2 * NSEC_PER_SEC) &&
- (state->duty_cycle * clk_rate * 2 >= NSEC_PER_SEC);
- diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
- index 20d99b44d..09ac9c747 100644
- --- a/sound/soc/codecs/Kconfig
- +++ b/sound/soc/codecs/Kconfig
- @@ -1787,4 +1787,12 @@ config SND_SOC_TPA6130A2
- tristate "Texas Instruments TPA6130A2 headphone amplifier"
- depends on I2C
-
- +config SND_SOC_ACX00
- + tristate "ACX00 Codec"
- + select MFD_ACX00
- + default n
- + help
- + ACX00 now used as SUN50IW6 internal Codec, Connect Through I2S0.
- + Say Y or M if you want to add support internal audio codec.
- +
- endmenu
- diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
- index cfdeed716..e6c378f71 100644
- --- a/sound/soc/codecs/Makefile
- +++ b/sound/soc/codecs/Makefile
- @@ -306,6 +306,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o
- snd-soc-tas2552-objs := tas2552.o
- snd-soc-tas2562-objs := tas2562.o
- snd-soc-tas2764-objs := tas2764.o
- +snd-soc-acx00-objs := acx00.o
-
- obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
- obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o
- @@ -615,3 +616,4 @@ obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
- obj-$(CONFIG_SND_SOC_MAX98504) += snd-soc-max98504.o
- obj-$(CONFIG_SND_SOC_SIMPLE_AMPLIFIER) += snd-soc-simple-amplifier.o
- obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
- +obj-$(CONFIG_SND_SOC_ACX00) += snd-soc-acx00.o
- \ No newline at end of file
- diff --git a/sound/soc/codecs/acx00.c b/sound/soc/codecs/acx00.c
- new file mode 100644
- index 000000000..afa072353
- --- /dev/null
- +++ b/sound/soc/codecs/acx00.c
- @@ -0,0 +1,1372 @@
- +/*
- + * acx00.c -- ACX00 ALSA Soc Audio Codec driver
- + *
- + * (C) Copyright 2010-2016 Allwinnertech Technology., Ltd.
- + *
- + * Author: Wolfgang Huang <huangjinhui@allwinner.com>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + */
- +
- +#include <linux/module.h>
- +#include <linux/moduleparam.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/firmware.h>
- +#include <linux/delay.h>
- +#include <linux/pm.h>
- +#include <linux/i2c.h>
- +#include <linux/clk.h>
- +#include <linux/of_gpio.h>
- +#include <linux/of_device.h>
- +#include <linux/of_platform.h>
- +#include <linux/debugfs.h>
- +#include <linux/slab.h>
- +#include <linux/mfd/ac200.h>
- +#include <sound/core.h>
- +#include <sound/pcm.h>
- +#include <sound/pcm_params.h>
- +#include <sound/soc.h>
- +#include <sound/initval.h>
- +#include <sound/tlv.h>
- +#include <linux/workqueue.h>
- +
- +#include "acx00.h"
- +
- +
- +#define ACX00_DEF_VOL 0x9F9F
- +#undef ACX00_DAPM_LINEOUT
- +
- +struct acx00_priv {
- + struct ac200_dev *acx00; /* parent mfd device struct */
- + struct snd_soc_component *component;
- + struct clk *clk;
- + unsigned int sample_rate;
- + unsigned int fmt;
- + unsigned int enable;
- + unsigned int spk_gpio;
- + unsigned int switch_gpio;
- + bool spk_gpio_used;
- + struct mutex mutex;
- + struct delayed_work spk_work;
- + struct delayed_work resume_work;
- +};
- +
- +struct sample_rate {
- + unsigned int samplerate;
- + unsigned int rate_bit;
- +};
- +
- +static const struct sample_rate sample_rate_conv[] = {
- + {44100, 7},
- + {48000, 8},
- + {8000, 0},
- + {32000, 6},
- + {22050, 4},
- + {24000, 5},
- + {16000, 3},
- + {11025, 1},
- + {12000, 2},
- + {192000, 10},
- + {96000, 9},
- +};
- +
- +void __iomem *io_stat_addr;
- +
- +static const DECLARE_TLV_DB_SCALE(i2s_mixer_adc_tlv, -600, 600, 1);
- +static const DECLARE_TLV_DB_SCALE(i2s_mixer_dac_tlv, -600, 600, 1);
- +static const DECLARE_TLV_DB_SCALE(dac_mixer_adc_tlv, -600, 600, 1);
- +static const DECLARE_TLV_DB_SCALE(dac_mixer_dac_tlv, -600, 600, 1);
- +static const DECLARE_TLV_DB_SCALE(line_out_tlv, -450, 150, 0);
- +static const DECLARE_TLV_DB_SCALE(mic_out_tlv, -450, 150, 0);
- +static const DECLARE_TLV_DB_SCALE(phoneout_tlv, -450, 150, 0);
- +static const DECLARE_TLV_DB_SCALE(adc_input_tlv, -450, 150, 0);
- +static const DECLARE_TLV_DB_SCALE(lineout_tlv, -4800, 150, 1);
- +static const unsigned int mic_boost_tlv[] = {
- + TLV_DB_RANGE_HEAD(2),
- + 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
- + 1, 7, TLV_DB_SCALE_ITEM(2400, 300, 0),
- +};
- +
- +static const struct snd_kcontrol_new acx00_codec_controls[] = {
- + SOC_DOUBLE_TLV("I2S Mixer ADC Volume", AC_I2S_MIXER_GAIN,
- + I2S_MIXERL_GAIN_ADC, I2S_MIXERR_GAIN_ADC,
- + 0x1, 0, i2s_mixer_adc_tlv),
- + SOC_DOUBLE_TLV("I2S Mixer DAC Volume", AC_I2S_MIXER_GAIN,
- + I2S_MIXERL_GAIN_DAC, I2S_MIXERR_GAIN_DAC,
- + 0x1, 0, i2s_mixer_dac_tlv),
- + SOC_DOUBLE_TLV("DAC Mixer ADC Volume", AC_DAC_MIXER_GAIN,
- + DAC_MIXERL_GAIN_ADC, DAC_MIXERR_GAIN_ADC,
- + 0x1, 0, dac_mixer_adc_tlv),
- + SOC_DOUBLE_TLV("DAC Mxier DAC Volume", AC_DAC_MIXER_GAIN,
- + DAC_MIXERL_GAIN_DAC, DAC_MIXERR_GAIN_DAC,
- + 0x1, 0, dac_mixer_dac_tlv),
- + SOC_SINGLE_TLV("Line Out Mixer Volume", AC_OUT_MIXER_CTL,
- + OUT_MIXER_LINE_VOL, 0x7, 0, line_out_tlv),
- + SOC_DOUBLE_TLV("MIC Out Mixer Volume", AC_OUT_MIXER_CTL,
- + OUT_MIXER_MIC1_VOL, OUT_MIXER_MIC2_VOL,
- + 0x7, 0, mic_out_tlv),
- + SOC_SINGLE_TLV("ADC Input Volume", AC_ADC_MIC_CTL,
- + ADC_GAIN, 0x07, 0, adc_input_tlv),
- + SOC_SINGLE_TLV("Master Volume", AC_LINEOUT_CTL,
- + LINEOUT_VOL, 0x1f, 0, lineout_tlv),
- + SOC_SINGLE_TLV("MIC1 Boost Volume", AC_ADC_MIC_CTL,
- + MIC1_BOOST, 0x07, 0, mic_boost_tlv),
- + SOC_SINGLE_TLV("MIC2 Boost Volume", AC_ADC_MIC_CTL,
- + MIC2_BOOST, 0x07, 0, mic_boost_tlv),
- +};
- +
- +/* Enable I2S & DAC clk, then enable the DAC digital part */
- +static int acx00_playback_event(struct snd_soc_dapm_widget *w,
- + struct snd_kcontrol *k, int event)
- +{
- + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- +
- + switch (event) {
- + case SND_SOC_DAPM_POST_PMU:
- + snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
- + (0x1<<SYS_CLK_DAC), (0x1<<SYS_CLK_DAC));
- + snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
- + (0x1<<MOD_RST_DAC), (0x1<<MOD_RST_DAC));
- + snd_soc_component_update_bits(component, AC_DAC_CTL,
- + (0x1<<DAC_CTL_DAC_EN), (0x1<<DAC_CTL_DAC_EN));
- + break;
- + case SND_SOC_DAPM_POST_PMD:
- + snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
- + (0x1<<SYS_CLK_DAC), (0x0<<SYS_CLK_DAC));
- + snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
- + (0x1<<MOD_RST_DAC), (0x0<<MOD_RST_DAC));
- + snd_soc_component_update_bits(component, AC_DAC_CTL,
- + (0x1<<DAC_CTL_DAC_EN), (0x0<<DAC_CTL_DAC_EN));
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +/* Enable I2S & ADC clk, then enable the ADC digital part */
- +static int acx00_capture_event(struct snd_soc_dapm_widget *w,
- + struct snd_kcontrol *k, int event)
- +{
- + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- +
- + switch (event) {
- + case SND_SOC_DAPM_POST_PMU:
- + snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
- + (0x1<<SYS_CLK_ADC), (0x1<<SYS_CLK_ADC));
- + snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
- + (0x1<<MOD_RST_ADC), (0x1<<MOD_RST_ADC));
- + snd_soc_component_update_bits(component, AC_ADC_CTL,
- + (0x1<<ADC_EN), (0x1<<ADC_EN));
- + break;
- + case SND_SOC_DAPM_POST_PMD:
- + snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
- + (0x1<<SYS_CLK_ADC), (0x0<<SYS_CLK_ADC));
- + snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
- + (0x1<<MOD_RST_ADC), (0x0<<MOD_RST_ADC));
- + snd_soc_component_update_bits(component, AC_ADC_CTL,
- + (0x1<<ADC_EN), (0x0<<ADC_EN));
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +/*
- + * we used for three scene:
- + * 1. No external Spker & DAPM LINEOUT used, we just enable the LINEOUT in the
- + * ALSA codec probe(acx00_codec_probe) and resume, and we shutdown the LINEOUT
- + * in device shutdown or suspend.
- + * 2. No external Spker, but DAPM LINEOUT used, we just using the LINEOUT
- + * enable or disable throught the DAPM control.
- + * 3. External Spker & DAPM LINEOUT used, we just using the LINEOUT and
- + * External Spker control GPIO enable or disable through DAPM control.
- + */
- +static unsigned int spk_delay = 100;
- +module_param(spk_delay, int, 0644);
- +MODULE_PARM_DESC(spk_delay, "ACX00-Codec spk mute delay time");
- +
- +static void acx00_spk_enable(struct work_struct *work)
- +{
- + struct acx00_priv *priv = container_of(work,
- + struct acx00_priv, spk_work.work);
- + gpio_set_value(priv->spk_gpio, 1);
- +}
- +
- +static int acx00_lineout_event(struct snd_soc_dapm_widget *w,
- + struct snd_kcontrol *k, int event)
- +{
- + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- +
- + switch (event) {
- + case SND_SOC_DAPM_POST_PMU:
- + if (!priv->enable) {
- + snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
- + (1<<LINEL_SRC_EN), (1<<LINEL_SRC_EN));
- + snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
- + (1<<LINER_SRC_EN), (1<<LINER_SRC_EN));
- + msleep(100);
- + priv->enable = 1;
- + }
- +#ifdef ACX00_DAPM_LINEOUT
- + snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
- + (1<<LINEOUT_EN), (1<<LINEOUT_EN));
- + mdelay(50);
- +#endif
- + if (priv->spk_gpio_used) {
- + if (spk_delay == 0) {
- + gpio_set_value(priv->spk_gpio, 1);
- + /*
- + * time delay to wait spk pa work fine,
- + * general setting 50ms
- + */
- + mdelay(50);
- + } else
- + schedule_delayed_work(&priv->spk_work,
- + msecs_to_jiffies(spk_delay));
- + }
- + break;
- + case SND_SOC_DAPM_PRE_PMD:
- + mdelay(50);
- + if (priv->spk_gpio_used) {
- + gpio_set_value(priv->spk_gpio, 0);
- + msleep(50);
- + }
- +#ifdef ACX00_DAPM_LINEOUT
- + snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
- + (1<<LINEOUT_EN), (0<<LINEOUT_EN));
- +#endif
- + break;
- + default:
- + break;
- + }
- + return 0;
- +}
- +
- +/* AC_I2S_MIXER_SRC : 0x2114 */
- +static const struct snd_kcontrol_new i2sl_mixer_src[] = {
- + SOC_DAPM_SINGLE("I2SDACL Switch", AC_I2S_MIXER_SRC,
- + I2S_MIXERL_SRC_DAC, 1, 0),
- + SOC_DAPM_SINGLE("ADCL Switch", AC_I2S_MIXER_SRC,
- + I2S_MIXERL_SRC_ADC, 1, 0),
- +};
- +
- +static const struct snd_kcontrol_new i2sr_mixer_src[] = {
- + SOC_DAPM_SINGLE("I2SDACR Switch", AC_I2S_MIXER_SRC,
- + I2S_MIXERR_SRC_DAC, 1, 0),
- + SOC_DAPM_SINGLE("ADCR Switch", AC_I2S_MIXER_SRC,
- + I2S_MIXERR_SRC_ADC, 1, 0),
- +};
- +
- +/* AC_DAC_MIXER_SRC : 0x2202 */
- +static const struct snd_kcontrol_new dacl_mixer_src[] = {
- + SOC_DAPM_SINGLE("I2SDACL Switch", AC_DAC_MIXER_SRC,
- + DAC_MIXERL_SRC_DAC, 1, 0),
- + SOC_DAPM_SINGLE("ADCL Switch", AC_DAC_MIXER_SRC,
- + DAC_MIXERL_SRC_ADC, 1, 0),
- +};
- +
- +static const struct snd_kcontrol_new dacr_mixer_src[] = {
- + SOC_DAPM_SINGLE("I2SDACR Switch", AC_DAC_MIXER_SRC,
- + DAC_MIXERR_SRC_DAC, 1, 0),
- + SOC_DAPM_SINGLE("ADCR Switch", AC_DAC_MIXER_SRC,
- + DAC_MIXERR_SRC_ADC, 1, 0),
- +};
- +
- +/* AC_OUT_MIXER_SRC : 0x2222 */
- +static const struct snd_kcontrol_new left_output_mixer[] = {
- + SOC_DAPM_SINGLE("MIC1 Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERL_SRC_MIC1, 1, 0),
- + SOC_DAPM_SINGLE("MIC2 Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERL_SRC_MIC2, 1, 0),
- + SOC_DAPM_SINGLE("PhonePN Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERL_SRC_PHPN, 1, 0),
- + SOC_DAPM_SINGLE("PhoneN Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERL_SRC_PHN, 1, 0),
- + SOC_DAPM_SINGLE("LINEINL Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERL_SRC_LINEL, 1, 0),
- + SOC_DAPM_SINGLE("DACL Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERL_SRC_DACL, 1, 0),
- + SOC_DAPM_SINGLE("DACR Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERL_SRC_DACR, 1, 0),
- +};
- +
- +static const struct snd_kcontrol_new right_output_mixer[] = {
- + SOC_DAPM_SINGLE("MIC1 Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERR_SRC_MIC1, 1, 0),
- + SOC_DAPM_SINGLE("MIC2 Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERR_SRC_MIC2, 1, 0),
- + SOC_DAPM_SINGLE("PhonePN Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERR_SRC_PHPN, 1, 0),
- + SOC_DAPM_SINGLE("PhoneP Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERR_SRC_PHP, 1, 0),
- + SOC_DAPM_SINGLE("LINEINR Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERR_SRC_LINER, 1, 0),
- + SOC_DAPM_SINGLE("DACR Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERR_SRC_DACR, 1, 0),
- + SOC_DAPM_SINGLE("DACL Switch", AC_OUT_MIXER_SRC,
- + OUT_MIXERR_SRC_DACL, 1, 0),
- +};
- +
- +/* AC_LINEOUT_CTL : 0x2224 */
- +const char * const left_lineout_text[] = {
- + "Left OMixer", "LR OMixer",
- +};
- +
- +static const struct soc_enum left_lineout_enum =
- + SOC_ENUM_SINGLE(AC_LINEOUT_CTL, LINEL_SRC,
- + ARRAY_SIZE(left_lineout_text), left_lineout_text);
- +
- +static const struct snd_kcontrol_new left_lineout_mux =
- + SOC_DAPM_ENUM("Left LINEOUT Mux", left_lineout_enum);
- +
- +const char * const right_lineout_text[] = {
- + "Right OMixer", "LR OMixer",
- +};
- +
- +static const struct soc_enum right_lineout_enum =
- + SOC_ENUM_SINGLE(AC_LINEOUT_CTL, LINER_SRC,
- + ARRAY_SIZE(right_lineout_text), right_lineout_text);
- +
- +static const struct snd_kcontrol_new right_lineout_mux =
- + SOC_DAPM_ENUM("Right LINEOUT Mux", right_lineout_enum);
- +
- +/* AC_ADC_MIXER_SRC : 0x2322 */
- +static const struct snd_kcontrol_new left_input_mixer[] = {
- + SOC_DAPM_SINGLE("MIC1 Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERL_MIC1, 1, 0),
- + SOC_DAPM_SINGLE("MIC2 Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERL_MIC2, 1, 0),
- + SOC_DAPM_SINGLE("PhonePN Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERL_PHPN, 1, 0),
- + SOC_DAPM_SINGLE("PhoneN Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERL_PHN, 1, 0),
- + SOC_DAPM_SINGLE("LINEINL Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERL_LINEL, 1, 0),
- + SOC_DAPM_SINGLE("OMixerL Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERL_MIXL, 1, 0),
- + SOC_DAPM_SINGLE("OMixerR Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERL_MIXR, 1, 0),
- +};
- +
- +static const struct snd_kcontrol_new right_input_mixer[] = {
- + SOC_DAPM_SINGLE("MIC1 Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERR_MIC1, 1, 0),
- + SOC_DAPM_SINGLE("MIC2 Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERR_MIC2, 1, 0),
- + SOC_DAPM_SINGLE("PhonePN Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERR_PHPN, 1, 0),
- + SOC_DAPM_SINGLE("PhoneP Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERR_PHP, 1, 0),
- + SOC_DAPM_SINGLE("LINEINR Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERR_LINER, 1, 0),
- + SOC_DAPM_SINGLE("OMixerR Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERR_MIXR, 1, 0),
- + SOC_DAPM_SINGLE("OMixerL Switch", AC_ADC_MIXER_SRC,
- + ADC_MIXERR_MIXL, 1, 0),
- +};
- +
- +static const struct snd_soc_dapm_widget acx00_codec_dapm_widgets[] = {
- + SND_SOC_DAPM_AIF_IN_E("DACL", "Playback", 0, AC_DAC_CTL,
- + OUT_MIXER_DACL_EN, 0,
- + acx00_playback_event,
- + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- + SND_SOC_DAPM_AIF_IN_E("DACR", "Playback", 0,
- + AC_DAC_CTL, OUT_MIXER_DACR_EN, 0,
- + acx00_playback_event,
- + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- +
- + SND_SOC_DAPM_AIF_OUT_E("ADCL", "Capture", 0,
- + AC_ADC_MIC_CTL, ADCL_EN, 0,
- + acx00_capture_event,
- + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- + SND_SOC_DAPM_AIF_OUT_E("ADCR", "Capture", 0,
- + AC_ADC_MIC_CTL, ADCR_EN, 0,
- + acx00_capture_event,
- + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- +
- + SND_SOC_DAPM_MIXER("Left Output Mixer", AC_OUT_MIXER_CTL,
- + OUT_MIXER_LMIX_EN, 0,
- + left_output_mixer, ARRAY_SIZE(left_output_mixer)),
- +
- + SND_SOC_DAPM_MIXER("Right Output Mixer", AC_OUT_MIXER_CTL,
- + OUT_MIXER_RMIX_EN, 0, right_output_mixer,
- + ARRAY_SIZE(right_output_mixer)),
- +
- + SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0,
- + left_input_mixer, ARRAY_SIZE(left_input_mixer)),
- + SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
- + right_input_mixer, ARRAY_SIZE(right_input_mixer)),
- +
- + SND_SOC_DAPM_MIXER("Left DAC Mixer", AC_OUT_MIXER_CTL,
- + OUT_MIXER_DACL_EN, 0, dacl_mixer_src,
- + ARRAY_SIZE(dacl_mixer_src)),
- + SND_SOC_DAPM_MIXER("Right DAC Mixer", AC_OUT_MIXER_CTL,
- + OUT_MIXER_DACR_EN, 0, dacr_mixer_src,
- + ARRAY_SIZE(dacr_mixer_src)),
- +
- + SND_SOC_DAPM_MIXER("Left I2S Mixer", SND_SOC_NOPM,
- + 0, 0, i2sl_mixer_src, ARRAY_SIZE(i2sl_mixer_src)),
- + SND_SOC_DAPM_MIXER("Right I2S Mixer", SND_SOC_NOPM,
- + 0, 0, i2sr_mixer_src, ARRAY_SIZE(i2sr_mixer_src)),
- +
- + SND_SOC_DAPM_MUX("Left LINEOUT Mux", SND_SOC_NOPM,
- + 0, 0, &left_lineout_mux),
- + SND_SOC_DAPM_MUX("Right LINEOUT Mux", SND_SOC_NOPM,
- + 0, 0, &right_lineout_mux),
- +
- + SND_SOC_DAPM_PGA("MIC1 PGA", AC_ADC_MIC_CTL,
- + MIC1_GAIN_EN, 0, NULL, 0),
- + SND_SOC_DAPM_PGA("MIC2 PGA", AC_ADC_MIC_CTL,
- + MIC2_GAIN_EN, 0, NULL, 0),
- +
- + SND_SOC_DAPM_MICBIAS("MIC Bias", AC_MICBIAS_CTL,
- + MMBIAS_EN, 0),
- +
- + /* PHONEIN & PHONEOUT not enable in pin assign */
- + SND_SOC_DAPM_INPUT("PHONEINP"),
- + SND_SOC_DAPM_INPUT("PHONEINN"),
- + SND_SOC_DAPM_INPUT("PHONEINPN"),
- +
- + /* endpoint define */
- + SND_SOC_DAPM_LINE("LINEIN", NULL),
- + SND_SOC_DAPM_LINE("LINEOUT", acx00_lineout_event),
- + SND_SOC_DAPM_MIC("MIC1", NULL),
- + SND_SOC_DAPM_MIC("MIC2", NULL),
- +};
- +
- +static const struct snd_soc_dapm_route acx00_codec_dapm_routes[] = {
- + {"Left Output Mixer", "MIC1 Switch", "MIC1 PGA"},
- + {"Left Output Mixer", "MIC2 Switch", "MIC2 PGA"},
- + {"Left Output Mixer", "PhonePN Switch", "PHONEINPN"},
- + {"Left Output Mixer", "PhoneN Switch", "PHONEINN"},
- + {"Left Output Mixer", "LINEINL Switch", "LINEIN"},
- + {"Left Output Mixer", "DACR Switch", "Right DAC Mixer"},
- + {"Left Output Mixer", "DACL Switch", "Left DAC Mixer"},
- +
- + {"Right Output Mixer", "MIC1 Switch", "MIC1 PGA"},
- + {"Right Output Mixer", "MIC2 Switch", "MIC2 PGA"},
- + {"Right Output Mixer", "PhonePN Switch", "PHONEINPN"},
- + {"Right Output Mixer", "PhoneP Switch", "PHONEINP"},
- + {"Right Output Mixer", "LINEINR Switch", "LINEIN"},
- + {"Right Output Mixer", "DACR Switch", "Right DAC Mixer"},
- + {"Right Output Mixer", "DACL Switch", "Left DAC Mixer"},
- +
- + {"Left LINEOUT Mux", NULL, "Left Output Mixer"},
- + {"Left LINEOUT Mux", "LR OMixer", "Right Output Mixer"},
- + {"Right LINEOUT Mux", NULL, "Right Output Mixer"},
- + {"Right LINEOUT Mux", "LR OMixer", "Left Output Mixer"},
- +
- + {"Left Input Mixer", "MIC1 Switch", "MIC1 PGA"},
- + {"Left Input Mixer", "MIC2 Switch", "MIC2 PGA"},
- + {"Left Input Mixer", "PhonePN Switch", "PHONEINPN"},
- + {"Left Input Mixer", "PhoneN Switch", "PHONEINN"},
- + {"Left Input Mixer", "LINEINL Switch", "LINEIN"},
- + {"Left Input Mixer", "OMixerL Switch", "Left Output Mixer"},
- + {"Left Input Mixer", "OMixerR Switch", "Right Output Mixer"},
- +
- + {"Right Input Mixer", "MIC1 Switch", "MIC1 PGA"},
- + {"Right Input Mixer", "MIC2 Switch", "MIC2 PGA"},
- + {"Right Input Mixer", "PhonePN Switch", "PHONEINPN"},
- + {"Right Input Mixer", "PhoneP Switch", "PHONEINP"},
- + {"Right Input Mixer", "LINEINR Switch", "LINEIN"},
- + {"Right Input Mixer", "OMixerR Switch", "Right Output Mixer"},
- + {"Right Input Mixer", "OMixerL Switch", "Left Output Mixer"},
- +
- + {"Left I2S Mixer", "I2SDACL Switch", "DACL"},
- + {"Left I2S Mixer", "ADCL Switch", "Left Input Mixer"},
- +
- + {"Right I2S Mixer", "I2SDACR Switch", "DACR"},
- + {"Right I2S Mixer", "ADCR Switch", "Right Input Mixer"},
- +
- + {"Left DAC Mixer", "I2SDACL Switch", "DACL"},
- + {"Left DAC Mixer", "ADCL Switch", "Left Input Mixer"},
- +
- + {"Right DAC Mixer", "I2SDACR Switch", "DACR"},
- + {"Right DAC Mixer", "ADCR Switch", "Right Input Mixer"},
- +
- + {"ADCL", NULL, "Left I2S Mixer"},
- + {"ADCR", NULL, "Right I2S Mixer"},
- +
- + {"LINEOUT", NULL, "Left LINEOUT Mux"},
- + {"LINEOUT", NULL, "Right LINEOUT Mux"},
- +
- + {"MIC Bias", NULL, "MIC1"},
- + {"MIC Bias", NULL, "MIC2"},
- + {"MIC1 PGA", NULL, "MIC Bias"},
- + {"MIC2 PGA", NULL, "MIC Bias"},
- +};
- +
- +static void acx00_codec_txctrl_enable(struct snd_soc_component *component,
- + int enable)
- +{
- + pr_debug("Enter %s, enable %d\n", __func__, enable);
- + if (enable) {
- + snd_soc_component_update_bits(component, AC_I2S_CTL,
- + (1<<I2S_RX_EN), (1<<I2S_RX_EN));
- + } else {
- + snd_soc_component_update_bits(component, AC_I2S_CTL,
- + (1<<I2S_RX_EN), (0<<I2S_RX_EN));
- + }
- + pr_debug("End %s, enable %d\n", __func__, enable);
- +}
- +
- +static void acx00_codec_rxctrl_enable(struct snd_soc_component *component,
- + int enable)
- +{
- + pr_debug("Enter %s, enable %d\n", __func__, enable);
- + if (enable) {
- + snd_soc_component_update_bits(component, AC_I2S_CTL,
- + (1<<I2S_TX_EN), (1<<I2S_TX_EN));
- + } else {
- + snd_soc_component_update_bits(component, AC_I2S_CTL,
- + (1<<I2S_TX_EN), (0<<I2S_TX_EN));
- + }
- + pr_debug("End %s, enable %d\n", __func__, enable);
- +}
- +
- +int acx00_reg_read(struct ac200_dev *acx00, unsigned short reg)
- +{
- + unsigned int val;
- + int ret;
- +
- + ret = regmap_read(acx00->regmap, reg, &val);
- +
- + if (ret < 0)
- + return ret;
- + else
- + return val;
- +}
- +
- +int acx00_reg_write(struct ac200_dev *acx00, unsigned short reg, unsigned short val)
- +{
- + return regmap_write(acx00->regmap, reg, val);
- +}
- +
- +static void acx00_codec_init(struct snd_soc_component *component)
- +{
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- +
- + acx00_reg_write(priv->acx00, 0x50, 0x82b1);
- + acx00_reg_write(priv->acx00, 0xc, 0xce01);
- +
- + /* acx00_codec sysctl init */
- + acx00_reg_write(priv->acx00, 0x0010, 0x03);
- + acx00_reg_write(priv->acx00, 0x0012, 0x01);
- +
- + /* The bit3 need to setup to 1 for bias current. */
- + snd_soc_component_update_bits(component, AC_MICBIAS_CTL,
- + (0x1 << ADDA_BIAS_CUR), (0x1 << ADDA_BIAS_CUR));
- +
- + /* enable the output & global enable bit */
- + snd_soc_component_update_bits(component, AC_I2S_CTL,
- + (1<<I2S_SDO0_EN), (1<<I2S_SDO0_EN));
- + snd_soc_component_update_bits(component, AC_I2S_CTL, (1<<I2S_GEN), (1<<I2S_GEN));
- +
- + /* Default setting slot width as 32 bit for I2S */
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (7<<I2S_FMT_SLOT_WIDTH), (7<<I2S_FMT_SLOT_WIDTH));
- +
- + /* default setting 0xA0A0 for ADC & DAC Volume */
- + snd_soc_component_write(component, AC_I2S_DAC_VOL, ACX00_DEF_VOL);
- + snd_soc_component_write(component, AC_I2S_ADC_VOL, ACX00_DEF_VOL);
- +
- + /* Enable HPF for high pass filter */
- + snd_soc_component_update_bits(component, AC_DAC_CTL,
- + (1<<DAC_CTL_HPF_EN), (1<<DAC_CTL_HPF_EN));
- +
- + /* LINEOUT ANTI POP & Click noise */
- + snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
- + (0x7<<LINE_ANTI_TIME), (0x3<<LINE_ANTI_TIME));
- + snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
- + (0x3<<LINE_SLOPE_SEL), (0x3<<LINE_SLOPE_SEL));
- +
- + /* enable & setting adc convert delay time */
- + snd_soc_component_update_bits(component, AC_ADC_CTL, (0x3<<ADC_DELAY_TIME),
- + (0x3<<ADC_DELAY_TIME));
- + snd_soc_component_update_bits(component, AC_ADC_CTL, (1<<ADC_DELAY_EN),
- + (1<<ADC_DELAY_EN));
- +
- + if (priv->spk_gpio_used) {
- + snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
- + (1<<LINEL_SRC_EN), (1<<LINEL_SRC_EN));
- + snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
- + (1<<LINER_SRC_EN), (1<<LINER_SRC_EN));
- + priv->enable = 1;
- + }
- +#ifndef ACX00_DAPM_LINEOUT
- + snd_soc_component_update_bits(component, AC_LINEOUT_CTL, (1<<LINEOUT_EN),
- + (1<<LINEOUT_EN));
- +#endif
- +
- + snd_soc_component_update_bits(component, AC_LINEOUT_CTL, 0x1f, 0x0f);
- + snd_soc_component_write(component, AC_DAC_MIXER_SRC, 0x2200);
- + snd_soc_component_write(component, AC_OUT_MIXER_SRC, 0x0202);
- +}
- +
- +static int acx00_codec_hw_params(struct snd_pcm_substream *substream,
- + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
- +{
- + struct snd_soc_component *component = dai->component;
- + int i;
- +
- + switch (params_format(params)) {
- + case SNDRV_PCM_FORMAT_S16_LE:
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (7<<I2S_FMT_SAMPLE), (3<<I2S_FMT_SAMPLE));
- + break;
- + case SNDRV_PCM_FORMAT_S24_LE:
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (7<<I2S_FMT_SAMPLE), (5<<I2S_FMT_SAMPLE));
- + break;
- + case SNDRV_PCM_FORMAT_S32_LE:
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (7<<I2S_FMT_SAMPLE), (7<<I2S_FMT_SAMPLE));
- + break;
- + default:
- + dev_err(component->dev, "unrecognized format support\n");
- + break;
- + }
- + for (i = 0; i < ARRAY_SIZE(sample_rate_conv); i++) {
- + if (sample_rate_conv[i].samplerate == params_rate(params)) {
- + snd_soc_component_update_bits(component, AC_SYS_SR_CTL,
- + (SYS_SR_MASK<<SYS_SR_BIT),
- + (sample_rate_conv[i].rate_bit<<SYS_SR_BIT));
- + }
- + }
- +
- + return 0;
- +}
- +
- +static int acx00_codec_dai_set_sysclk(struct snd_soc_dai *codec_dai,
- + int clk_id, unsigned int freq, int dir)
- +{
- + return 0;
- +}
- +
- +static int acx00_codec_dai_set_fmt(struct snd_soc_dai *codec_dai,
- + unsigned int fmt)
- +{
- + struct acx00_priv *priv = snd_soc_dai_get_drvdata(codec_dai);
- + struct snd_soc_component *component = priv->component;
- +
- + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- + /* codec clk & FRM master */
- + case SND_SOC_DAIFMT_CBM_CFM:
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x1<<I2S_BCLK_OUT), (0x1<<I2S_BCLK_OUT));
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x1<<I2S_LRCK_OUT), (0x1<<I2S_LRCK_OUT));
- + break;
- + /* codec clk & FRM slave */
- + case SND_SOC_DAIFMT_CBS_CFS:
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x1<<I2S_BCLK_OUT), 0x0<<I2S_BCLK_OUT);
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x1<<I2S_LRCK_OUT), 0x0<<I2S_LRCK_OUT);
- + break;
- + }
- +
- + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- + case SND_SOC_DAIFMT_I2S:
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x3FF<<I2S_LRCK_PERIOD),
- + (0x1F<<I2S_LRCK_PERIOD));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x3<<I2S_FMT_MODE), (0x1<<I2S_FMT_MODE));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_TX_OFFSET),
- + (0x1<<I2S_FMT_TX_OFFSET));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_RX_OFFSET),
- + (0x1<<I2S_FMT_RX_OFFSET));
- + break;
- + case SND_SOC_DAIFMT_RIGHT_J:
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x3FF<<I2S_LRCK_PERIOD),
- + (0x1F<<I2S_LRCK_PERIOD));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x3<<I2S_FMT_MODE), (0x2<<I2S_FMT_MODE));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_TX_OFFSET),
- + (0x0<<I2S_FMT_TX_OFFSET));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_TX_OFFSET),
- + (0x0<<I2S_FMT_RX_OFFSET));
- + break;
- + case SND_SOC_DAIFMT_LEFT_J:
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x3FF<<I2S_LRCK_PERIOD),
- + (0x1F<<I2S_LRCK_PERIOD));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x3<<I2S_FMT_MODE), (0x1<<I2S_FMT_MODE));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_TX_OFFSET),
- + (0x0<<I2S_FMT_TX_OFFSET));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_RX_OFFSET),
- + (0x0<<I2S_FMT_RX_OFFSET));
- + break;
- + case SND_SOC_DAIFMT_DSP_A:
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x3FF<<I2S_LRCK_PERIOD),
- + (0x3F<<I2S_LRCK_PERIOD));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x3<<I2S_FMT_MODE), (0x0<<I2S_FMT_MODE));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_TX_OFFSET),
- + (0x1<<I2S_FMT_TX_OFFSET));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_RX_OFFSET),
- + (0x1<<I2S_FMT_RX_OFFSET));
- + break;
- + case SND_SOC_DAIFMT_DSP_B:
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (0x3FF<<I2S_LRCK_PERIOD),
- + (0x3F<<I2S_LRCK_PERIOD));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x3<<I2S_FMT_MODE), (0x0<<I2S_FMT_MODE));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_TX_OFFSET),
- + (0x0<<I2S_FMT_TX_OFFSET));
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_RX_OFFSET),
- + (0x0<<I2S_FMT_RX_OFFSET));
- + break;
- + default:
- + dev_err(component->dev, "format setting failed\n");
- + break;
- + }
- +
- + switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- + case SND_SOC_DAIFMT_NB_NF:
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_BCLK_POLAR),
- + (0x0<<I2S_FMT_BCLK_POLAR));
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_LRCK_POLAR),
- + (0x0<<I2S_FMT_LRCK_POLAR));
- + break;
- + case SND_SOC_DAIFMT_NB_IF:
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_BCLK_POLAR),
- + (0x0<<I2S_FMT_BCLK_POLAR));
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_LRCK_POLAR),
- + (0x1<<I2S_FMT_LRCK_POLAR));
- + break;
- + case SND_SOC_DAIFMT_IB_NF:
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_BCLK_POLAR),
- + (0x1<<I2S_FMT_BCLK_POLAR));
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_LRCK_POLAR),
- + (0x0<<I2S_FMT_LRCK_POLAR));
- + break;
- + case SND_SOC_DAIFMT_IB_IF:
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_BCLK_POLAR),
- + (0x1<<I2S_FMT_BCLK_POLAR));
- + snd_soc_component_update_bits(component, AC_I2S_FMT1,
- + (0x1<<I2S_FMT_LRCK_POLAR),
- + (0x1<<I2S_FMT_LRCK_POLAR));
- + break;
- + default:
- + dev_err(component->dev, "invert clk setting failed\n");
- + return -EINVAL;
- + }
- + return 0;
- +}
- +
- +static int acx00_codec_dai_set_clkdiv(struct snd_soc_dai *codec_dai,
- + int clk_id, int clk_div)
- +{
- + struct acx00_priv *priv = snd_soc_dai_get_drvdata(codec_dai);
- + struct snd_soc_component *component = priv->component;
- + unsigned int bclk_div;
- + /*
- + * when PCM mode, setting as 64fs, when I2S mode as 32fs,
- + * then two channel, then just as 64fs
- + */
- + unsigned int div_ratio = clk_div / 64;
- +
- + switch (div_ratio) {
- + case 1:
- + bclk_div = I2S_BCLK_DIV_1;
- + break;
- + case 2:
- + bclk_div = I2S_BCLK_DIV_2;
- + break;
- + case 4:
- + bclk_div = I2S_BCLK_DIV_3;
- + break;
- + case 6:
- + bclk_div = I2S_BCLK_DIV_4;
- + break;
- + case 8:
- + bclk_div = I2S_BCLK_DIV_5;
- + break;
- + case 12:
- + bclk_div = I2S_BCLK_DIV_6;
- + break;
- + case 16:
- + bclk_div = I2S_BCLK_DIV_7;
- + break;
- + case 24:
- + bclk_div = I2S_BCLK_DIV_8;
- + break;
- + case 32:
- + bclk_div = I2S_BCLK_DIV_9;
- + break;
- + case 48:
- + bclk_div = I2S_BCLK_DIV_10;
- + break;
- + case 64:
- + bclk_div = I2S_BCLK_DIV_11;
- + break;
- + case 96:
- + bclk_div = I2S_BCLK_DIV_12;
- + break;
- + case 128:
- + bclk_div = I2S_BCLK_DIV_13;
- + break;
- + case 176:
- + bclk_div = I2S_BCLK_DIV_14;
- + break;
- + case 192:
- + bclk_div = I2S_BCLK_DIV_15;
- + break;
- + default:
- + dev_err(component->dev, "setting blck div failed\n");
- + break;
- + }
- +
- + snd_soc_component_update_bits(component, AC_I2S_CLK,
- + (I2S_BCLK_DIV_MASK<<I2S_BLCK_DIV),
- + (bclk_div<<I2S_BLCK_DIV));
- + return 0;
- +}
- +
- +static int acx00_codec_startup(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *codec_dai)
- +{
- + return 0;
- +}
- +
- +static bool acx00_loop_en;
- +module_param(acx00_loop_en, bool, 0644);
- +MODULE_PARM_DESC(acx00_loop_en, "ACX00-Codec audio loopback debug(Y=enable, N=disable)");
- +
- +static int acx00_codec_trigger(struct snd_pcm_substream *substream,
- + int cmd, struct snd_soc_dai *codec_dai)
- +{
- + struct snd_soc_component *component = codec_dai->component;
- + return 0;
- +}
- +
- +static int acx00_codec_prepare(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *codec_dai)
- +{
- + struct snd_soc_component *component = codec_dai->component;
- +
- + snd_soc_component_update_bits(component, AC_SYS_CLK_CTL,
- + (0x1<<SYS_CLK_I2S), (0x1<<SYS_CLK_I2S));
- + snd_soc_component_update_bits(component, AC_SYS_MOD_RST,
- + (0x1<<MOD_RST_I2S), (0x1<<MOD_RST_I2S));
- +
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- + if (acx00_loop_en)
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_LOOP),
- + (0x1<<I2S_FMT_LOOP));
- + else
- + snd_soc_component_update_bits(component, AC_I2S_FMT0,
- + (0x1<<I2S_FMT_LOOP),
- + (0x0<<I2S_FMT_LOOP));
- + acx00_codec_txctrl_enable(component, 1);
- + } else
- + acx00_codec_rxctrl_enable(component, 1);
- + return 0;
- +}
- +
- +static int acx00_codec_digital_mute(struct snd_soc_dai *codec_dai,
- + int mute)
- +{
- + struct snd_soc_component *component = codec_dai->component;
- +
- + if (mute)
- + snd_soc_component_write(component, AC_I2S_DAC_VOL, 0);
- + else
- + snd_soc_component_write(component, AC_I2S_DAC_VOL, ACX00_DEF_VOL);
- + return 0;
- +}
- +
- +static void acx00_codec_shutdown(struct snd_pcm_substream *substream,
- + struct snd_soc_dai *dai)
- +{
- + struct snd_soc_component *component = dai->component;
- +
- + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- + acx00_codec_txctrl_enable(component, 0);
- + else
- + acx00_codec_rxctrl_enable(component, 0);
- +}
- +
- +static const struct snd_soc_dai_ops acx00_codec_dai_ops = {
- + .hw_params = acx00_codec_hw_params,
- + .shutdown = acx00_codec_shutdown,
- +// .digital_mute = acx00_codec_digital_mute,
- + .set_sysclk = acx00_codec_dai_set_sysclk,
- + .set_fmt = acx00_codec_dai_set_fmt,
- + .set_clkdiv = acx00_codec_dai_set_clkdiv,
- + .startup = acx00_codec_startup,
- + .trigger = acx00_codec_trigger,
- + .prepare = acx00_codec_prepare,
- +};
- +
- +static struct snd_soc_dai_driver acx00_codec_dai[] = {
- + {
- + .name = "acx00-dai",
- + .playback = {
- + .stream_name = "Playback",
- + .channels_min = 1,
- + .channels_max = 2,
- + .rates = SNDRV_PCM_RATE_8000_192000
- + | SNDRV_PCM_RATE_KNOT,
- + .formats = SNDRV_PCM_FMTBIT_S16_LE
- + | SNDRV_PCM_FMTBIT_S24_LE
- + | SNDRV_PCM_FMTBIT_S32_LE,
- + },
- +
- + .capture = {
- + .stream_name = "Capture",
- + .channels_min = 1,
- + .channels_max = 2,
- + .rates = SNDRV_PCM_RATE_8000_192000
- + | SNDRV_PCM_RATE_KNOT,
- + .formats = SNDRV_PCM_FMTBIT_S16_LE
- + | SNDRV_PCM_FMTBIT_S24_LE
- + | SNDRV_PCM_FMTBIT_S32_LE,
- + },
- +
- + .ops = &acx00_codec_dai_ops,
- + },
- +};
- +
- +static void acx00_codec_resume_work(struct work_struct *work)
- +{
- + struct acx00_priv *priv = container_of(work,
- + struct acx00_priv, resume_work.work);
- +
- + acx00_codec_init(priv->component);
- +}
- +
- +static int acx00_codec_probe(struct snd_soc_component *component)
- +{
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
- + int ret = 0;
- +
- + mutex_init(&priv->mutex);
- +
- + priv->component = component;
- +#if 0
- + /* Add virtual switch */
- + ret = snd_soc_add_component_controls(component, acx00_codec_controls,
- + ARRAY_SIZE(acx00_codec_controls));
- + if (ret) {
- + pr_err("[audio-codec] Failed to register audio mode control, will continue without it.\n");
- + }
- + snd_soc_dapm_new_controls(dapm, acx00_codec_dapm_widgets, ARRAY_SIZE(acx00_codec_dapm_widgets));
- + snd_soc_dapm_add_routes(dapm, acx00_codec_dapm_routes, ARRAY_SIZE(acx00_codec_dapm_routes));
- +#endif
- + /* using late_initcall to wait 120ms acx00-core to make chip reset */
- + acx00_codec_init(component);
- + INIT_DELAYED_WORK(&priv->spk_work, acx00_spk_enable);
- + INIT_DELAYED_WORK(&priv->resume_work, acx00_codec_resume_work);
- + return 0;
- +}
- +
- +static void acx00_codec_remove(struct snd_soc_component *component)
- +{
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- +
- + cancel_delayed_work_sync(&priv->spk_work);
- + cancel_delayed_work_sync(&priv->resume_work);
- +}
- +
- +static unsigned int acx00_codec_read(struct snd_soc_component *component,
- + unsigned int reg)
- +{
- + unsigned int data;
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- +
- + /* Device I/O API */
- + data = acx00_reg_read(priv->acx00, reg);
- + return data;
- +}
- +
- +static int acx00_codec_write(struct snd_soc_component *component,
- + unsigned int reg, unsigned int value)
- +{
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- +
- + return acx00_reg_write(priv->acx00, reg, value);
- +}
- +
- +static int sunxi_gpio_iodisable(u32 gpio)
- +{
- + char pin_name[8];
- + u32 config, ret;
- +#if 0
- + sunxi_gpio_to_name(gpio, pin_name);
- + config = 7 << 16;
- + ret = pin_config_set(SUNXI_PINCTRL, pin_name, config);
- +#endif
- + return ret;
- +}
- +
- +static int acx00_codec_suspend(struct snd_soc_component *component)
- +{
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- +
- + pr_debug("Enter %s\n", __func__);
- +
- + clk_disable_unprepare(priv->clk);
- +
- + /* PA_CTRL first setting low state, then make it iodisabled */
- + if (priv->spk_gpio_used) {
- + sunxi_gpio_iodisable(priv->spk_gpio);
- + msleep(30);
- + }
- +
- + /*
- + * when codec suspend, then the register reset, if auto reset produce
- + * Pop & Click noise, then we should cut down the LINEOUT in this town.
- + */
- + if (priv->enable) {
- + snd_soc_component_update_bits(component, AC_LINEOUT_CTL,
- + (1<<LINEOUT_EN), (0<<LINEOUT_EN));
- + snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
- + (1<<LINEL_SRC_EN), (0<<LINEL_SRC_EN));
- + snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
- + (1<<LINER_SRC_EN), (0<<LINER_SRC_EN));
- + priv->enable = 0;
- + }
- +
- + pr_debug("Exit %s\n", __func__);
- +
- + return 0;
- +}
- +
- +static int acx00_codec_resume(struct snd_soc_component *component)
- +{
- + struct acx00_priv *priv = snd_soc_component_get_drvdata(component);
- +
- + pr_debug("Enter %s\n", __func__);
- +
- + if (clk_prepare_enable(priv->clk)) {
- + dev_err(component->dev, "codec resume clk failed\n");
- + return -EBUSY;
- + }
- +
- + schedule_delayed_work(&priv->resume_work, msecs_to_jiffies(300));
- +
- + if (priv->spk_gpio_used) {
- + gpio_direction_output(priv->spk_gpio, 1);
- + gpio_set_value(priv->spk_gpio, 0);
- + }
- +
- + pr_debug("Exit %s\n", __func__);
- +
- + return 0;
- +}
- +
- +
- +static int acx00_codec_set_bias_level(struct snd_soc_component *component,
- + enum snd_soc_bias_level level)
- +{
- + component->dapm.bias_level = level;
- + return 0;
- +}
- +
- +struct label {
- + const char *name;
- + int value;
- +};
- +
- +#define LABEL(constant) { #constant, constant }
- +#define LABEL_END { NULL, -1 }
- +
- +static struct label reg_labels[] = {
- + LABEL(AC_SYS_CLK_CTL),
- + LABEL(AC_SYS_MOD_RST),
- + LABEL(AC_SYS_SR_CTL),
- + LABEL(AC_I2S_CTL),
- + LABEL(AC_I2S_CLK),
- + LABEL(AC_I2S_FMT0),
- + LABEL(AC_I2S_FMT1),
- + LABEL(AC_I2S_MIXER_SRC),
- + LABEL(AC_I2S_MIXER_GAIN),
- + LABEL(AC_I2S_DAC_VOL),
- + LABEL(AC_I2S_ADC_VOL),
- + LABEL(AC_DAC_CTL),
- + LABEL(AC_DAC_MIXER_SRC),
- + LABEL(AC_DAC_MIXER_GAIN),
- + LABEL(AC_OUT_MIXER_CTL),
- + LABEL(AC_OUT_MIXER_SRC),
- + LABEL(AC_LINEOUT_CTL),
- + LABEL(AC_ADC_CTL),
- + LABEL(AC_MICBIAS_CTL),
- + LABEL(AC_ADC_MIC_CTL),
- + LABEL(AC_ADC_MIXER_SRC),
- + LABEL(AC_BIAS_CTL),
- + LABEL(AC_ANALOG_PROF_CTL),
- + LABEL_END,
- +};
- +
- +static ssize_t show_audio_reg(struct device *dev,
- + struct device_attribute *attr, char *buf)
- +{
- + struct acx00_priv *priv = dev_get_drvdata(dev);
- + int count = 0, i = 0;
- + unsigned int reg_val;
- +
- + count += sprintf(buf, "dump audio reg:\n");
- +
- + while (reg_labels[i].name != NULL) {
- + reg_val = acx00_reg_read(priv->acx00, reg_labels[i].value);
- + count += sprintf(buf + count, "%s 0x%x: 0x%x\n",
- + reg_labels[i].name, (reg_labels[i].value), reg_val);
- + i++;
- + }
- +
- + return count;
- +}
- +
- +/*
- + * param 1: 0 read;1 write
- + * param 2: 1 digital reg; 2 analog reg
- + * param 3: reg value;
- + * param 4: write value;
- + * read:
- + * echo 0,1,0x00> audio_reg
- + * echo 0,2,0x00> audio_reg
- + * write:
- + * echo 1,1,0x00,0xa > audio_reg
- + * echo 1,2,0x00,0xff > audio_reg
- +*/
- +static ssize_t store_audio_reg(struct device *dev,
- + struct device_attribute *attr, const char *buf, size_t count)
- +{
- + int ret;
- + int rw_flag;
- + unsigned int input_reg_val = 0;
- + int input_reg_group = 0;
- + unsigned int input_reg_offset = 0;
- + struct acx00_priv *priv = dev_get_drvdata(dev);
- +
- + ret = sscanf(buf, "%d,%d,0x%x,0x%x", &rw_flag, &input_reg_group,
- + &input_reg_offset, &input_reg_val);
- + dev_info(dev, "ret:%d, reg_group:%d, reg_offset:%d, reg_val:0x%x\n",
- + ret, input_reg_group, input_reg_offset, input_reg_val);
- +
- + if (input_reg_group != 1) {
- + pr_err("not exist reg group\n");
- + ret = count;
- + goto out;
- + }
- + if (!(rw_flag == 1 || rw_flag == 0)) {
- + pr_err("not rw_flag\n");
- + ret = count;
- + goto out;
- + }
- +
- + if (rw_flag) {
- + acx00_reg_write(priv->acx00, input_reg_offset, input_reg_val);
- + } else {
- + input_reg_val = acx00_reg_read(priv->acx00, input_reg_offset);
- + dev_info(dev, "\n\n Reg[0x%x] : 0x%04x\n\n",
- + input_reg_offset, input_reg_val);
- + }
- + ret = count;
- +
- +out:
- + return ret;
- +}
- +
- +static DEVICE_ATTR(audio_reg, 0644, show_audio_reg, store_audio_reg);
- +
- +static struct attribute *audio_debug_attrs[] = {
- + &dev_attr_audio_reg.attr,
- + NULL,
- +};
- +
- +static struct attribute_group audio_debug_attr_group = {
- + .name = "audio_reg_debug",
- + .attrs = audio_debug_attrs,
- +};
- +
- +static struct snd_soc_component_driver soc_codec_driver_acx00 = {
- + .probe = acx00_codec_probe,
- + .remove = acx00_codec_remove,
- + .suspend = acx00_codec_suspend,
- + .resume = acx00_codec_resume,
- + .read = acx00_codec_read,
- + .write = acx00_codec_write,
- +// .ignore_pmdown_time = 1,
- + .set_bias_level = acx00_codec_set_bias_level,
- + .controls = acx00_codec_controls,
- + .num_controls = ARRAY_SIZE(acx00_codec_controls),
- + .dapm_widgets = acx00_codec_dapm_widgets,
- + .num_dapm_widgets = ARRAY_SIZE(acx00_codec_dapm_widgets),
- + .dapm_routes = acx00_codec_dapm_routes,
- + .num_dapm_routes = ARRAY_SIZE(acx00_codec_dapm_routes),
- +};
- +
- +/* through acx00 is part of mfd devices, after the mfd */
- +static int acx00_codec_dev_probe(struct platform_device *pdev)
- +{
- + struct acx00_priv *priv;
- + int ret;
- + struct device_node *np = of_find_compatible_node(NULL, NULL, "allwinner,ac200_codec");
- +
- + priv = devm_kzalloc(&pdev->dev, sizeof(struct acx00_priv), GFP_KERNEL);
- + if (!priv) {
- + dev_err(&pdev->dev, "acx00 codec priv mem alloc failed\n");
- + return -ENOMEM;
- + }
- +
- + platform_set_drvdata(pdev, priv);
- + priv->acx00 = dev_get_drvdata(pdev->dev.parent);
- +
- + if (np) {
- + ret = of_get_named_gpio(np, "gpio-spk", 0);
- + if (ret >= 0) {
- + priv->spk_gpio_used = 1;
- + priv->spk_gpio = ret;
- + if (!gpio_is_valid(priv->spk_gpio)) {
- + dev_err(&pdev->dev, "gpio-spk is valid\n");
- + ret = -EINVAL;
- + goto err_devm_kfree;
- + } else {
- + ret = devm_gpio_request(&pdev->dev,
- + priv->spk_gpio, "SPK");
- + if (ret) {
- + dev_err(&pdev->dev,
- + "failed request gpio-spk\n");
- + ret = -EBUSY;
- + goto err_devm_kfree;
- + } else {
- + gpio_direction_output(priv->spk_gpio,
- + 1);
- + gpio_set_value(priv->spk_gpio, 0);
- + }
- + }
- + } else {
- + priv->spk_gpio_used = 0;
- + }
- +
- + ret = of_get_named_gpio(np, "gpio-switch", 0);
- + if (ret >= 0) {
- + priv->switch_gpio = ret;
- + if (!gpio_is_valid(priv->switch_gpio)) {
- + dev_err(&pdev->dev, "gpio-switch is valid\n");
- + ret = -EINVAL;
- + goto err_devm_kfree;
- + } else {
- + ret = devm_gpio_request(&pdev->dev, priv->switch_gpio, "SWITCH");
- + if (ret) {
- + dev_err(&pdev->dev,
- + "failed request gpio-switch\n");
- + ret = -EBUSY;
- + goto err_devm_kfree;
- + } else {
- + gpio_direction_output(priv->switch_gpio, 1);
- + gpio_set_value(priv->switch_gpio, 1);
- + }
- + }
- + }
- + }
- +
- + ret = snd_soc_register_component(&pdev->dev, &soc_codec_driver_acx00,
- + acx00_codec_dai, ARRAY_SIZE(acx00_codec_dai));
- +
- + if (ret < 0)
- + dev_err(&pdev->dev, "Failed register acx00: %d\n", ret);
- +
- + ret = sysfs_create_group(&pdev->dev.kobj, &audio_debug_attr_group);
- + if (ret)
- + dev_warn(&pdev->dev, "failed to create attr group\n");
- +
- + return 0;
- +
- +err_devm_kfree:
- + devm_kfree(&pdev->dev, priv);
- + return ret;
- +}
- +
- +/* Mark this space to clear the LINEOUT & gpio */
- +static void acx00_codec_dev_shutdown(struct platform_device *pdev)
- +{
- + struct acx00_priv *priv = platform_get_drvdata(pdev);
- +
- + if (priv->spk_gpio_used)
- + gpio_set_value(priv->spk_gpio, 0);
- +}
- +
- +static int acx00_codec_dev_remove(struct platform_device *pdev)
- +{
- + struct acx00_priv *priv = platform_get_drvdata(pdev);
- +
- +#ifndef ACX00_DAPM_LINEOUT
- + /*
- + snd_soc_component_update_bits(priv->component, AC_LINEOUT_CTL,
- + (1<<LINEOUT_EN), (0<<LINEOUT_EN));
- + */
- +#endif
- + snd_soc_unregister_component(&pdev->dev);
- + clk_disable_unprepare(priv->clk);
- + devm_kfree(&pdev->dev, priv);
- + return 0;
- +}
- +
- +static const struct of_device_id acx00_codec_match[] = {
- + { .compatible = "x-powers,ac200-codec" },
- + { }
- +};
- +MODULE_DEVICE_TABLE(of, acx00_codec_match);
- +
- +static struct platform_driver acx00_codec_driver = {
- + .driver = {
- + .name = "acx00-codec",
- + .of_match_table = acx00_codec_match,
- + },
- + .probe = acx00_codec_dev_probe,
- + .remove = acx00_codec_dev_remove,
- + .shutdown = acx00_codec_dev_shutdown,
- +};
- +
- +static int __init acx00_codec_driver_init(void)
- +{
- + return platform_driver_register(&acx00_codec_driver);
- +}
- +
- +static void __exit acx00_codec_driver_exit(void)
- +{
- + platform_driver_unregister(&acx00_codec_driver);
- +}
- +late_initcall(acx00_codec_driver_init);
- +module_exit(acx00_codec_driver_exit);
- +
- +MODULE_LICENSE("GPL");
- +MODULE_DESCRIPTION("SUNXI ASoC ACX00 Codec Driver");
- +MODULE_AUTHOR("wolfgang huang");
- +MODULE_ALIAS("platform:acx00-codec");
- +
- diff --git a/sound/soc/codecs/acx00.h b/sound/soc/codecs/acx00.h
- new file mode 100644
- index 000000000..4d53184fc
- --- /dev/null
- +++ b/sound/soc/codecs/acx00.h
- @@ -0,0 +1,357 @@
- +/*
- + * sound\soc\codecs\acx00.h
- + * (C) Copyright 2012-2016
- + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- + * Wolfgang Huang <huangjinhui@allwinnertech.com>
- + *
- + * some simple description for this code
- + *
- + * This program is free software; you can redistribute it and/or
- + * modify it under the terms of the GNU General Public License as
- + * published by the Free Software Foundation; either version 2 of
- + * the License, or (at your option) any later version.
- + *
- + */
- +
- +#ifndef __ACX00_H_
- +#define __ACX00_H_
- +
- +/* ACX00 register offset list */
- +#define AC_SYS_CLK_CTL 0x2000
- +#define AC_SYS_MOD_RST 0x2002
- +#define AC_SYS_SR_CTL 0x2004
- +/* Left blank */
- +#define AC_I2S_CTL 0x2100
- +#define AC_I2S_CLK 0x2102
- +#define AC_I2S_FMT0 0x2104
- +/* Left blank */
- +#define AC_I2S_FMT1 0x2108
- +/* Left blank */
- +#define AC_I2S_MIXER_SRC 0x2114
- +#define AC_I2S_MIXER_GAIN 0x2116
- +#define AC_I2S_DAC_VOL 0x2118
- +#define AC_I2S_ADC_VOL 0x211A
- +/* Left blank */
- +#define AC_DAC_CTL 0x2200
- +#define AC_DAC_MIXER_SRC 0x2202
- +#define AC_DAC_MIXER_GAIN 0x2204
- +/* Left blank */
- +#define AC_OUT_MIXER_CTL 0x2220
- +#define AC_OUT_MIXER_SRC 0x2222
- +#define AC_LINEOUT_CTL 0x2224
- +/* Left blank */
- +#define AC_ADC_CTL 0x2300
- +/* Left blank */
- +#define AC_MICBIAS_CTL 0x2310
- +/* Left blank */
- +#define AC_ADC_MIC_CTL 0x2320
- +#define AC_ADC_MIXER_SRC 0x2322
- +/* Left blank */
- +#define AC_BIAS_CTL 0x232A
- +#define AC_ANALOG_PROF_CTL 0x232C
- +/* Left blank */
- +#define AC_ADC_DAPL_CTRL 0x2500
- +#define AC_ADC_DAPR_CTRL 0x2502
- +#define AC_ADC_DAPLSTA 0x2504
- +#define AC_ADC_DAPRSTA 0x2506
- +#define AC_ADC_DAP_LTL 0x2508
- +#define AC_ADC_DAP_RTL 0x250A
- +#define AC_ADC_DAP_LHAC 0x250C
- +#define AC_ADC_DAP_LLAC 0x250E
- +#define AC_ADC_DAP_RHAC 0x2510
- +#define AC_ADC_DAP_RLAC 0x2512
- +#define AC_ADC_DAP_LDT 0x2514
- +#define AC_ADC_DAP_LAT 0x2516
- +#define AC_ADC_DAP_RDT 0x2518
- +#define AC_ADC_DAP_RAT 0x251A
- +#define AC_ADC_DAP_NTH 0x251C
- +#define AC_ADC_DAP_LHNAC 0x251E
- +#define AC_ADC_DAP_LLNAC 0x2520
- +#define AC_ADC_DAP_RHNAC 0x2522
- +#define AC_ADC_DAP_RLNAC 0x2524
- +#define AC_ADC_DAP_HHPFC 0x2526
- +#define AC_ADC_DAP_LHPFC 0x2528
- +#define AC_ADC_DAP_OPT 0x252A
- +/* Left blank */
- +#define AC_AGC_SEL 0x2480
- +/* Left blank */
- +#define AC_ADC_DAPL_CTRL 0x2500
- +#define AC_ADC_DAPR_CTRL 0x2502
- +#define AC_ADC_DAPLSTA 0x2504
- +#define AC_ADC_DAPRSTA 0x2506
- +#define AC_ADC_DAP_LTL 0x2508
- +#define AC_ADC_DAP_RTL 0x250A
- +#define AC_ADC_DAP_LHAC 0x250C
- +#define AC_ADC_DAP_LLAC 0x250E
- +#define AC_ADC_DAP_RHAC 0x2510
- +#define AC_ADC_DAP_RLAC 0x2512
- +#define AC_ADC_DAP_LDT 0x2514
- +#define AC_ADC_DAP_LAT 0x2516
- +#define AC_ADC_DAP_RDT 0x2518
- +#define AC_ADC_DAP_RAT 0x251A
- +#define AC_ADC_DAP_NTH 0x251C
- +#define AC_ADC_DAP_LHNAC 0x251E
- +#define AC_ADC_DAP_LLNAC 0x2520
- +#define AC_ADC_DAP_RHNAC 0x2522
- +#define AC_ADC_DAP_RLNAC 0x2524
- +#define AC_ADC_DAP_HHPFC 0x2526
- +#define AC_ADC_DAP_LHPFC 0x2528
- +#define AC_ADC_DAP_OPT 0x252A
- +/* Left blank */
- +#define AC_DRC_SEL 0x2f80
- +/* Left blank */
- +#define AC_DRC_CHAN_CTRL 0x3000
- +#define AC_DRC_HHPFC 0x3002
- +#define AC_DRC_LHPFC 0x3004
- +#define AC_DRC_CTRL 0x3006
- +#define AC_DRC_LPFHAT 0x3008
- +#define AC_DRC_LPFLAT 0x300A
- +#define AC_DRC_RPFHAT 0x300C
- +#define AC_DRC_RPFLAT 0x300E
- +#define AC_DRC_LPFHRT 0x3010
- +#define AC_DRC_LPFLRT 0x3012
- +#define AC_DRC_RPFHRT 0x3014
- +#define AC_DRC_RPFLRT 0x3016
- +#define AC_DRC_LRMSHAT 0x3018
- +#define AC_DRC_LRMSLAT 0x301A
- +#define AC_DRC_RRMSHAT 0x301C
- +#define AC_DRC_RRMSLAT 0x301E
- +#define AC_DRC_HCT 0x3020
- +#define AC_DRC_LCT 0x3022
- +#define AC_DRC_HKC 0x3024
- +#define AC_DRC_LKC 0x3026
- +#define AC_DRC_HOPC 0x3028
- +#define AC_DRC_LOPC 0x302A
- +#define AC_DRC_HLT 0x302C
- +#define AC_DRC_LLT 0x302E
- +#define AC_DRC_HKI 0x3030
- +#define AC_DRC_LKI 0x3032
- +#define AC_DRC_HOPL 0x3034
- +#define AC_DRC_LOPL 0x3036
- +#define AC_DRC_HET 0x3038
- +#define AC_DRC_LET 0x303A
- +#define AC_DRC_HKE 0x303C
- +#define AC_DRC_LKE 0x303E
- +#define AC_DRC_HOPE 0x3040
- +#define AC_DRC_LOPE 0x3042
- +#define AC_DRC_HKN 0x3044
- +#define AC_DRC_LKN 0x3046
- +#define AC_DRC_SFHAT 0x3048
- +#define AC_DRC_SFLAT 0x304A
- +#define AC_DRC_SFHRT 0x304C
- +#define AC_DRC_SFLRT 0x304E
- +#define AC_DRC_MXGHS 0x3050
- +#define AC_DRC_MXGLS 0x3052
- +#define AC_DRC_MNGHS 0x3054
- +#define AC_DRC_MNGLS 0x3056
- +#define AC_DRC_EPSHC 0x3058
- +#define AC_DRC_EPSLC 0x305A
- +#define AC_DRC_OPT 0x305C
- +#define AC_DRC_HPFHGAIN 0x305E
- +#define AC_DRC_HPFLGAIN 0x3060
- +#define AC_DRC_BISTCR 0x3100
- +#define AC_DRC_BISTST 0x3102
- +
- +/* AC_SYS_CLK_CTL : 0x2000 */
- +#define SYS_CLK_I2S 15
- +#define SYS_CLK_AGC 7
- +#define SYS_CLK_DRC 6
- +#define SYS_CLK_ADC 3
- +#define SYS_CLK_DAC 2
- +
- +/* AC_SYS_MOD_RST : 0x2002 */
- +#define MOD_RST_I2S 15
- +#define MOD_RST_AGC 7
- +#define MOD_RST_DRC 6
- +#define MOD_RST_ADC 3
- +#define MOD_RST_DAC 2
- +
- +/* AC_SYS_SR_CTL : 0x2004 */
- +#define SYS_SR_BIT 0
- +#define SYS_SR_MASK 0xF
- +#define SYS_SR_BIT_0 0 /* 8000 */
- +#define SYS_SR_BIT_1 1 /* 11025 */
- +#define SYS_SR_BIT_2 2 /* 12000 */
- +#define SYS_SR_BIT_3 3 /* 16000 */
- +#define SYS_SR_BIT_4 4 /* 22050 */
- +#define SYS_SR_BIT_5 5 /* 24000 */
- +#define SYS_SR_BIT_6 6 /* 32000 */
- +#define SYS_SR_BIT_7 7 /* 44100 */
- +#define SYS_SR_BIT_8 8 /* 48000 */
- +#define SYS_SR_BIT_9 9 /* 96000 */
- +#define SYS_SR_BIT_10 10 /* 192000 */
- +
- +/* AC_I2S_CTL : 0x2100 */
- +#define I2S_SDO0_EN 3
- +#define I2S_TX_EN 2
- +#define I2S_RX_EN 1
- +#define I2S_GEN 0
- +
- +/* AC_I2S_CLK : 0x2102 */
- +#define I2S_BCLK_OUT 15
- +#define I2S_LRCK_OUT 14
- +#define I2S_BLCK_DIV 10
- +#define I2S_LRCK_PERIOD 0
- +/* BCLK DIV Define */
- +#define I2S_BCLK_DIV_MASK 0xF
- +#define I2S_BCLK_DIV_1 1
- +#define I2S_BCLK_DIV_2 2
- +#define I2S_BCLK_DIV_3 3
- +#define I2S_BCLK_DIV_4 4
- +#define I2S_BCLK_DIV_5 5
- +#define I2S_BCLK_DIV_6 6
- +#define I2S_BCLK_DIV_7 7
- +#define I2S_BCLK_DIV_8 8
- +#define I2S_BCLK_DIV_9 9
- +#define I2S_BCLK_DIV_10 10
- +#define I2S_BCLK_DIV_11 11
- +#define I2S_BCLK_DIV_12 12
- +#define I2S_BCLK_DIV_13 13
- +#define I2S_BCLK_DIV_14 14
- +#define I2S_BCLK_DIV_15 15
- +#define I2S_LRCK_PERIOD_MASK 0x3FF
- +
- +/* AC_I2S_FMT0 : 0x2104 */
- +#define I2S_FMT_MODE 14
- +#define I2S_FMT_TX_OFFSET 10
- +#define I2S_FMT_RX_OFFSET 8
- +#define I2S_FMT_SAMPLE 4
- +#define I2S_FMT_SLOT_WIDTH 1
- +#define I2S_FMT_LOOP 0
- +
- +/* AC_I2S_FMT1 : 0x2108 */
- +#define I2S_FMT_BCLK_POLAR 15
- +#define I2S_FMT_LRCK_POLAR 14
- +#define I2S_FMT_EDGE_TRANSFER 13
- +#define I2S_FMT_RX_MLS 11
- +#define I2S_FMT_TX_MLS 10
- +#define I2S_FMT_EXTEND 9
- +#define I2S_FMT_LRCK_WIDTH 4 /* PCM long/short Frame */
- +#define I2S_MFT_RX_PDM 2
- +#define I2S_FMT_TX_PDM 0
- +
- +/* AC_I2S_MIXER_SRC : 0x2114 */
- +#define I2S_MIXERL_SRC_DAC 13
- +#define I2S_MIXERL_SRC_ADC 12
- +#define I2S_MIXERR_SRC_DAC 9
- +#define I2S_MIXERR_SRC_ADC 8
- +
- +/* AC_I2S_MIXER_GAIN : 0x2116 */
- +#define I2S_MIXERL_GAIN_DAC 13
- +#define I2S_MIXERL_GAIN_ADC 12
- +#define I2S_MIXERR_GAIN_DAC 9
- +#define I2S_MIXERR_GAIN_ADC 8
- +
- +
- +/* AC_I2S_DAC_VOL : 0x2118 */
- +#define I2S_DACL_VOL 8
- +#define I2S_DACR_VOL 0
- +
- +/* AC_I2S_ADC_VOL : 0x211A */
- +#define I2S_ADCL_VOL 8
- +#define I2S_ADCR_VOL 0
- +
- +/* AC_DAC_CTL : 0x2200 */
- +#define DAC_CTL_DAC_EN 15
- +#define DAC_CTL_HPF_EN 14
- +#define DAC_CTL_FIR 13
- +#define DAC_CTL_MODQU 8
- +
- +/* AC_DAC_MIXER_SRC : 0x2202 */
- +#define DAC_MIXERL_SRC_DAC 13
- +#define DAC_MIXERL_SRC_ADC 12
- +#define DAC_MIXERR_SRC_DAC 9
- +#define DAC_MIXERR_SRC_ADC 8
- +
- +/* AC_DAC_MIXER_GAIN : 0x2204 */
- +#define DAC_MIXERL_GAIN_DAC 13
- +#define DAC_MIXERL_GAIN_ADC 12
- +#define DAC_MIXERR_GAIN_DAC 9
- +#define DAC_MIXERR_GAIN_ADC 8
- +
- +/* AC_OUT_MIXER_CTL : 0x2220 */
- +#define OUT_MIXER_DACR_EN 15
- +#define OUT_MIXER_DACL_EN 14
- +#define OUT_MIXER_RMIX_EN 13
- +#define OUT_MIXER_LMIX_EN 12
- +#define OUT_MIXER_LINE_VOL 8
- +#define OUT_MIXER_MIC1_VOL 4
- +#define OUT_MIXER_MIC2_VOL 0
- +
- +/* AC_OUT_MIXER_SRC : 0x2222 */
- +#define OUT_MIXERR_SRC_MIC1 14
- +#define OUT_MIXERR_SRC_MIC2 13
- +#define OUT_MIXERR_SRC_PHPN 12
- +#define OUT_MIXERR_SRC_PHP 11
- +#define OUT_MIXERR_SRC_LINER 10
- +#define OUT_MIXERR_SRC_DACR 9
- +#define OUT_MIXERR_SRC_DACL 8
- +#define OUT_MIXERL_SRC_MIC1 6
- +#define OUT_MIXERL_SRC_MIC2 5
- +#define OUT_MIXERL_SRC_PHPN 4
- +#define OUT_MIXERL_SRC_PHN 3
- +#define OUT_MIXERL_SRC_LINEL 2
- +#define OUT_MIXERL_SRC_DACL 1
- +#define OUT_MIXERL_SRC_DACR 0
- +
- +/* AC_LINEOUT_CTL : 0x2224 */
- +#define LINEOUT_EN 15
- +#define LINEL_SRC_EN 14
- +#define LINER_SRC_EN 13
- +#define LINEL_SRC 12
- +#define LINER_SRC 11
- +/* ramp just skip */
- +#define LINE_SLOPE_SEL 8
- +#define LINE_ANTI_TIME 5
- +#define LINEOUT_VOL 0
- +
- +/* AC_ADC_CTL : 0x2300 */
- +#define ADC_EN 15
- +#define ADC_ENDM 14
- +#define ADC_FIR 13
- +#define ADC_DELAY_TIME 2
- +#define ADC_DELAY_EN 1
- +
- +/* AC_MICBIAS_CTL : 0x2310 */
- +#define MMBIAS_EN 15
- +#define MMBIAS_CHOPPER 14
- +#define MMBIAS_CHOP_CLK 12
- +#define MMBIAS_SEL 8
- +#define ADDA_BIAS_CUR 3
- +
- +/* AC_ADC_MIC_CTL : 0x2320 */
- +#define ADCR_EN 15
- +#define ADCL_EN 14
- +#define ADC_GAIN 8
- +#define MIC1_GAIN_EN 7
- +#define MIC1_BOOST 4
- +#define MIC2_GAIN_EN 3
- +#define MIC2_BOOST 0
- +
- +/* AC_ADC_MIXER_SRC : 0x2322 */
- +#define ADC_MIXERR_MIC1 14
- +#define ADC_MIXERR_MIC2 13
- +#define ADC_MIXERR_PHPN 12
- +#define ADC_MIXERR_PHP 11
- +#define ADC_MIXERR_LINER 10
- +#define ADC_MIXERR_MIXR 9
- +#define ADC_MIXERR_MIXL 8
- +#define ADC_MIXERL_MIC1 6
- +#define ADC_MIXERL_MIC2 5
- +#define ADC_MIXERL_PHPN 4
- +#define ADC_MIXERL_PHN 3
- +#define ADC_MIXERL_LINEL 2
- +#define ADC_MIXERL_MIXL 1
- +#define ADC_MIXERL_MIXR 0
- +
- +/* AC_BIAS_CTL : 0x232A */
- +
- +/* AC_ANALOG_PROF_CTL : 0x232C */
- +/* used for current performance measure */
- +
- +/* AC_DLDO_OSC_CTL : 0x2340 */
- +/* AC_ALDO_CTL : 0x2342 */
- +/* used for digital & analog LDO test... etc */
- +
- +#endif
- +
- diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c
- index 9f8e868b9..f2ef01aae 100644
- --- a/sound/soc/sunxi/sun4i-i2s.c
- +++ b/sound/soc/sunxi/sun4i-i2s.c
- @@ -724,7 +724,8 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
- val = 0;
- break;
- case SND_SOC_DAIFMT_NB_NF:
- - val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
- + //val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
- + val = SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
- break;
- default:
- return -EINVAL;
- @@ -796,9 +797,9 @@ static int sun8i_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
- val);
-
- /* Set sign extension to pad out LSB with 0 */
- - regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
- + /* regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
- SUN8I_I2S_FMT1_REG_SEXT_MASK,
- - SUN8I_I2S_FMT1_REG_SEXT(0));
- + SUN8I_I2S_FMT1_REG_SEXT(0)); */
-
- return 0;
- }
- @@ -831,7 +832,8 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
- val = 0;
- break;
- case SND_SOC_DAIFMT_NB_NF:
- - val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
- + //val = SUN8I_I2S_FMT0_LRCLK_POLARITY_INVERTED;
- + val = SUN8I_I2S_FMT0_LRCLK_POLARITY_NORMAL;
- break;
- default:
- return -EINVAL;
- @@ -903,9 +905,9 @@ static int sun50i_h6_i2s_set_soc_fmt(const struct sun4i_i2s *i2s,
- val);
-
- /* Set sign extension to pad out LSB with 0 */
- - regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
- + /* regmap_update_bits(i2s->regmap, SUN4I_I2S_FMT1_REG,
- SUN8I_I2S_FMT1_REG_SEXT_MASK,
- - SUN8I_I2S_FMT1_REG_SEXT(0));
- + SUN8I_I2S_FMT1_REG_SEXT(0)); */
-
- return 0;
- }
- @@ -1238,6 +1240,7 @@ static const struct regmap_config sun8i_i2s_regmap_config = {
- };
-
- static const struct regmap_config sun50i_h6_i2s_regmap_config = {
- + .name = "h6_i2s",
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
|