| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783 |
- /*
- * Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
- *
- * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
- * the the people's Republic of China and other countries.
- * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
- *
- * DISCLAIMER
- * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
- * IF YOU NEED TO INTEGRATE THIRD PARTY’S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
- * IN ALLWINNERS’SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
- * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
- * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
- * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
- * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY’S TECHNOLOGY.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
- * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
- * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
- * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
- * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <getopt.h>
- #include <sound/snd_core.h>
- #include <sound/snd_pcm.h>
- #include <sound/pcm_common.h>
- #include <aw_common.h>
- #include <unistd.h>
- #include "ac108.h"
- //test config
- #define AC108_KCONTROL_TEST_EN
- //add to
- #undef AC108_IDLE_RESET_EN
- //AC108 SDO2/TX2 Enable (SDO1 has be enabled default)
- #define AC108_SDO2_EN 0
- #define AC108_DMIC_EN 0 //0:ADC 1:DMIC
- #undef AC108_IDLE_RESET_EN //reset AC108 when in idle time
- #define AC108_POWERON_RESET_EN 1 //AC108 poweron soft reset enable
- //add to
- #undef AC108_POWERON_RESET_EN
- #define AC108_REGULATOR_NAME "regulator_name"
- #define AC108_RATES (SNDRV_PCM_RATE_8000_96000 | SNDRV_PCM_RATE_KNOT)
- #define AC108_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S20_3LE | \
- SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
- struct real_val_to_reg_val {
- unsigned int real_val;
- unsigned int reg_val;
- };
- struct pll_div {
- unsigned int freq_in;
- unsigned int freq_out;
- unsigned int m1;
- unsigned int m2;
- unsigned int n;
- unsigned int k1;
- unsigned int k2;
- };
- #if 0
- static const unsigned char ac108_reg_addr_list[] = {
- CHIP_AUDIO_RST,
- //Power Control
- PWR_CTRL1,
- PWR_CTRL2,
- PWR_CTRL3,
- PWR_CTRL4,
- PWR_CTRL5,
- PWR_CTRL6,
- PWR_CTRL7,
- PWR_CTRL8,
- PWR_CTRL9,
- //PLL Configure Control
- PLL_CTRL1,
- PLL_CTRL2,
- PLL_CTRL3,
- PLL_CTRL4,
- PLL_CTRL5,
- PLL_CTRL6,
- PLL_CTRL7,
- PLL_LOCK_CTRL,
- //System Clock Control
- SYSCLK_CTRL,
- MOD_CLK_EN,
- MOD_RST_CTRL,
- DSM_CLK_CTRL,
- //I2S Common Control
- I2S_CTRL,
- I2S_BCLK_CTRL,
- I2S_LRCK_CTRL1,
- I2S_LRCK_CTRL2,
- I2S_FMT_CTRL1,
- I2S_FMT_CTRL2,
- I2S_FMT_CTRL3,
- //I2S TX1 Control
- I2S_TX1_CTRL1,
- I2S_TX1_CTRL2,
- I2S_TX1_CTRL3,
- I2S_TX1_CHMP_CTRL1,
- I2S_TX1_CHMP_CTRL2,
- I2S_TX1_CHMP_CTRL3,
- I2S_TX1_CHMP_CTRL4,
- //I2S TX2 Control
- I2S_TX2_CTRL1,
- I2S_TX2_CTRL2,
- I2S_TX2_CTRL3,
- I2S_TX2_CHMP_CTRL1,
- I2S_TX2_CHMP_CTRL2,
- I2S_TX2_CHMP_CTRL3,
- I2S_TX2_CHMP_CTRL4,
- //I2S RX1 Control
- I2S_RX1_CTRL1,
- I2S_RX1_CHMP_CTRL1,
- I2S_RX1_CHMP_CTRL2,
- I2S_RX1_CHMP_CTRL3,
- I2S_RX1_CHMP_CTRL4,
- //I2S Loopback Debug
- I2S_LPB_DEBUG,
- //ADC Common Control
- ADC_SPRC,
- ADC_DIG_EN,
- DMIC_EN,
- ADC_DSR,
- ADC_FIR,
- ADC_DDT_CTRL,
- //HPF Control
- HPF_EN,
- HPF_COEF_REGH1,
- HPF_COEF_REGH2,
- HPF_COEF_REGL1,
- HPF_COEF_REGL2,
- HPF_GAIN_REGH1,
- HPF_GAIN_REGH2,
- HPF_GAIN_REGL1,
- HPF_GAIN_REGL2,
- //ADC Digital Channel Volume Control
- ADC1_DVOL_CTRL,
- ADC2_DVOL_CTRL,
- ADC3_DVOL_CTRL,
- ADC4_DVOL_CTRL,
- //ADC Digital Mixer Source and Gain Control
- ADC1_DMIX_SRC,
- ADC2_DMIX_SRC,
- ADC3_DMIX_SRC,
- ADC4_DMIX_SRC,
- //ADC Digital Debug Control
- ADC_DIG_DEBUG,
- //I2S Pad Drive Control
- I2S_DAT_PADDRV_CTRL,
- I2S_CLK_PADDRV_CTRL,
- //Analog PGA Control
- ANA_PGA1_CTRL,
- ANA_PGA2_CTRL,
- ANA_PGA3_CTRL,
- ANA_PGA4_CTRL,
- //MIC Offset Control
- MIC_OFFSET_CTRL1,
- MIC_OFFSET_CTRL2,
- MIC1_OFFSET_STATU1,
- MIC1_OFFSET_STATU2,
- MIC2_OFFSET_STATU1,
- MIC2_OFFSET_STATU2,
- MIC3_OFFSET_STATU1,
- MIC3_OFFSET_STATU2,
- MIC4_OFFSET_STATU1,
- MIC4_OFFSET_STATU2,
- //ADC1 Analog Control
- ANA_ADC1_CTRL1,
- ANA_ADC1_CTRL2,
- ANA_ADC1_CTRL3,
- ANA_ADC1_CTRL4,
- ANA_ADC1_CTRL5,
- ANA_ADC1_CTRL6,
- ANA_ADC1_CTRL7,
- //ADC2 Analog Control
- ANA_ADC2_CTRL1,
- ANA_ADC2_CTRL2,
- ANA_ADC2_CTRL3,
- ANA_ADC2_CTRL4,
- ANA_ADC2_CTRL5,
- ANA_ADC2_CTRL6,
- ANA_ADC2_CTRL7,
- //ADC3 Analog Control
- ANA_ADC3_CTRL1,
- ANA_ADC3_CTRL2,
- ANA_ADC3_CTRL3,
- ANA_ADC3_CTRL4,
- ANA_ADC3_CTRL5,
- ANA_ADC3_CTRL6,
- ANA_ADC3_CTRL7,
- //ADC4 Analog Control
- ANA_ADC4_CTRL1,
- ANA_ADC4_CTRL2,
- ANA_ADC4_CTRL3,
- ANA_ADC4_CTRL4,
- ANA_ADC4_CTRL5,
- ANA_ADC4_CTRL6,
- ANA_ADC4_CTRL7,
- //GPIO Configure
- GPIO_CFG1,
- GPIO_CFG2,
- GPIO_DAT,
- GPIO_DRV,
- GPIO_PULL,
- GPIO_INT_CFG,
- GPIO_INT_EN,
- GPIO_INT_STATUS,
- //Misc
- BGTC_DAT,
- BGVC_DAT,
- PRNG_CLK_CTRL,
- };
- #endif
- static const struct real_val_to_reg_val ac108_sample_rate[] = {
- {8000, 0},
- {11025, 1},
- {12000, 2},
- {16000, 3},
- {22050, 4},
- {24000, 5},
- {32000, 6},
- {44100, 7},
- {48000, 8},
- {96000, 9},
- };
- static const struct real_val_to_reg_val ac108_sample_resolution[] = {
- {8, 1},
- {12, 2},
- {16, 3},
- {20, 4},
- {24, 5},
- {28, 6},
- {32, 7},
- };
- static const struct real_val_to_reg_val ac108_bclk_div[] = {
- {0, 0},
- {1, 1},
- {2, 2},
- {4, 3},
- {6, 4},
- {8, 5},
- {12, 6},
- {16, 7},
- {24, 8},
- {32, 9},
- {48, 10},
- {64, 11},
- {96, 12},
- {128, 13},
- {176, 14},
- {192, 15},
- };
- //FOUT =(FIN * N) / [(M1+1) * (M2+1)*(K1+1)*(K2+1)] ;
- //M1[0,31], M2[0,1], N[0,1023], K1[0,31], K2[0,1]
- static const struct pll_div ac108_pll_div[] = {
- {400000, 24576000, 0, 0, 983, 7, 1}, //<out: 24.575M>
- {512000, 24576000, 0, 0, 960, 9, 1}, //24576000/48
- {768000, 24576000, 0, 0, 640, 9, 1}, //24576000/32
- {800000, 24576000, 0, 0, 768, 24, 0},
- {1024000, 24576000, 0, 0, 480, 9, 1}, //24576000/24
- {1600000, 24576000, 0, 0, 384, 24, 0},
- {2048000, 24576000, 0, 0, 240, 9, 1}, //24576000/12
- {3072000, 24576000, 0, 0, 160, 9, 1}, //24576000/8
- {4096000, 24576000, 0, 0, 120, 9, 1}, //24576000/6
- {6000000, 24576000, 4, 0, 512, 24, 0},
- {12000000, 24576000, 9, 0, 512, 24, 0},
- {13000000, 24576000, 12, 0, 639, 12, 1}, //<out: 24.577M>
- {15360000, 24576000, 9, 0, 320, 9, 1},
- {16000000, 24576000, 9, 0, 384, 24, 0},
- {19200000, 24576000, 11, 0, 384, 24, 0},
- {19680000, 24576000, 15, 1, 999, 24, 0}, //<out: 24.575M>
- {24000000, 24576000, 9, 0, 256, 24, 0},
- {400000, 22579200, 0, 0, 1016, 8, 1}, //<out: 22.5778M>
- {512000, 22579200, 0, 0, 882, 9, 1},
- {768000, 22579200, 0, 0, 588, 9, 1},
- {800000, 22579200, 0, 0, 508, 8, 1}, //<out: 22.5778M>
- {1024000, 22579200, 0, 0, 441, 9, 1},
- {1600000, 22579200, 0, 0, 254, 8, 1}, //<out: 22.5778M>
- {2048000, 22579200, 1, 0, 441, 9, 1},
- {3072000, 22579200, 2, 0, 441, 9, 1},
- {4096000, 22579200, 3, 0, 441, 9, 1},
- {6000000, 22579200, 5, 0, 429, 18, 0}, //<out: 22.5789M>
- {12000000, 22579200, 11, 0, 429, 18, 0}, //<out: 22.5789M>
- {13000000, 22579200, 12, 0, 429, 18, 0}, //<out: 22.5789M>
- {15360000, 22579200, 14, 0, 441, 9, 1},
- {16000000, 22579200, 24, 0, 882, 24, 0},
- {19200000, 22579200, 4, 0, 147, 24, 0},
- {19680000, 22579200, 13, 1, 771, 23, 0}, //<out: 22.5793M>
- {24000000, 22579200, 24, 0, 588, 24, 0},
- {12288000, 24576000, 9, 0, 400, 9, 1}, //24576000/2
- {11289600, 22579200, 9, 0, 400, 9, 1}, //22579200/2
- {24576000/1, 24576000, 9, 0, 200, 9, 1}, //24576000
- {24576000/4, 24576000, 4, 0, 400, 9, 1}, //6144000
- {24576000/16, 24576000, 0, 0, 320, 9, 1}, //1536000
- {24576000/64, 24576000, 0, 0, 640, 4, 1}, //384000
- {24576000/96, 24576000, 0, 0, 960, 4, 1}, //256000
- {24576000/128, 24576000, 0, 0, 512, 1, 1}, //192000
- {24576000/176, 24576000, 0, 0, 880, 4, 0}, //140000
- {24576000/192, 24576000, 0, 0, 960, 4, 0}, //128000
- {22579200/1, 22579200, 9, 0, 200, 9, 1}, //22579200
- {22579200/4, 22579200, 4, 0, 400, 9, 1}, //5644800
- {22579200/16, 22579200, 0, 0, 320, 9, 1}, //1411200
- {22579200/64, 22579200, 0, 0, 640, 4, 1}, //352800
- {22579200/96, 22579200, 0, 0, 960, 4, 1}, //235200
- {22579200/128, 22579200, 0, 0, 512, 1, 1}, //176400
- {22579200/176, 22579200, 0, 0, 880, 4, 0}, //128290
- {22579200/192, 22579200, 0, 0, 960, 4, 0}, //117600
- {22579200/6, 22579200, 2, 0, 360, 9, 1}, //3763200
- {22579200/8, 22579200, 0, 0, 160, 9, 1}, //2822400
- {22579200/12, 22579200, 0, 0, 240, 9, 1}, //1881600
- {22579200/24, 22579200, 0, 0, 480, 9, 1}, //940800
- {22579200/32, 22579200, 0, 0, 640, 9, 1}, //705600
- {22579200/48, 22579200, 0, 0, 960, 9, 1}, //470400
- };
- static twi_status_t ac108_init_i2c_device(twi_port_t port)
- {
- twi_status_t ret = 0;
- ret = hal_twi_init(port);
- if (ret != TWI_STATUS_OK) {
- snd_err("init i2c err ret=%d.\n", ret);
- return ret;
- }
- return TWI_STATUS_OK;
- }
- static twi_status_t ac108_deinit_i2c_device(twi_port_t port)
- {
- twi_status_t ret = 0;
- ret = hal_twi_uninit(port);
- if (ret != TWI_STATUS_OK) {
- snd_err("init i2c err ret=%d.\n", ret);
- return ret;
- }
- return TWI_STATUS_OK;
- }
- static twi_status_t ac108_read(struct twi_device *twi_dev,
- unsigned char reg, unsigned char *rt_value)
- {
- twi_status_t ret;
- hal_twi_control(twi_dev->bus, I2C_SLAVE, &twi_dev->addr);
- ret = hal_twi_read(twi_dev->bus, reg, rt_value, 1);
- if (ret != TWI_STATUS_OK) {
- snd_err("error = %d [REG-0x%02x]\n", ret, reg);
- return ret;
- }
- return TWI_STATUS_OK;
- }
- static int ac108_write(struct twi_device *twi_dev,
- unsigned char reg, unsigned char value)
- {
- twi_status_t ret;
- twi_msg_t msg;
- unsigned char buf[2] = {reg, value};
- msg.flags = 0;
- msg.addr = twi_dev->addr;
- msg.len = 2;
- msg.buf = buf;
- ret = hal_twi_control(twi_dev->bus, I2C_RDWR, &msg);
- if (ret != TWI_STATUS_OK) {
- snd_err("error = %d [REG-0x%02x]\n", ret, reg);
- return ret;
- }
- return TWI_STATUS_OK;
- }
- static int ac108_update_bits(struct twi_device *twi_dev,
- unsigned char reg, unsigned char mask, unsigned char value)
- {
- unsigned char val_old = 0;
- unsigned char val_new = 0;
- ac108_read(twi_dev, reg, &val_old);
- val_new = (val_old & ~mask) | (value & mask);
- if (val_new != val_old)
- ac108_write(twi_dev, reg, val_new);
- return 0;
- }
- static int ac108_multi_chips_write(struct ac108_priv *ac108,
- unsigned char reg, unsigned char value)
- {
- unsigned char i;
- for (i = 0; i < ac108->param.chip_num; i++)
- ac108_write(&(ac108->param.twi_dev[i]), reg, value);
- return 0;
- }
- static int ac108_multi_chips_update_bits(struct ac108_priv *ac108,
- unsigned char reg, unsigned char mask, unsigned char value)
- {
- unsigned char i;
- for (i = 0; i < ac108->param.chip_num; i++)
- ac108_update_bits(&(ac108->param.twi_dev[i]), reg, mask, value);
- return 0;
- }
- #ifdef AC108_KCONTROL_TEST_EN
- /* ac108 mixer controls define */
- static const char * const adc_digital_src_mux[] = {
- "ADC1_Switch", "ADC2_Switch", "ADC3_Switch", "ADC4_Switch",
- };
- static const char * const adc12_dmic1_src_mux[] = {
- "ADC12_Switch", "DMIC1_Switch",
- };
- static const char * const adc34_dmic2_src_mux[] = {
- "ADC34_Switch", "DMIC2_Switch",
- };
- static const char * const i2s_tx1ch_map_mux[] = {
- "ADC1_Sample_Switch", "ADC2_Sample_Switch",
- "ADC3_Sample_Switch", "ADC4_Sample_Switch",
- };
- static int ac108_ctl_enum_value_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_info *info)
- {
- unsigned int val = 0;
- if (kcontrol->type != SND_CTL_ELEM_TYPE_ENUMERATED) {
- snd_err("invalid kcontrol type = %d.\n", kcontrol->type);
- return -EINVAL;
- }
- if (kcontrol->private_data_type == SND_MODULE_CODEC) {
- struct snd_codec *codec = kcontrol->private_data;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- ac108_read(¶m->twi_dev[0], kcontrol->reg, (unsigned char *)&val);
- } else {
- snd_err("%s invalid kcontrol data type = %d.\n", __func__,
- kcontrol->private_data_type);
- }
- snd_kcontrol_to_snd_ctl_info(kcontrol, info, val);
- return 0;
- }
- static int ac108_ctl_enum_value_set(struct snd_kcontrol *kcontrol, unsigned long val)
- {
- if (kcontrol->type != SND_CTL_ELEM_TYPE_ENUMERATED) {
- snd_err("invalid kcontrol type = %d.\n", kcontrol->type);
- return -EINVAL;
- }
- if (val >= kcontrol->items) {
- snd_err("invalid kcontrol items = %ld.\n", val);
- return -EINVAL;
- }
- if (kcontrol->private_data_type == SND_MODULE_CODEC) {
- struct snd_codec *codec = kcontrol->private_data;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- ac108_update_bits(¶m->twi_dev[0], kcontrol->reg,
- (kcontrol->mask << kcontrol->shift),
- ((unsigned int)val << kcontrol->shift));
- } else {
- snd_err("invalid kcontrol data type = %d.\n",
- kcontrol->private_data_type);
- return -EINVAL;
- }
- kcontrol->value = val & kcontrol->mask;
- snd_info("mask:0x%x, shift:%d, value:0x%x\n",
- kcontrol->mask, kcontrol->shift, kcontrol->value);
- return 0;
- }
- static int ac108_ctl_value_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_info *info)
- {
- unsigned int val = 0;
- int mask = 0;
- if (kcontrol->type != SND_CTL_ELEM_TYPE_INTEGER) {
- snd_err("invalid kcontrol type = %d.\n", kcontrol->type);
- return -EINVAL;
- }
- if (kcontrol->private_data_type == SND_MODULE_CODEC) {
- struct snd_codec *codec = kcontrol->private_data;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- ac108_read(¶m->twi_dev[0], kcontrol->reg, (unsigned char *)&val);
- } else {
- snd_err("%s invalid kcontrol data type = %d.\n", __func__,
- kcontrol->private_data_type);
- }
- snd_kcontrol_to_snd_ctl_info(kcontrol, info, val);
- return 0;
- }
- static int ac108_ctl_value_set(struct snd_kcontrol *kcontrol, unsigned long val)
- {
- if (kcontrol->type != SND_CTL_ELEM_TYPE_INTEGER) {
- snd_err("invalid kcontrol type = %d.\n", kcontrol->type);
- return -EINVAL;
- }
- if (kcontrol->private_data_type == SND_MODULE_CODEC) {
- struct snd_codec *codec = kcontrol->private_data;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- ac108_update_bits(¶m->twi_dev[0], kcontrol->reg,
- (kcontrol->mask << kcontrol->shift),
- ((unsigned int)val << kcontrol->shift));
- } else {
- snd_err("%s invalid kcontrol data type = %d.\n", __func__,
- kcontrol->private_data_type);
- }
- snd_info("mask:0x%x, shitf:%d, value:0x%x\n",
- kcontrol->mask, kcontrol->shift, val);
- return 0;
- }
- static struct snd_kcontrol ac108_codec_controls[] = {
- //ADC1 DIG MUX
- SND_CTL_ENUM_VALUE_EXT("ADC1 DIG MUX", ARRAY_SIZE(adc_digital_src_mux),
- adc_digital_src_mux, ADC_DSR, DIG_ADC1_SRS,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //ADC2 DIG MUX
- SND_CTL_ENUM_VALUE_EXT("ADC2 DIG MUX", ARRAY_SIZE(adc_digital_src_mux),
- adc_digital_src_mux, ADC_DSR, DIG_ADC2_SRS,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //ADC3 DIG MUX
- SND_CTL_ENUM_VALUE_EXT("ADC3 DIG MUX", ARRAY_SIZE(adc_digital_src_mux),
- adc_digital_src_mux, ADC_DSR, DIG_ADC3_SRS,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //ADC4 DIG MUX
- SND_CTL_ENUM_VALUE_EXT("ADC4 DIG MUX", ARRAY_SIZE(adc_digital_src_mux),
- adc_digital_src_mux, ADC_DSR, DIG_ADC4_SRS,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //ADC12 DMIC1 MUX
- SND_CTL_ENUM_VALUE_EXT("ADC12 DMIC1 MUX", ARRAY_SIZE(adc12_dmic1_src_mux),
- adc12_dmic1_src_mux, DMIC_EN, DMIC1_EN,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //ADC34 DMIC2 MUX
- SND_CTL_ENUM_VALUE_EXT("ADC34 DMIC2 MUX", ARRAY_SIZE(adc34_dmic2_src_mux),
- adc34_dmic2_src_mux, DMIC_EN, DMIC2_EN,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //ADC1 DIG MIXER
- SND_CTL_KCONTROL_VALUE_EXT("ADC1 DIG MIXER ADC1 DAT switch",
- ADC1_DMIX_SRC, ADC1_ADC1_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC1 DIG MIXER ADC2 DAT switch",
- ADC1_DMIX_SRC, ADC1_ADC2_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC1 DIG MIXER ADC3 DAT switch",
- ADC1_DMIX_SRC, ADC1_ADC3_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC1 DIG MIXER ADC4 DAT switch",
- ADC1_DMIX_SRC, ADC1_ADC4_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- //ADC2 DIG MIXER
- SND_CTL_KCONTROL_VALUE_EXT("ADC2 DIG MIXER ADC1 DAT switch",
- ADC2_DMIX_SRC, ADC2_ADC1_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC2 DIG MIXER ADC2 DAT switch",
- ADC2_DMIX_SRC, ADC2_ADC2_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC2 DIG MIXER ADC3 DAT switch",
- ADC2_DMIX_SRC, ADC2_ADC3_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC2 DIG MIXER ADC4 DAT switch",
- ADC2_DMIX_SRC, ADC2_ADC4_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- //ADC3 DIG MIXER
- SND_CTL_KCONTROL_VALUE_EXT("ADC3 DIG MIXER ADC1 DAT switch",
- ADC3_DMIX_SRC, ADC3_ADC1_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC3 DIG MIXER ADC2 DAT switch",
- ADC3_DMIX_SRC, ADC3_ADC2_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC3 DIG MIXER ADC3 DAT switch",
- ADC3_DMIX_SRC, ADC3_ADC3_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC3 DIG MIXER ADC4 DAT switch",
- ADC3_DMIX_SRC, ADC3_ADC4_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- //ADC4 DIG MIXER
- SND_CTL_KCONTROL_VALUE_EXT("ADC4 DIG MIXER ADC1 DAT switch",
- ADC4_DMIX_SRC, ADC4_ADC1_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC4 DIG MIXER ADC2 DAT switch",
- ADC4_DMIX_SRC, ADC4_ADC2_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC4 DIG MIXER ADC3 DAT switch",
- ADC4_DMIX_SRC, ADC4_ADC3_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- SND_CTL_KCONTROL_VALUE_EXT("ADC4 DIG MIXER ADC4 DAT switch",
- ADC4_DMIX_SRC, ADC4_ADC4_DMXL_SRC, 1, 0,
- ac108_ctl_value_get, ac108_ctl_value_set),
- //I2S TX1 CH1 MUX
- SND_CTL_ENUM_VALUE_EXT("I2S TX1 CH1 MUX", ARRAY_SIZE(i2s_tx1ch_map_mux),
- i2s_tx1ch_map_mux, I2S_TX1_CHMP_CTRL1, TX1_CH1_MAP,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //I2S TX1 CH2 MUX
- SND_CTL_ENUM_VALUE_EXT("I2S TX1 CH2 MUX", ARRAY_SIZE(i2s_tx1ch_map_mux),
- i2s_tx1ch_map_mux, I2S_TX1_CHMP_CTRL1, TX1_CH2_MAP,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //I2S TX1 CH3 MUX
- SND_CTL_ENUM_VALUE_EXT("I2S TX1 CH3 MUX", ARRAY_SIZE(i2s_tx1ch_map_mux),
- i2s_tx1ch_map_mux, I2S_TX1_CHMP_CTRL1, TX1_CH3_MAP,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- //I2S TX1 CH4 MUX
- SND_CTL_ENUM_VALUE_EXT("I2S TX1 CH4 MUX", ARRAY_SIZE(i2s_tx1ch_map_mux),
- i2s_tx1ch_map_mux, I2S_TX1_CHMP_CTRL1, TX1_CH4_MAP,
- SND_CTL_ENUM_AUTO_MASK,
- ac108_ctl_enum_value_get, ac108_ctl_enum_value_set),
- };
- #endif
- static int ac108_codec_startup(struct snd_pcm_substream *substream,
- struct snd_dai *dai)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- int ret = 0;
- snd_print("\n");
- return 0;
- }
- static int ac108_codec_set_pll(struct snd_dai *dai, int pll_id, int source,
- unsigned int freq_in, unsigned int freq_out)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- unsigned int i = 0;
- unsigned int m1 = 0;
- unsigned int m2 = 0;
- unsigned int n = 0;
- unsigned int k1 = 0;
- unsigned int k2 = 0;
- snd_print("\n");
- if (freq_out == 0) {
- snd_err("freq_out is 0.\n");
- return 0;
- }
- //default: freq_int == freq_out; pll_id = 0; source = 0;
- if (freq_in < 128000 || freq_in > 24576000) {
- snd_err("AC108 PLLCLK source input freq only support [128K,24M],while now %u\n\n", freq_in);
- return -EINVAL;
- } else if ((freq_in == 24576000 || freq_in == 22579200) &&
- pll_id == SYSCLK_SRC_MCLK) {
- //System Clock Source Select MCLK, SYSCLK Enable
- snd_print("AC108 don't need to use PLL\n\n");
- ac108_multi_chips_update_bits(ac108, SYSCLK_CTRL,
- 0x1 << SYSCLK_SRC | 0x1 << SYSCLK_EN,
- 0x0 << SYSCLK_SRC | 0x1 << SYSCLK_EN);
- return 0; //Don't need to use PLL
- }
- //PLL Clock Source Select
- switch (pll_id) {
- case PLLCLK_SRC_MCLK:
- snd_print("AC108 PLLCLK input source select MCLK\n");
- ac108_multi_chips_update_bits(ac108, SYSCLK_CTRL, 0x3 << PLLCLK_SRC,
- 0x0 << PLLCLK_SRC);
- break;
- case PLLCLK_SRC_BCLK:
- snd_print("AC108 PLLCLK input source select BCLK\n");
- ac108_multi_chips_update_bits(ac108, SYSCLK_CTRL, 0x3 << PLLCLK_SRC,
- 0x1 << PLLCLK_SRC);
- break;
- case PLLCLK_SRC_GPIO2:
- snd_print("AC108 PLLCLK input source select GPIO2\n");
- ac108_multi_chips_update_bits(ac108, SYSCLK_CTRL, 0x3 << PLLCLK_SRC,
- 0x2 << PLLCLK_SRC);
- break;
- case PLLCLK_SRC_GPIO3:
- snd_print("AC108 PLLCLK input source select GPIO3\n");
- ac108_multi_chips_update_bits(ac108, SYSCLK_CTRL, 0x3 << PLLCLK_SRC,
- 0x3 << PLLCLK_SRC);
- break;
- default:
- snd_err("AC108 PLLCLK source config error:%d\n", pll_id);
- return -EINVAL;
- }
- //FOUT =(FIN * N) / [(M1+1) * (M2+1)*(K1+1)*(K2+1)] ;
- for (i = 0; i < ARRAY_SIZE(ac108_pll_div); i++) {
- if (ac108_pll_div[i].freq_in == freq_in &&
- ac108_pll_div[i].freq_out == freq_out) {
- m1 = ac108_pll_div[i].m1;
- m2 = ac108_pll_div[i].m2;
- n = ac108_pll_div[i].n;
- k1 = ac108_pll_div[i].k1;
- k2 = ac108_pll_div[i].k2;
- snd_print("AC108 PLL freq_in match:%u, freq_out:%u\n",
- freq_in, freq_out);
- break;
- }
- }
- if (i == ARRAY_SIZE(ac108_pll_div)) {
- snd_err("AC108 don't match PLLCLK freq_in and freq_out table\n");
- return -EINVAL;
- }
- //Config PLL DIV param M1/M2/N/K1/K2
- ac108_multi_chips_update_bits(ac108, PLL_CTRL2,
- 0x1f << PLL_PREDIV1 | 0x1 << PLL_PREDIV2,
- m1 << PLL_PREDIV1 | m2 << PLL_PREDIV2);
- ac108_multi_chips_update_bits(ac108, PLL_CTRL3, 0x3 << PLL_LOOPDIV_MSB,
- (n >> 8) << PLL_LOOPDIV_MSB);
- ac108_multi_chips_update_bits(ac108, PLL_CTRL4, 0xff << PLL_LOOPDIV_LSB,
- (u8)n << PLL_LOOPDIV_LSB);
- ac108_multi_chips_update_bits(ac108, PLL_CTRL5,
- (0x1f << PLL_POSTDIV1) | (0x1 << PLL_POSTDIV2),
- k1 << PLL_POSTDIV1 | (k2 << PLL_POSTDIV2));
- //Config PLL module current
- //ac108_multi_chips_update_bits(ac108, PLL_CTRL1, 0x7<<PLL_IBIAS, 0x4<<PLL_IBIAS);
- //ac108_multi_chips_update_bits(ac108, PLL_CTRL6, 0x1f<<PLL_CP, 0xf<<PLL_CP);
- //PLL module enable
- //PLL CLK lock enable
- ac108_multi_chips_update_bits(ac108, PLL_LOCK_CTRL, 0x1 << PLL_LOCK_EN,
- 0x1 << PLL_LOCK_EN);
- //PLL Common voltage Enable, PLL Enable
- //ac108_multi_chips_update_bits(ac108, PLL_CTRL1,
- // 0x1 << PLL_EN | 0x1 << PLL_COM_EN,
- // 0x1<<PLL_EN | 0x1<<PLL_COM_EN);
- //PLLCLK Enable, SYSCLK Enable
- //0x1<<SYSCLK_SRC
- ac108_multi_chips_update_bits(ac108, SYSCLK_CTRL,
- 0x1 << PLLCLK_EN | 0x1 << SYSCLK_EN,
- 0x1 << PLLCLK_EN | 0x1 << SYSCLK_EN);
- return 0;
- }
- static int ac108_codec_set_clkdiv(struct snd_dai *dai, int div_id, int div)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- unsigned int i = 0;
- unsigned int bclk_div = 0;
- unsigned int bclk_div_reg_val = 0;
- snd_print("\n");
- /* default: div_id = 0; */
- if (param->daudio_master == 4) {
- /*
- *daudio_master(val << 12):
- * 1: SND_SOC_DAIFMT_CBM_CFM(codec clk & FRM master)
- * 4: SND_SOC_DAIFMT_CBS_CFS(codec clk & FRM slave)
- */
- snd_print("AC108 work as Slave mode, don't need to config BCLK_DIV.\n");
- return 0;
- }
- /* SND_SOC_DAIFMT_I2S*/
- switch (param->daudio_format) {
- case SND_SOC_DAIFMT_DSP_A:
- case SND_SOC_DAIFMT_DSP_B:
- bclk_div = div / param->lrck_period;
- break;
- case SND_SOC_DAIFMT_I2S:
- case SND_SOC_DAIFMT_RIGHT_J:
- case SND_SOC_DAIFMT_LEFT_J:
- default:
- bclk_div = div / (2 * param->lrck_period);
- break;
- }
- for (i = 0; i < ARRAY_SIZE(ac108_bclk_div); i++) {
- if (ac108_bclk_div[i].real_val == bclk_div) {
- bclk_div_reg_val = ac108_bclk_div[i].reg_val;
- snd_print("AC108 set BCLK_DIV_[%u]\n", bclk_div);
- break;
- }
- }
- if (i == ARRAY_SIZE(ac108_bclk_div)) {
- snd_err("AC108 don't support BCLK_DIV_[%u]\n", bclk_div);
- return -EINVAL;
- }
- //AC108 set BCLK DIV
- ac108_multi_chips_update_bits(ac108, I2S_BCLK_CTRL, 0xf << BCLKDIV,
- bclk_div_reg_val << BCLKDIV);
- return 0;
- }
- static int ac108_codec_set_fmt(struct snd_dai *dai, unsigned int fmt)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- unsigned int i = 0;
- unsigned char tx_offset = 0;
- unsigned char i2s_mode = 0;
- unsigned char lrck_polarity = 0;
- unsigned char brck_polarity = 0;
- snd_print("\n");
- //AC108 config Master/Slave mode
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM: //AC108 Master
- snd_print("AC108 set to work as Master\n");
- //BCLK & LRCK output
- ac108_update_bits(¶m->twi_dev[0], I2S_CTRL, 0x3 << LRCK_IOEN,
- 0x3 << LRCK_IOEN);
- break;
- case SND_SOC_DAIFMT_CBS_CFS: //AC108 Slave
- snd_print("AC108 set to work as Slave\n");
- //BCLK & LRCK input
- ac108_update_bits(¶m->twi_dev[0], I2S_CTRL, 0x3 << LRCK_IOEN,
- 0x0 << LRCK_IOEN);
- break;
- default:
- snd_err("AC108 Master/Slave mode config error:%u\n\n",
- (fmt & SND_SOC_DAIFMT_MASTER_MASK) >> 12);
- return -EINVAL;
- }
- for (i = 0; i < param->chip_num; i++) {
- /*
- * multi_chips: only one chip set as Master,
- * and the others also need to set as Slave
- */
- ac108_update_bits(¶m->twi_dev[i], I2S_CTRL, 0x3 << LRCK_IOEN,
- 0x0 << LRCK_IOEN);
- }
- //AC108 config I2S/LJ/RJ/PCM format
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- snd_print("AC108 config I2S format\n");
- i2s_mode = LEFT_JUSTIFIED_FORMAT;
- tx_offset = 1;
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- snd_print("AC108 config RIGHT-JUSTIFIED format\n");
- i2s_mode = RIGHT_JUSTIFIED_FORMAT;
- tx_offset = 0;
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- snd_print("AC108 config LEFT-JUSTIFIED format\n");
- i2s_mode = LEFT_JUSTIFIED_FORMAT;
- tx_offset = 0;
- break;
- case SND_SOC_DAIFMT_DSP_A:
- snd_print("AC108 config PCM-A format\n");
- i2s_mode = PCM_FORMAT;
- tx_offset = 1;
- break;
- case SND_SOC_DAIFMT_DSP_B:
- snd_print("AC108 config PCM-B format\n");
- i2s_mode = PCM_FORMAT;
- tx_offset = 0;
- break;
- default:
- snd_err("AC108 I2S format config error:%u\n\n",
- fmt & SND_SOC_DAIFMT_FORMAT_MASK);
- return -EINVAL;
- }
- ac108_multi_chips_update_bits(ac108, I2S_FMT_CTRL1,
- 0x3 << MODE_SEL | 0x1 << TX2_OFFSET | 0x1 << TX1_OFFSET,
- i2s_mode<<MODE_SEL | tx_offset<<TX2_OFFSET | tx_offset << TX1_OFFSET);
- //AC108 config BCLK&LRCK polarity
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- snd_print("AC108 config: BCLK_normal,LRCK_normal.\n");
- brck_polarity = BCLK_NORMAL_DRIVE_N_SAMPLE_P;
- lrck_polarity = LRCK_LEFT_LOW_RIGHT_HIGH;
- break;
- case SND_SOC_DAIFMT_NB_IF:
- snd_print("AC108 config: BCLK_normal,LRCK_invert.\n");
- brck_polarity = BCLK_NORMAL_DRIVE_N_SAMPLE_P;
- lrck_polarity = LRCK_LEFT_HIGH_RIGHT_LOW;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- snd_print("AC108 config: BCLK_invert,LRCK_normal.\n");
- brck_polarity = BCLK_INVERT_DRIVE_P_SAMPLE_N;
- lrck_polarity = LRCK_LEFT_LOW_RIGHT_HIGH;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- snd_print("AC108 config: BCLK_invert,LRCK_invert.\n");
- brck_polarity = BCLK_INVERT_DRIVE_P_SAMPLE_N;
- lrck_polarity = LRCK_LEFT_HIGH_RIGHT_LOW;
- break;
- default:
- snd_err("AC108 config BCLK/LRCLK polarity error:%u\n",
- (fmt & SND_SOC_DAIFMT_INV_MASK) >> 8);
- return -EINVAL;
- }
- ac108_multi_chips_update_bits(ac108, I2S_BCLK_CTRL, 0x1<<BCLK_POLARITY,
- brck_polarity << BCLK_POLARITY);
- ac108_multi_chips_update_bits(ac108, I2S_LRCK_CTRL1, 0x1<<LRCK_POLARITY,
- lrck_polarity << LRCK_POLARITY);
- return 0;
- }
- static void ac108_codec_set_pga_gain(struct twi_device *twi_dev, struct ac108_param *param)
- {
- unsigned int i;
- snd_print("\n");
- if (twi_dev->ref_chan.ref_channel != 0x0) {
- snd_info("ref_cfg.ref_channel:0x%x, set ref_pga_gain:%d\n",
- twi_dev->ref_chan.ref_channel, twi_dev->ref_chan.ref_pga);
- /* set the gain for referenced channels, always used for aec */
- for (i = 0; i < 4; i++) {
- if ((twi_dev->ref_chan.ref_channel >> i) & 0x1) {
- ac108_update_bits(twi_dev, ANA_PGA1_CTRL + i,
- 0x1F << ADC1_ANALOG_PGA,
- twi_dev->ref_chan.ref_pga << ADC1_ANALOG_PGA);
- } else
- ac108_update_bits(twi_dev, ANA_PGA1_CTRL + i,
- 0x1F << ADC1_ANALOG_PGA,
- param->pga_gain << ADC1_ANALOG_PGA);
- }
- } else {
- for (i = 0; i < 4; i++)
- ac108_update_bits(twi_dev, ANA_PGA1_CTRL + i,
- 0x1F << ADC1_ANALOG_PGA,
- param->pga_gain << ADC1_ANALOG_PGA);
- }
- }
- static void ac108_codec_hw_init(struct twi_device *twi_dev, struct ac108_param *param)
- {
- /*** Chip reset ***/
- /*0x00=0x12: reset all registers to their default state*/
- //ac108_write(twi_dev, CHIP_AUDIO_RST, 0x12);
- #if !AC108_DMIC_EN
- /*** Analog voltage enable ***/
- /*0x06=0x01: Enable Analog LDO*/
- ac108_write(twi_dev, PWR_CTRL6, 0x01);
- /*
- * 0x07=0x9b: VREF faststart Enable,
- * Enable VREF @ 3.4V (5V) or 3.1V (3.3V)
- * (needed for Analog LDO and MICBIAS)
- */
- ac108_write(twi_dev, PWR_CTRL7, 0x9b);
- /*
- * 0x09=0x81: VREFP faststart Enable, Enable VREFP_FASTSTART_ENABLE
- * (needed by all audio input channels)
- */
- ac108_write(twi_dev, PWR_CTRL9, 0x81);
- /*
- * DSM low power mode enable, Control bias current for
- * DSM integrator opamps
- */
- ac108_write(twi_dev, ANA_ADC3_CTRL7, 0x0b);
- #endif
- /*** SYSCLK Config ***/
- /*SYSCLK Enable*/
- ac108_update_bits(twi_dev, SYSCLK_CTRL, 0x1 << SYSCLK_EN, 0x1 << SYSCLK_EN);
- /*
- * 0x21=0x93: Module clock enable<I2S, ADC digital,
- * MIC offset Calibration, ADC analog>
- */
- ac108_write(twi_dev, MOD_CLK_EN, 0x93);
- /*
- * 0x22=0x93: Module reset de-asserted
- * <I2S, ADC digital, MIC offset Calibration, ADC analog>
- */
- ac108_write(twi_dev, MOD_RST_CTRL, 0x93);
- /*** I2S Common Config ***/
- /*SDO1 enable, SDO2 Enable*/
- ac108_update_bits(twi_dev, I2S_CTRL, ((0x1 << SDO1_EN) | (0x1 << SDO2_EN)),
- ((0x1 << SDO1_EN) | (!!AC108_SDO2_EN << SDO2_EN)));
- /*SDO drive data and SDI sample data at the different BCLK edge*/
- ac108_update_bits(twi_dev, I2S_BCLK_CTRL, (0x1 << EDGE_TRANSFER),
- (0x0 << EDGE_TRANSFER));
- ac108_update_bits(twi_dev, I2S_LRCK_CTRL1, 0x3 << LRCK_PERIODH,
- (((param->lrck_period - 1) >> 8) << LRCK_PERIODH));
- /*
- * config LRCK period:
- * 16bit * 8ch = 128,
- * 32bit * 8ch = 256,
- * 32bit *16ch = 512
- */
- ac108_write(twi_dev, I2S_LRCK_CTRL2, (param->lrck_period - 1) & 0xFF);
- /*
- * Encoding mode enable, Turn to hi-z state (TDM)
- * when not transferring slot
- */
- ac108_update_bits(twi_dev, I2S_FMT_CTRL1,
- 0x1 << ENCD_SEL | 0x1 << TX_SLOT_HIZ | 0x1 << TX_STATE,
- !!AC108_ENCODING_EN << ENCD_SEL | 0x0 << TX_SLOT_HIZ | 0x1 << TX_STATE);
- /* 8/12/16/20/24/28/32bit Slot Width */
- ac108_update_bits(twi_dev, I2S_FMT_CTRL2, 0x7 << SLOT_WIDTH_SEL,
- (param->slot_width / 4 - 1) << SLOT_WIDTH_SEL);
- /*
- * 0x36=0x70: TX MSB first, TX2 Mute, Transfer 0 after
- * each sample in each slot(sample resolution < slot width),
- * LRCK = 1 BCLK width (short frame), Linear PCM Data Mode
- */
- ac108_write(twi_dev, I2S_FMT_CTRL3, AC108_SDO2_EN ? 0x60 : 0x70);
- /*0x3C=0xe4: TX1 CHn Map to CHn adc sample, n=[1,4]*/
- ac108_write(twi_dev, I2S_TX1_CHMP_CTRL1, 0xe4);
- /*0x3D=0xe4: TX1 CHn Map to CH(n-4) adc sample, n=[5,8]*/
- ac108_write(twi_dev, I2S_TX1_CHMP_CTRL2, 0xe4);
- /*0x3E=0xe4: TX1 CHn Map to CH(n-8) adc sample, n=[9,12]*/
- ac108_write(twi_dev, I2S_TX1_CHMP_CTRL3, 0xe4);
- /*0x3F=0xe4: TX1 CHn Map to CH(n-12) adc sample, n=[13,16]*/
- ac108_write(twi_dev, I2S_TX1_CHMP_CTRL4, 0xe4);
- #if AC108_SDO2_EN
- /*
- * 0x44=0x4e: TX2 CH1/2 Map to CH3/4 adc sample,
- * TX2 CH3/4 Map to CH1/2 adc sample
- */
- ac108_write(twi_dev, I2S_TX2_CHMP_CTRL1, 0x4e);
- /*0x45=0xe4: TX2 CHn Map to CH(n-4) adc sample, n=[5,8]*/
- ac108_write(twi_dev, I2S_TX2_CHMP_CTRL2, 0xe4);
- /*0x46=0xe4: TX2 CHn Map to CH(n-8) adc sample, n=[9,12]*/
- ac108_write(twi_dev, I2S_TX2_CHMP_CTRL3, 0xe4);
- /*0x47=0xe4: TX2 CHn Map to CH(n-12) adc sample, n=[13,16]*/
- ac108_write(twi_dev, I2S_TX2_CHMP_CTRL4, 0xe4);
- #endif
- /*** ADC DIG part Config***/
- /*0x60=0x03: ADC Sample Rate 16KHz*/
- //ac108_write(ADC_SPRC, 0x03);
- /*0x61=0x1f: Digital part globe enable, ADCs digital part enable*/
- ac108_write(twi_dev, ADC_DIG_EN, 0x1f);
- /*0xBB=0x0f: Gating ADCs CLK de-asserted (ADCs CLK Enable)*/
- ac108_write(twi_dev, ANA_ADC4_CTRL7, 0x0f);
- if (twi_dev->debug_mode) {
- /*0x66=0x00: Digital ADCs channel HPF disable*/
- ac108_write(twi_dev, HPF_EN, 0x00);
- /*
- * 0X7F=0x00: ADC pattern select: 0:ADC normal, 1:0x5A5A5A,
- * 2:0x123456, 3:0x00, 4~7:I2S RX data
- */
- ac108_write(twi_dev, ADC_DIG_DEBUG, twi_dev->debug_mode & 0x7);
- }
- #if !AC108_DMIC_EN
- /*** ADCs analog PGA gain Config***/
- ac108_codec_set_pga_gain(twi_dev, param);
- /*** enable AAF/ADC/PGA and UnMute Config ***/
- /*
- * 0xA0=0x07: ADC1 AAF & ADC enable, ADC1 PGA enable,
- * ADC1 MICBIAS enable and UnMute
- */
- ac108_write(twi_dev, ANA_ADC1_CTRL1, 0x07);
- /*
- * 0xA7=0x07: ADC2 AAF & ADC enable, ADC2 PGA enable,
- * ADC2 MICBIAS enable and UnMute
- */
- ac108_write(twi_dev, ANA_ADC2_CTRL1, 0x07);
- /*
- * 0xAE=0x07: ADC3 AAF & ADC enable, ADC3 PGA enable,
- * ADC3 MICBIAS enable and UnMute
- */
- ac108_write(twi_dev, ANA_ADC3_CTRL1, 0x07);
- /*
- * 0xB5=0x07: ADC4 AAF & ADC enable, ADC4 PGA enable,
- * ADC4 MICBIAS enable and UnMute
- */
- ac108_write(twi_dev, ANA_ADC4_CTRL1, 0x07);
- /*
- * delay 50ms to let VREF/VRP faststart powerup stable,
- * then disable faststart
- */
- usleep(50 * 1000);
- /* VREF faststart disable */
- ac108_update_bits(twi_dev, PWR_CTRL7, 0x1 << VREF_FASTSTART_ENABLE,
- 0x0 << VREF_FASTSTART_ENABLE);
- /*VREFP faststart disable*/
- ac108_update_bits(twi_dev, PWR_CTRL9, 0x1 << VREFP_FASTSTART_ENABLE,
- 0x0 << VREFP_FASTSTART_ENABLE);
- #else
- /*** DMIC module Enable ***/
- /*DMIC1/2 Enable, while ADC DIG source select DMIC1/2*/
- ac108_write(twi_dev, DMIC_EN, 0x03);
- /*GPIO1 as DMIC1_DAT, GPIO2 as DMIC_CLK*/
- ac108_write(twi_dev, GPIO_CFG1, 0xee);
- /*GPIO3 as DMIC2_DAT*/
- ac108_write(twi_dev, GPIO_CFG2, 0x7e);
- #endif
- }
- static int ac108_codec_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params, struct snd_dai *dai)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- int i = 0;
- int ret = 0;
- unsigned char reg_val = 0;
- unsigned short channels = 0;
- unsigned short channels_en = 0;
- unsigned short sample_resolution = 0;
- snd_print("\n");
- /* set codec dai fmt */
- ret = snd_soc_dai_set_fmt(dai, param->daudio_format
- | (param->signal_inversion << SND_SOC_DAIFMT_SIG_SHIFT)
- | (param->daudio_master << SND_SOC_DAIFMT_MASTER_SHIFT));
- if (ret < 0) {
- snd_err("codec_dai set pll failed\n");
- return -EINVAL;
- }
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_print("AC108 not need playback.\n");
- return 0;
- }
- //AC108 hw init
- for (i = 0; i < param->chip_num; i++)
- ac108_codec_hw_init(¶m->twi_dev[i], param);
- //AC108 set sample rate
- for (i = 0; i < ARRAY_SIZE(ac108_sample_rate); i++) {
- if (ac108_sample_rate[i].real_val ==
- params_rate(params) / (AC108_ENCODING_EN ? AC108_ENCODING_CH_NUMS / 2 : 1)) {
- ac108_multi_chips_update_bits(ac108, ADC_SPRC,
- 0xf << ADC_FS_I2S1,
- ac108_sample_rate[i].reg_val << ADC_FS_I2S1);
- break;
- }
- }
- //AC108 set channels
- #if !AC108_SDO2_EN
- channels = params_channels(params) *
- (AC108_ENCODING_EN ? AC108_ENCODING_CH_NUMS/2 : 1);
- for (i = 0; i < (channels + 3) / 4; i++) {
- channels_en = (channels >= 4 * (i + 1)) ? 0x000f << (4 * i) :
- ((1 << (channels % 4)) - 1) << (4 * i);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL1, channels - 1);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL2, (unsigned char )channels_en);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL3, channels_en >> 8);
- }
- for (; i < param->chip_num; i++) {
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL1, 0);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL2, 0);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL3, 0);
- }
- #else
- channels = params_channels(params);
- for (i = 0; i < (channels + 3) / 4; i++) {
- //(2 >= 4*(i+1)) ? 0x000f<<(4*i) : ((1<<(2%4))-1)<<(4*i);
- channels_en = 0x03;
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL1, 2 - 1);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL2, (u8)channels_en);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL3, channels_en >> 8);
- }
- for (; i < param->chip_num; i++) {
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL1, 0);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL2, 0);
- ac108_write(¶m->twi_dev[i], I2S_TX1_CTRL3, 0);
- }
- for (i = 0; i < (channels + 3) / 4; i++) {
- //(2 >= 4*(i+1)) ? 0x000f<<(4*i) : ((1<<(2%4))-1)<<(4*i);
- channels_en = 0x03;
- ac108_write(¶m->twi_dev[i], I2S_TX2_CTRL1, 2 - 1);
- ac108_write(¶m->twi_dev[i], I2S_TX2_CTRL2, (u8)channels_en);
- ac108_write(¶m->twi_dev[i], I2S_TX2_CTRL3, channels_en >> 8);
- }
- for (; i < param->chip_num; i++) {
- ac108_write(¶m->twi_dev[i], I2S_TX2_CTRL1, 0);
- ac108_write(¶m->twi_dev[i], I2S_TX2_CTRL2, 0);
- ac108_write(¶m->twi_dev[i], I2S_TX2_CTRL3, 0);
- }
- #endif
- //AC108 set sample resorution
- switch (params_format(params)) {
- case SND_PCM_FORMAT_S16_LE:
- sample_resolution = 16;
- break;
- case SND_PCM_FORMAT_S24_LE:
- sample_resolution = 24;
- break;
- case SND_PCM_FORMAT_S32_LE:
- sample_resolution = 32;
- break;
- default:
- snd_err("AC108 don't supported the sample resolution: %u\n",
- params_format(params));
- return -EINVAL;
- }
- #if 0
- //AC108_ENCODING_EN
- //TX Encoding mode, SR add 4bits to mark channel number
- if ((sample_resolution <= 24) && (sample_resolution != 16))
- sample_resolution += 4;
- #endif
- for (i = 0; i < ARRAY_SIZE(ac108_sample_resolution); i++) {
- if (ac108_sample_resolution[i].real_val == sample_resolution) {
- ac108_multi_chips_update_bits(ac108, I2S_FMT_CTRL2,
- 0x7 << SAMPLE_RESOLUTION,
- ac108_sample_resolution[i].reg_val << SAMPLE_RESOLUTION);
- break;
- }
- }
- ac108_read(¶m->twi_dev[0], SYSCLK_CTRL, ®_val);
- if (reg_val & 0x80) {
- //PLLCLK Enable
- //PLL Common voltage Enable, PLL Enable
- ac108_multi_chips_update_bits(ac108, PLL_CTRL1,
- 0x1 << PLL_EN | 0x1 << PLL_COM_EN,
- 0x1 << PLL_EN | 0x1 << PLL_COM_EN);
- if (!(reg_val & 0x08)) {
- //SYSCLK select MCLK
- //GPIO4 output Clock 24MHz from DPLL
- ac108_multi_chips_update_bits(ac108, GPIO_CFG2,
- 0xf << GPIO4_SELECT, 0x9 << GPIO4_SELECT);
- }
- }
- return 0;
- }
- static int ac108_codec_set_sysclk(struct snd_dai *dai,
- int clk_id, unsigned int freq, int dir)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- snd_print("\n");
- //default: clk_id = 0;
- switch (clk_id) {
- case SYSCLK_SRC_MCLK:
- snd_print("AC108 SYSCLK source select MCLK.\n");
- //System Clock Source Select MCLK
- ac108_multi_chips_update_bits(ac108,
- SYSCLK_CTRL, 0x1 << SYSCLK_SRC,
- 0x0 << SYSCLK_SRC);
- break;
- case SYSCLK_SRC_PLL:
- snd_print("AC108 SYSCLK source select PLL.\n");
- //System Clock Source Select PLL
- ac108_multi_chips_update_bits(ac108,
- SYSCLK_CTRL, 0x1 << SYSCLK_SRC,
- 0x1 << SYSCLK_SRC);
- break;
- default:
- snd_err("AC108 SYSCLK source config error:%d\n\n", clk_id);
- return -EINVAL;
- }
- //SYSCLK Enable
- ac108_multi_chips_update_bits(ac108,
- SYSCLK_CTRL, 0x1 << SYSCLK_EN,
- 0x1 << SYSCLK_EN);
- //AC108 TX enable, Globle enable
- ac108_multi_chips_update_bits(ac108, I2S_CTRL,
- 0x1 << TXEN | 0x1 << GEN,
- 0x1 << TXEN | 0x1 << GEN);
- return 0;
- }
- static int ac108_codec_prepare(struct snd_pcm_substream *substream,
- struct snd_dai *dai)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- snd_print("\n");
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_print("ac108 playback prepare.\n");
- } else {
- snd_print("ac108 capture prepare.\n");
- }
- return 0;
- }
- void ac108_reg_show(void);
- static int ac108_codec_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_dai *dai)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- snd_print("\n");
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_print("ac108 playback trigger start.\n");
- } else {
- snd_print("ac108 capture trigger start\n");
- }
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_print("ac108 playback trigger stop.\n");
- } else {
- snd_print("ac108 capture trigger stop\n");
- }
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- static int ac108_codec_hw_free(struct snd_pcm_substream *substream,
- struct snd_dai *dai)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- snd_print("\n");
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_print("AC108 playback hw_free.\n");
- return 0;
- }
- //AC108 I2S Globle disable
- ac108_multi_chips_update_bits(ac108, I2S_CTRL,
- 0x1 << GEN, 0x0 << GEN);
- #ifdef AC108_IDLE_RESET_EN
- snd_print("AC108 reset all register to their default value\n");
- ac108_multi_chips_write(ac108, CHIP_AUDIO_RST, 0x12);
- #else
- //repair PLL version no sync problem && Encoding no DAT
- ac108_multi_chips_update_bits(ac108, PLL_CTRL1,
- 0x1 << PLL_EN | 0x1 << PLL_COM_EN,
- 0x0 << PLL_EN | 0x0 << PLL_COM_EN);
- ac108_multi_chips_update_bits(ac108, MOD_CLK_EN,
- 0x1 << I2S | 0x1 << ADC_DIGITAL,
- 0x0<<I2S | 0x0<<ADC_DIGITAL);
- ac108_multi_chips_update_bits(ac108, MOD_RST_CTRL,
- 0x1 << I2S | 0x1 << ADC_DIGITAL,
- 0x0 << I2S | 0x0 << ADC_DIGITAL);
- #endif
- return 0;
- }
- static void ac108_codec_shutdown(struct snd_pcm_substream *substream,
- struct snd_dai *dai)
- {
- struct snd_codec *codec = dai->component;
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- int ret = 0;
- unsigned int i = 0;
- snd_print("\n");
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- snd_print("AC108 playback shutdown.\n");
- } else {
- snd_print("AC108 capture shutdown.\n");
- }
- return;
- }
- static struct snd_dai_ops ac108_codec_dai_ops = {
- .startup = ac108_codec_startup,
- .set_sysclk = ac108_codec_set_sysclk,
- .set_pll = ac108_codec_set_pll,
- .set_clkdiv = ac108_codec_set_clkdiv,
- .set_fmt = ac108_codec_set_fmt,
- .hw_params = ac108_codec_hw_params,
- .prepare = ac108_codec_prepare,
- .trigger = ac108_codec_trigger,
- .hw_free = ac108_codec_hw_free,
- .shutdown = ac108_codec_shutdown,
- };
- static struct snd_dai ac108_codec_dai[] = {
- {
- .name = "ac108-codecdai",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 8,
- .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,
- .rate_min = 8000,
- .rate_max = 48000,
- },
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 8,
- .rates = SNDRV_PCM_RATE_8000_48000
- | SNDRV_PCM_RATE_KNOT,
- .formats = SNDRV_PCM_FMTBIT_S16_LE
- | SNDRV_PCM_FMTBIT_S24_LE,
- .rate_min = 8000,
- .rate_max = 48000,
- },
- .ops = &ac108_codec_dai_ops,
- },
- };
- static int ac108_codec_probe(struct snd_codec *codec)
- {
- unsigned char read_data = 0x0;
- struct ac108_priv *ac108 = NULL;
- unsigned int i = 0;
- twi_status_t ret = 0;
- unsigned char reset_cmd[2] = {0x0, 0x12};
- struct ac108_param default_param = {
- .chip_num = AC108_CHIP_NUM,
- .twi_dev = AC108_CHIP_CFG,
- .pga_gain = AC108_PGA_GAIN,
- .daudio_master = AC108_DAUDIO_MASTER,
- .daudio_format = AC108_DAUDIO_FORMAT,
- .signal_inversion = AC108_DAUDIO_SIG_INV,
- .lrck_period = AC108_LRCK_PERIOD,
- .slot_width = AC108_SLOT_WIDTH,
- };
- if (!codec->codec_dai) {
- snd_err("codec->codec_dai is null.\n");
- return -EFAULT;
- }
- ac108 = snd_malloc(sizeof(struct ac108_priv));
- if (!ac108) {
- snd_err("no memory\n");
- return -ENOMEM;
- }
- snd_print("codec para init.\n");
- codec->private_data = (void *)ac108;
- ac108->param = default_param;
- ac108->codec = codec;
- codec->codec_dai->component = codec;
- snd_print("init ac108 i2c port.\n");
- ret = ac108_init_i2c_device(ac108->param.twi_dev[i].bus);
- if (ret != TWI_STATUS_OK) {
- snd_err("init i2c err\n");
- ret = -EFAULT;
- goto err_twi_init;
- }
- for (i = 0; i < ac108->param.chip_num; i++) {
- hal_twi_control(ac108->param.twi_dev[i].bus, I2C_SLAVE, &default_param.twi_dev[i].addr);
- }
- snd_print("ac108 codec register finished.\n");
- return 0;
- err_twi_init:
- snd_free(ac108);
- return ret;
- }
- static int ac108_codec_remove(struct snd_codec *codec)
- {
- struct ac108_priv *ac108 = codec->private_data;
- struct ac108_param *param = &ac108->param;
- unsigned int i = 0;
- int ret = 0;
- snd_print("deinit ac108 i2c port.\n");
- ret = ac108_deinit_i2c_device(param->twi_dev[i].bus);
- if (ret != TWI_STATUS_OK) {
- snd_err("i2c deinit port %d failed.\n",
- param->twi_dev[i].bus);
- }
- snd_free(ac108);
- codec->private_data = NULL;
- return 0;
- }
- struct snd_codec ac108_codec = {
- .name = "ac108-codec",
- .codec_dai = ac108_codec_dai,
- .codec_dai_num = ARRAY_SIZE(ac108_codec_dai),
- .private_data = NULL,
- .probe = ac108_codec_probe,
- .remove = ac108_codec_remove,
- #ifdef AC108_KCONTROL_TEST_EN
- .controls = ac108_codec_controls,
- .num_controls = ARRAY_SIZE(ac108_codec_controls),
- #endif
- };
- /* for ac108 debug */
- void ac108_reg_dump_usage(void)
- {
- printf("\n\n=========ac108 debug===========\n");
- printf("Usage: ac108_reg [option]\n");
- printf("\t-l, ac108 dev list\n");
- printf("\t-h, tools help\n");
- printf("\t-d, ac108 dev addr(hex)\n");
- printf("\t-r, ac108 reg addr(hex)\n");
- printf("\t-n, ac108 reg read num(hex)\n");
- printf("\t-s, ac108 show all regs\n");
- printf("\t-w, ac108 write reg val(hex)\n");
- printf("\n");
- }
- void ac108_chip_list(void)
- {
- unsigned int chip_num = AC108_CHIP_NUM;
- struct twi_device twi_dev[] = AC108_CHIP_CFG;
- int i = 0;
- printf("\n\n=========ac108 show ===========\n");
- printf("\tac108 dev num:\t%d\n", chip_num);
- for (i = 0; i < chip_num; i++)
- printf("\t%d i2c%d-0x%02x\n", i, twi_dev[i].bus, twi_dev[i].addr);
- printf("===============================\n");
- }
- void ac108_reg_show(void)
- {
- unsigned int chip_num = AC108_CHIP_NUM;
- struct twi_device twi_dev[] = AC108_CHIP_CFG;
- unsigned char read_command;
- unsigned char read_data[1] = {0x0};
- twi_status_t ret = 0;
- unsigned int i = 0;
- unsigned int j = 0;
- for (i = 0; i < chip_num; i++) {
- printf("\n=========ac108 chip [i2c%d-0x%02x] ===========\n",
- twi_dev[i].bus, twi_dev[i].addr);
- for (j = 0; j <= AC108_REG_MAX; j++) {
- if (j % 8 == 0)
- printf("\n");
- read_command = 0x0 + j;
- ret = ac108_read(&twi_dev[i], read_command, read_data);
- if (ret != TWI_STATUS_OK) {
- snd_err("[i2c%d-0x%02x] read [REG-0x%02x,val-0x%02x] ret = %d.\n",
- twi_dev[i].bus, twi_dev[i].addr,
- read_command, read_data[0], ret);
- }
- printf("[0x%02x]: 0x%02x ", read_command, read_data[0]);
- }
- printf("\n=========================================\n");
- }
- }
- int cmd_ac108_reg(int argc, char ** argv)
- {
- twi_status_t ret = -1;
- unsigned int i;
- const struct option long_option[] = {
- {"help", 0, NULL, 'h'},
- {"list", 0, NULL, 'l'},
- {"addr", 1, NULL, 'd'},
- {"reg", 1, NULL, 'r'},
- {"num", 1, NULL, 'n'},
- {"show", 0, NULL, 's'},
- {"write", 1, NULL, 'w'},
- {NULL, 0, NULL, 0},
- };
- unsigned int chip_num = AC108_CHIP_NUM;
- struct twi_device twi_dev[] = AC108_CHIP_CFG;
- unsigned char reset_cmd[2] = {0x0, 0x12};
- unsigned char write_cmd[2] = {0x0, 0x0};
- unsigned char read_cmd[1] = {0x0};
- unsigned char read_data[1] = {0x0};
- unsigned int num = 1;
- unsigned int twi_addr = 0x3b;
- bool wr_flag = 0;
- while (1) {
- int c;
- if ((c = getopt_long(argc, argv, "hlsd:r:n:w:", long_option, NULL)) < 0)
- break;
- switch (c) {
- case 'h':
- ac108_reg_dump_usage();
- goto ac108_reg_exit;
- case 'l':
- ac108_chip_list();
- goto ac108_reg_exit;
- case 's':
- ac108_reg_show();
- goto ac108_reg_exit;
- case 'd':
- if (isdigit(*optarg)) {
- sscanf(optarg, "0x%x", &twi_addr);
- //twi_addr = atoi(optarg);
- printf("\ntwi_addr slave address is 0x%02x.\n", twi_addr);
- } else
- fprintf(stderr, "twi addr is not a digital value.\n");
- break;
- case 'r':
- if (isdigit(*optarg)) {
- sscanf(optarg, "0x%hhx", &read_cmd[0]);
- //read_cmd[0] = atoi(optarg);
- write_cmd[0] = read_cmd[0];
- printf("\nreg is 0x%02x.\n", read_cmd[0]);
- } else
- fprintf(stderr, "reg is not a digital value.\n");
- break;
- case 'n':
- if (isdigit(*optarg)) {
- sscanf(optarg, "0x%x", &num);
- //num = atoi(optarg);
- printf("\nnum is %d.\n", num);
- } else
- fprintf(stderr, "num is not a digital value.\n");
- break;
- case 'w':
- if (isdigit(*optarg)) {
- wr_flag = 1;
- sscanf(optarg, "0x%hhx", &write_cmd[1]);
- //write_cmd[1] = atoi(optarg);
- printf("\nwrite val is 0x%02x.\n", write_cmd[1]);
- } else
- fprintf(stderr, "write val is not a digital value.\n");
- break;
- default:
- fprintf(stderr, "Invalid switch or option needs an argument.\n");
- break;
- }
- }
- //checkout i2c port and addr.
- for (i = 0; i < chip_num; i++) {
- if (twi_addr == twi_dev[i].addr)
- break;
- }
- if (i >= chip_num) {
- fprintf(stderr, "the addr is error.\n");
- goto ac108_reg_exit;
- }
- if ((read_cmd[0] > AC108_REG_MAX) ||
- (write_cmd[0] > AC108_REG_MAX)) {
- fprintf(stderr, "the reg is over 0x%02x error.\n", AC108_REG_MAX);
- goto ac108_reg_exit;
- }
- if (wr_flag) {
- ret = ac108_write(&twi_dev[i], write_cmd[0], write_cmd[1]);
- if (ret != TWI_STATUS_OK) {
- snd_err("write error [REG-0x%02x,val-0x%02x] ret = %d.\n",
- write_cmd[0], write_cmd[1], ret);
- }
- ret = ac108_read(&twi_dev[i], read_cmd[0], read_data);
- if (ret != TWI_STATUS_OK) {
- snd_err("write error [I2C%d-0x%0x] REG=0x%02x, val=0x%02x] ret = %d.\n",
- twi_dev[i].bus, twi_dev[i].addr, read_cmd[0], read_data[0], ret);
- goto ac108_reg_exit;
- }
- if (read_data[0] == write_cmd[1]) {
- printf("write success, [I2C%d-0x%0x] REG=0x%02x, val=0x%02x] ret = %d.\n",
- twi_dev[i].bus, twi_dev[i].addr, read_cmd[0], read_data[0], ret);
- } else {
- printf("write val:0x%02x failed, [I2C%d-0x%0x] REG=0x%02x, val=0x%02x] ret = %d.\n",
- write_cmd[1], twi_dev[i].bus, twi_dev[i].addr, read_cmd[0], read_data[0], ret);
- }
- } else {
- for (i = 0; i < num; i++) {
- ret = ac108_read(&twi_dev[i], read_cmd[0], read_data);
- if (ret != TWI_STATUS_OK) {
- snd_err("read error [I2C%d-0x%0x] REG=0x%02x, val=0x%02x] ret = %d.\n",
- twi_dev[i].bus, twi_dev[i].addr, read_cmd[0], read_data[0], ret);
- goto ac108_reg_exit;
- } else {
- printf("read success. [I2C%d-0x%0x] REG=0x%02x, val=0x%02x].\n",
- twi_dev[i].bus, twi_dev[i].addr, read_cmd[0], read_data[0]);
- }
- }
- }
- ac108_reg_exit:
- return 0;
- }
- FINSH_FUNCTION_EXPORT_CMD(cmd_ac108_reg, ac108_reg, ac108 regs dump);
|