1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * cs42l42.c -- CS42L42 ALSA SoC audio driver
- *
- * Copyright 2016 Cirrus Logic, Inc.
- *
- * Author: James Schulman <james.schulman@cirrus.com>
- * Author: Brian Austin <brian.austin@cirrus.com>
- * Author: Michael White <michael.white@cirrus.com>
- */
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/version.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <linux/i2c.h>
- #include <linux/gpio.h>
- #include <linux/regmap.h>
- #include <linux/slab.h>
- #include <linux/platform_device.h>
- #include <linux/property.h>
- #include <linux/regulator/consumer.h>
- #include <linux/gpio/consumer.h>
- #include <linux/of_device.h>
- #include <sound/core.h>
- #include <sound/pcm.h>
- #include <sound/pcm_params.h>
- #include <sound/soc.h>
- #include <sound/soc-dapm.h>
- #include <sound/initval.h>
- #include <sound/tlv.h>
- #include <dt-bindings/sound/cs42l42.h>
- #include "cs42l42.h"
- static const struct reg_default cs42l42_reg_defaults[] = {
- { CS42L42_FRZ_CTL, 0x00 },
- { CS42L42_SRC_CTL, 0x10 },
- { CS42L42_MCLK_STATUS, 0x02 },
- { CS42L42_MCLK_CTL, 0x02 },
- { CS42L42_SFTRAMP_RATE, 0xA4 },
- { CS42L42_I2C_DEBOUNCE, 0x88 },
- { CS42L42_I2C_STRETCH, 0x03 },
- { CS42L42_I2C_TIMEOUT, 0xB7 },
- { CS42L42_PWR_CTL1, 0xFF },
- { CS42L42_PWR_CTL2, 0x84 },
- { CS42L42_PWR_CTL3, 0x20 },
- { CS42L42_RSENSE_CTL1, 0x40 },
- { CS42L42_RSENSE_CTL2, 0x00 },
- { CS42L42_OSC_SWITCH, 0x00 },
- { CS42L42_OSC_SWITCH_STATUS, 0x05 },
- { CS42L42_RSENSE_CTL3, 0x1B },
- { CS42L42_TSENSE_CTL, 0x1B },
- { CS42L42_TSRS_INT_DISABLE, 0x00 },
- { CS42L42_TRSENSE_STATUS, 0x00 },
- { CS42L42_HSDET_CTL1, 0x77 },
- { CS42L42_HSDET_CTL2, 0x00 },
- { CS42L42_HS_SWITCH_CTL, 0xF3 },
- { CS42L42_HS_DET_STATUS, 0x00 },
- { CS42L42_HS_CLAMP_DISABLE, 0x00 },
- { CS42L42_MCLK_SRC_SEL, 0x00 },
- { CS42L42_SPDIF_CLK_CFG, 0x00 },
- { CS42L42_FSYNC_PW_LOWER, 0x00 },
- { CS42L42_FSYNC_PW_UPPER, 0x00 },
- { CS42L42_FSYNC_P_LOWER, 0xF9 },
- { CS42L42_FSYNC_P_UPPER, 0x00 },
- { CS42L42_ASP_CLK_CFG, 0x00 },
- { CS42L42_ASP_FRM_CFG, 0x10 },
- { CS42L42_FS_RATE_EN, 0x00 },
- { CS42L42_IN_ASRC_CLK, 0x00 },
- { CS42L42_OUT_ASRC_CLK, 0x00 },
- { CS42L42_PLL_DIV_CFG1, 0x00 },
- { CS42L42_ADC_OVFL_STATUS, 0x00 },
- { CS42L42_MIXER_STATUS, 0x00 },
- { CS42L42_SRC_STATUS, 0x00 },
- { CS42L42_ASP_RX_STATUS, 0x00 },
- { CS42L42_ASP_TX_STATUS, 0x00 },
- { CS42L42_CODEC_STATUS, 0x00 },
- { CS42L42_DET_INT_STATUS1, 0x00 },
- { CS42L42_DET_INT_STATUS2, 0x00 },
- { CS42L42_SRCPL_INT_STATUS, 0x00 },
- { CS42L42_VPMON_STATUS, 0x00 },
- { CS42L42_PLL_LOCK_STATUS, 0x00 },
- { CS42L42_TSRS_PLUG_STATUS, 0x00 },
- { CS42L42_ADC_OVFL_INT_MASK, 0x01 },
- { CS42L42_MIXER_INT_MASK, 0x0F },
- { CS42L42_SRC_INT_MASK, 0x0F },
- { CS42L42_ASP_RX_INT_MASK, 0x1F },
- { CS42L42_ASP_TX_INT_MASK, 0x0F },
- { CS42L42_CODEC_INT_MASK, 0x03 },
- { CS42L42_SRCPL_INT_MASK, 0x7F },
- { CS42L42_VPMON_INT_MASK, 0x01 },
- { CS42L42_PLL_LOCK_INT_MASK, 0x01 },
- { CS42L42_TSRS_PLUG_INT_MASK, 0x0F },
- { CS42L42_PLL_CTL1, 0x00 },
- { CS42L42_PLL_DIV_FRAC0, 0x00 },
- { CS42L42_PLL_DIV_FRAC1, 0x00 },
- { CS42L42_PLL_DIV_FRAC2, 0x00 },
- { CS42L42_PLL_DIV_INT, 0x40 },
- { CS42L42_PLL_CTL3, 0x10 },
- { CS42L42_PLL_CAL_RATIO, 0x80 },
- { CS42L42_PLL_CTL4, 0x03 },
- { CS42L42_LOAD_DET_RCSTAT, 0x00 },
- { CS42L42_LOAD_DET_DONE, 0x00 },
- { CS42L42_LOAD_DET_EN, 0x00 },
- { CS42L42_HSBIAS_SC_AUTOCTL, 0x03 },
- { CS42L42_WAKE_CTL, 0xC0 },
- { CS42L42_ADC_DISABLE_MUTE, 0x00 },
- { CS42L42_TIPSENSE_CTL, 0x02 },
- { CS42L42_MISC_DET_CTL, 0x03 },
- { CS42L42_MIC_DET_CTL1, 0x1F },
- { CS42L42_MIC_DET_CTL2, 0x2F },
- { CS42L42_DET_STATUS1, 0x00 },
- { CS42L42_DET_STATUS2, 0x00 },
- { CS42L42_DET_INT1_MASK, 0xE0 },
- { CS42L42_DET_INT2_MASK, 0xFF },
- { CS42L42_HS_BIAS_CTL, 0xC2 },
- { CS42L42_ADC_CTL, 0x00 },
- { CS42L42_ADC_VOLUME, 0x00 },
- { CS42L42_ADC_WNF_HPF_CTL, 0x71 },
- { CS42L42_DAC_CTL1, 0x00 },
- { CS42L42_DAC_CTL2, 0x02 },
- { CS42L42_HP_CTL, 0x0D },
- { CS42L42_CLASSH_CTL, 0x07 },
- { CS42L42_MIXER_CHA_VOL, 0x3F },
- { CS42L42_MIXER_ADC_VOL, 0x3F },
- { CS42L42_MIXER_CHB_VOL, 0x3F },
- { CS42L42_EQ_COEF_IN0, 0x00 },
- { CS42L42_EQ_COEF_IN1, 0x00 },
- { CS42L42_EQ_COEF_IN2, 0x00 },
- { CS42L42_EQ_COEF_IN3, 0x00 },
- { CS42L42_EQ_COEF_RW, 0x00 },
- { CS42L42_EQ_COEF_OUT0, 0x00 },
- { CS42L42_EQ_COEF_OUT1, 0x00 },
- { CS42L42_EQ_COEF_OUT2, 0x00 },
- { CS42L42_EQ_COEF_OUT3, 0x00 },
- { CS42L42_EQ_INIT_STAT, 0x00 },
- { CS42L42_EQ_START_FILT, 0x00 },
- { CS42L42_EQ_MUTE_CTL, 0x00 },
- { CS42L42_SP_RX_CH_SEL, 0x04 },
- { CS42L42_SP_RX_ISOC_CTL, 0x04 },
- { CS42L42_SP_RX_FS, 0x8C },
- { CS42l42_SPDIF_CH_SEL, 0x0E },
- { CS42L42_SP_TX_ISOC_CTL, 0x04 },
- { CS42L42_SP_TX_FS, 0xCC },
- { CS42L42_SPDIF_SW_CTL1, 0x3F },
- { CS42L42_SRC_SDIN_FS, 0x40 },
- { CS42L42_SRC_SDOUT_FS, 0x40 },
- { CS42L42_SPDIF_CTL1, 0x01 },
- { CS42L42_SPDIF_CTL2, 0x00 },
- { CS42L42_SPDIF_CTL3, 0x00 },
- { CS42L42_SPDIF_CTL4, 0x42 },
- { CS42L42_ASP_TX_SZ_EN, 0x00 },
- { CS42L42_ASP_TX_CH_EN, 0x00 },
- { CS42L42_ASP_TX_CH_AP_RES, 0x0F },
- { CS42L42_ASP_TX_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_TX_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_TX_HIZ_DLY_CFG, 0x00 },
- { CS42L42_ASP_TX_CH2_BIT_MSB, 0x00 },
- { CS42L42_ASP_TX_CH2_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_EN, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH1_AP_RES, 0x03 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH2_AP_RES, 0x03 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH2_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH3_AP_RES, 0x03 },
- { CS42L42_ASP_RX_DAI0_CH3_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH3_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH4_AP_RES, 0x03 },
- { CS42L42_ASP_RX_DAI0_CH4_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI0_CH4_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI1_CH1_AP_RES, 0x03 },
- { CS42L42_ASP_RX_DAI1_CH1_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI1_CH1_BIT_LSB, 0x00 },
- { CS42L42_ASP_RX_DAI1_CH2_AP_RES, 0x03 },
- { CS42L42_ASP_RX_DAI1_CH2_BIT_MSB, 0x00 },
- { CS42L42_ASP_RX_DAI1_CH2_BIT_LSB, 0x00 },
- { CS42L42_SUB_REVID, 0x03 },
- };
- static bool cs42l42_readable_register(struct device *dev, unsigned int reg)
- {
- switch (reg) {
- case CS42L42_PAGE_REGISTER:
- case CS42L42_DEVID_AB:
- case CS42L42_DEVID_CD:
- case CS42L42_DEVID_E:
- case CS42L42_FABID:
- case CS42L42_REVID:
- case CS42L42_FRZ_CTL:
- case CS42L42_SRC_CTL:
- case CS42L42_MCLK_STATUS:
- case CS42L42_MCLK_CTL:
- case CS42L42_SFTRAMP_RATE:
- case CS42L42_I2C_DEBOUNCE:
- case CS42L42_I2C_STRETCH:
- case CS42L42_I2C_TIMEOUT:
- case CS42L42_PWR_CTL1:
- case CS42L42_PWR_CTL2:
- case CS42L42_PWR_CTL3:
- case CS42L42_RSENSE_CTL1:
- case CS42L42_RSENSE_CTL2:
- case CS42L42_OSC_SWITCH:
- case CS42L42_OSC_SWITCH_STATUS:
- case CS42L42_RSENSE_CTL3:
- case CS42L42_TSENSE_CTL:
- case CS42L42_TSRS_INT_DISABLE:
- case CS42L42_TRSENSE_STATUS:
- case CS42L42_HSDET_CTL1:
- case CS42L42_HSDET_CTL2:
- case CS42L42_HS_SWITCH_CTL:
- case CS42L42_HS_DET_STATUS:
- case CS42L42_HS_CLAMP_DISABLE:
- case CS42L42_MCLK_SRC_SEL:
- case CS42L42_SPDIF_CLK_CFG:
- case CS42L42_FSYNC_PW_LOWER:
- case CS42L42_FSYNC_PW_UPPER:
- case CS42L42_FSYNC_P_LOWER:
- case CS42L42_FSYNC_P_UPPER:
- case CS42L42_ASP_CLK_CFG:
- case CS42L42_ASP_FRM_CFG:
- case CS42L42_FS_RATE_EN:
- case CS42L42_IN_ASRC_CLK:
- case CS42L42_OUT_ASRC_CLK:
- case CS42L42_PLL_DIV_CFG1:
- case CS42L42_ADC_OVFL_STATUS:
- case CS42L42_MIXER_STATUS:
- case CS42L42_SRC_STATUS:
- case CS42L42_ASP_RX_STATUS:
- case CS42L42_ASP_TX_STATUS:
- case CS42L42_CODEC_STATUS:
- case CS42L42_DET_INT_STATUS1:
- case CS42L42_DET_INT_STATUS2:
- case CS42L42_SRCPL_INT_STATUS:
- case CS42L42_VPMON_STATUS:
- case CS42L42_PLL_LOCK_STATUS:
- case CS42L42_TSRS_PLUG_STATUS:
- case CS42L42_ADC_OVFL_INT_MASK:
- case CS42L42_MIXER_INT_MASK:
- case CS42L42_SRC_INT_MASK:
- case CS42L42_ASP_RX_INT_MASK:
- case CS42L42_ASP_TX_INT_MASK:
- case CS42L42_CODEC_INT_MASK:
- case CS42L42_SRCPL_INT_MASK:
- case CS42L42_VPMON_INT_MASK:
- case CS42L42_PLL_LOCK_INT_MASK:
- case CS42L42_TSRS_PLUG_INT_MASK:
- case CS42L42_PLL_CTL1:
- case CS42L42_PLL_DIV_FRAC0:
- case CS42L42_PLL_DIV_FRAC1:
- case CS42L42_PLL_DIV_FRAC2:
- case CS42L42_PLL_DIV_INT:
- case CS42L42_PLL_CTL3:
- case CS42L42_PLL_CAL_RATIO:
- case CS42L42_PLL_CTL4:
- case CS42L42_LOAD_DET_RCSTAT:
- case CS42L42_LOAD_DET_DONE:
- case CS42L42_LOAD_DET_EN:
- case CS42L42_HSBIAS_SC_AUTOCTL:
- case CS42L42_WAKE_CTL:
- case CS42L42_ADC_DISABLE_MUTE:
- case CS42L42_TIPSENSE_CTL:
- case CS42L42_MISC_DET_CTL:
- case CS42L42_MIC_DET_CTL1:
- case CS42L42_MIC_DET_CTL2:
- case CS42L42_DET_STATUS1:
- case CS42L42_DET_STATUS2:
- case CS42L42_DET_INT1_MASK:
- case CS42L42_DET_INT2_MASK:
- case CS42L42_HS_BIAS_CTL:
- case CS42L42_ADC_CTL:
- case CS42L42_ADC_VOLUME:
- case CS42L42_ADC_WNF_HPF_CTL:
- case CS42L42_DAC_CTL1:
- case CS42L42_DAC_CTL2:
- case CS42L42_HP_CTL:
- case CS42L42_CLASSH_CTL:
- case CS42L42_MIXER_CHA_VOL:
- case CS42L42_MIXER_ADC_VOL:
- case CS42L42_MIXER_CHB_VOL:
- case CS42L42_EQ_COEF_IN0:
- case CS42L42_EQ_COEF_IN1:
- case CS42L42_EQ_COEF_IN2:
- case CS42L42_EQ_COEF_IN3:
- case CS42L42_EQ_COEF_RW:
- case CS42L42_EQ_COEF_OUT0:
- case CS42L42_EQ_COEF_OUT1:
- case CS42L42_EQ_COEF_OUT2:
- case CS42L42_EQ_COEF_OUT3:
- case CS42L42_EQ_INIT_STAT:
- case CS42L42_EQ_START_FILT:
- case CS42L42_EQ_MUTE_CTL:
- case CS42L42_SP_RX_CH_SEL:
- case CS42L42_SP_RX_ISOC_CTL:
- case CS42L42_SP_RX_FS:
- case CS42l42_SPDIF_CH_SEL:
- case CS42L42_SP_TX_ISOC_CTL:
- case CS42L42_SP_TX_FS:
- case CS42L42_SPDIF_SW_CTL1:
- case CS42L42_SRC_SDIN_FS:
- case CS42L42_SRC_SDOUT_FS:
- case CS42L42_SPDIF_CTL1:
- case CS42L42_SPDIF_CTL2:
- case CS42L42_SPDIF_CTL3:
- case CS42L42_SPDIF_CTL4:
- case CS42L42_ASP_TX_SZ_EN:
- case CS42L42_ASP_TX_CH_EN:
- case CS42L42_ASP_TX_CH_AP_RES:
- case CS42L42_ASP_TX_CH1_BIT_MSB:
- case CS42L42_ASP_TX_CH1_BIT_LSB:
- case CS42L42_ASP_TX_HIZ_DLY_CFG:
- case CS42L42_ASP_TX_CH2_BIT_MSB:
- case CS42L42_ASP_TX_CH2_BIT_LSB:
- case CS42L42_ASP_RX_DAI0_EN:
- case CS42L42_ASP_RX_DAI0_CH1_AP_RES:
- case CS42L42_ASP_RX_DAI0_CH1_BIT_MSB:
- case CS42L42_ASP_RX_DAI0_CH1_BIT_LSB:
- case CS42L42_ASP_RX_DAI0_CH2_AP_RES:
- case CS42L42_ASP_RX_DAI0_CH2_BIT_MSB:
- case CS42L42_ASP_RX_DAI0_CH2_BIT_LSB:
- case CS42L42_ASP_RX_DAI0_CH3_AP_RES:
- case CS42L42_ASP_RX_DAI0_CH3_BIT_MSB:
- case CS42L42_ASP_RX_DAI0_CH3_BIT_LSB:
- case CS42L42_ASP_RX_DAI0_CH4_AP_RES:
- case CS42L42_ASP_RX_DAI0_CH4_BIT_MSB:
- case CS42L42_ASP_RX_DAI0_CH4_BIT_LSB:
- case CS42L42_ASP_RX_DAI1_CH1_AP_RES:
- case CS42L42_ASP_RX_DAI1_CH1_BIT_MSB:
- case CS42L42_ASP_RX_DAI1_CH1_BIT_LSB:
- case CS42L42_ASP_RX_DAI1_CH2_AP_RES:
- case CS42L42_ASP_RX_DAI1_CH2_BIT_MSB:
- case CS42L42_ASP_RX_DAI1_CH2_BIT_LSB:
- case CS42L42_SUB_REVID:
- return true;
- default:
- return false;
- }
- }
- static bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
- {
- switch (reg) {
- case CS42L42_DEVID_AB:
- case CS42L42_DEVID_CD:
- case CS42L42_DEVID_E:
- case CS42L42_MCLK_STATUS:
- case CS42L42_TRSENSE_STATUS:
- case CS42L42_HS_DET_STATUS:
- case CS42L42_ADC_OVFL_STATUS:
- case CS42L42_MIXER_STATUS:
- case CS42L42_SRC_STATUS:
- case CS42L42_ASP_RX_STATUS:
- case CS42L42_ASP_TX_STATUS:
- case CS42L42_CODEC_STATUS:
- case CS42L42_DET_INT_STATUS1:
- case CS42L42_DET_INT_STATUS2:
- case CS42L42_SRCPL_INT_STATUS:
- case CS42L42_VPMON_STATUS:
- case CS42L42_PLL_LOCK_STATUS:
- case CS42L42_TSRS_PLUG_STATUS:
- case CS42L42_LOAD_DET_RCSTAT:
- case CS42L42_LOAD_DET_DONE:
- case CS42L42_DET_STATUS1:
- case CS42L42_DET_STATUS2:
- return true;
- default:
- return false;
- }
- }
- static const struct regmap_range_cfg cs42l42_page_range = {
- .name = "Pages",
- .range_min = 0,
- .range_max = CS42L42_MAX_REGISTER,
- .selector_reg = CS42L42_PAGE_REGISTER,
- .selector_mask = 0xff,
- .selector_shift = 0,
- .window_start = 0,
- .window_len = 256,
- };
- static const struct regmap_config cs42l42_regmap = {
- .reg_bits = 8,
- .val_bits = 8,
- .readable_reg = cs42l42_readable_register,
- .volatile_reg = cs42l42_volatile_register,
- .ranges = &cs42l42_page_range,
- .num_ranges = 1,
- .max_register = CS42L42_MAX_REGISTER,
- .reg_defaults = cs42l42_reg_defaults,
- .num_reg_defaults = ARRAY_SIZE(cs42l42_reg_defaults),
- .cache_type = REGCACHE_RBTREE,
- .use_single_read = true,
- .use_single_write = true,
- };
- static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
- static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
- static const char * const cs42l42_hpf_freq_text[] = {
- "1.86Hz", "120Hz", "235Hz", "466Hz"
- };
- static SOC_ENUM_SINGLE_DECL(cs42l42_hpf_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
- CS42L42_ADC_HPF_CF_SHIFT,
- cs42l42_hpf_freq_text);
- static const char * const cs42l42_wnf3_freq_text[] = {
- "160Hz", "180Hz", "200Hz", "220Hz",
- "240Hz", "260Hz", "280Hz", "300Hz"
- };
- static SOC_ENUM_SINGLE_DECL(cs42l42_wnf3_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
- CS42L42_ADC_WNF_CF_SHIFT,
- cs42l42_wnf3_freq_text);
- static const struct snd_kcontrol_new cs42l42_snd_controls[] = {
- /* ADC Volume and Filter Controls */
- SOC_SINGLE("ADC Notch Switch", CS42L42_ADC_CTL,
- CS42L42_ADC_NOTCH_DIS_SHIFT, true, true),
- SOC_SINGLE("ADC Weak Force Switch", CS42L42_ADC_CTL,
- CS42L42_ADC_FORCE_WEAK_VCM_SHIFT, true, false),
- SOC_SINGLE("ADC Invert Switch", CS42L42_ADC_CTL,
- CS42L42_ADC_INV_SHIFT, true, false),
- SOC_SINGLE("ADC Boost Switch", CS42L42_ADC_CTL,
- CS42L42_ADC_DIG_BOOST_SHIFT, true, false),
- SOC_SINGLE_S8_TLV("ADC Volume", CS42L42_ADC_VOLUME, -97, 12, adc_tlv),
- SOC_SINGLE("ADC WNF Switch", CS42L42_ADC_WNF_HPF_CTL,
- CS42L42_ADC_WNF_EN_SHIFT, true, false),
- SOC_SINGLE("ADC HPF Switch", CS42L42_ADC_WNF_HPF_CTL,
- CS42L42_ADC_HPF_EN_SHIFT, true, false),
- SOC_ENUM("HPF Corner Freq", cs42l42_hpf_freq_enum),
- SOC_ENUM("WNF 3dB Freq", cs42l42_wnf3_freq_enum),
- /* DAC Volume and Filter Controls */
- SOC_SINGLE("DACA Invert Switch", CS42L42_DAC_CTL1,
- CS42L42_DACA_INV_SHIFT, true, false),
- SOC_SINGLE("DACB Invert Switch", CS42L42_DAC_CTL1,
- CS42L42_DACB_INV_SHIFT, true, false),
- SOC_SINGLE("DAC HPF Switch", CS42L42_DAC_CTL2,
- CS42L42_DAC_HPF_EN_SHIFT, true, false),
- SOC_DOUBLE_R_TLV("Mixer Volume", CS42L42_MIXER_CHA_VOL,
- CS42L42_MIXER_CHB_VOL, CS42L42_MIXER_CH_VOL_SHIFT,
- 0x3f, 1, mixer_tlv)
- };
- static int cs42l42_hpdrv_evt(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
- {
- struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
- if (event & SND_SOC_DAPM_POST_PMU) {
- /* Enable the channels */
- snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_EN,
- CS42L42_ASP_RX0_CH_EN_MASK,
- (CS42L42_ASP_RX0_CH1_EN |
- CS42L42_ASP_RX0_CH2_EN) <<
- CS42L42_ASP_RX0_CH_EN_SHIFT);
- /* Power up */
- snd_soc_component_update_bits(component, CS42L42_PWR_CTL1,
- CS42L42_ASP_DAI_PDN_MASK | CS42L42_MIXER_PDN_MASK |
- CS42L42_HP_PDN_MASK, 0);
- } else if (event & SND_SOC_DAPM_PRE_PMD) {
- /* Disable the channels */
- snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_EN,
- CS42L42_ASP_RX0_CH_EN_MASK, 0);
- /* Power down */
- snd_soc_component_update_bits(component, CS42L42_PWR_CTL1,
- CS42L42_ASP_DAI_PDN_MASK | CS42L42_MIXER_PDN_MASK |
- CS42L42_HP_PDN_MASK,
- CS42L42_ASP_DAI_PDN_MASK | CS42L42_MIXER_PDN_MASK |
- CS42L42_HP_PDN_MASK);
- } else {
- dev_err(component->dev, "Invalid event 0x%x\n", event);
- }
- return 0;
- }
- static const struct snd_soc_dapm_widget cs42l42_dapm_widgets[] = {
- SND_SOC_DAPM_OUTPUT("HP"),
- SND_SOC_DAPM_AIF_IN("SDIN", NULL, 0, CS42L42_ASP_CLK_CFG,
- CS42L42_ASP_SCLK_EN_SHIFT, false),
- SND_SOC_DAPM_OUT_DRV_E("HPDRV", SND_SOC_NOPM, 0,
- 0, NULL, 0, cs42l42_hpdrv_evt,
- SND_SOC_DAPM_POST_PMU |
- SND_SOC_DAPM_PRE_PMD)
- };
- static const struct snd_soc_dapm_route cs42l42_audio_map[] = {
- {"SDIN", NULL, "Playback"},
- {"HPDRV", NULL, "SDIN"},
- {"HP", NULL, "HPDRV"}
- };
- static int cs42l42_set_bias_level(struct snd_soc_component *component,
- enum snd_soc_bias_level level)
- {
- struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
- int ret;
- switch (level) {
- case SND_SOC_BIAS_ON:
- break;
- case SND_SOC_BIAS_PREPARE:
- break;
- case SND_SOC_BIAS_STANDBY:
- if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
- regcache_cache_only(cs42l42->regmap, false);
- regcache_sync(cs42l42->regmap);
- ret = regulator_bulk_enable(
- ARRAY_SIZE(cs42l42->supplies),
- cs42l42->supplies);
- if (ret != 0) {
- dev_err(component->dev,
- "Failed to enable regulators: %d\n",
- ret);
- return ret;
- }
- }
- break;
- case SND_SOC_BIAS_OFF:
- regcache_cache_only(cs42l42->regmap, true);
- regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
- cs42l42->supplies);
- break;
- }
- return 0;
- }
- static int cs42l42_component_probe(struct snd_soc_component *component)
- {
- struct cs42l42_private *cs42l42 =
- (struct cs42l42_private *)snd_soc_component_get_drvdata(component);
- cs42l42->component = component;
- return 0;
- }
- static const struct snd_soc_component_driver soc_component_dev_cs42l42 = {
- .probe = cs42l42_component_probe,
- .set_bias_level = cs42l42_set_bias_level,
- .dapm_widgets = cs42l42_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(cs42l42_dapm_widgets),
- .dapm_routes = cs42l42_audio_map,
- .num_dapm_routes = ARRAY_SIZE(cs42l42_audio_map),
- .controls = cs42l42_snd_controls,
- .num_controls = ARRAY_SIZE(cs42l42_snd_controls),
- .idle_bias_on = 1,
- .endianness = 1,
- .non_legacy_dai_naming = 1,
- };
- struct cs42l42_pll_params {
- u32 sclk;
- u8 mclk_div;
- u8 mclk_src_sel;
- u8 sclk_prediv;
- u8 pll_div_int;
- u32 pll_div_frac;
- u8 pll_mode;
- u8 pll_divout;
- u32 mclk_int;
- u8 pll_cal_ratio;
- };
- /*
- * Common PLL Settings for given SCLK
- * Table 4-5 from the Datasheet
- */
- static const struct cs42l42_pll_params pll_ratio_table[] = {
- { 1536000, 0, 1, 0x00, 0x7D, 0x000000, 0x03, 0x10, 12000000, 125 },
- { 2822400, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 },
- { 3000000, 0, 1, 0x00, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 },
- { 3072000, 0, 1, 0x00, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 },
- { 4000000, 0, 1, 0x00, 0x30, 0x800000, 0x03, 0x10, 12000000, 96 },
- { 4096000, 0, 1, 0x00, 0x2E, 0xE00000, 0x03, 0x10, 12000000, 94 },
- { 5644800, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 11289600, 128 },
- { 6000000, 0, 1, 0x01, 0x40, 0x000000, 0x03, 0x10, 12000000, 128 },
- { 6144000, 0, 1, 0x01, 0x3E, 0x800000, 0x03, 0x10, 12000000, 125 },
- { 11289600, 0, 0, 0, 0, 0, 0, 0, 11289600, 0 },
- { 12000000, 0, 0, 0, 0, 0, 0, 0, 12000000, 0 },
- { 12288000, 0, 0, 0, 0, 0, 0, 0, 12288000, 0 },
- { 22579200, 1, 0, 0, 0, 0, 0, 0, 22579200, 0 },
- { 24000000, 1, 0, 0, 0, 0, 0, 0, 24000000, 0 },
- { 24576000, 1, 0, 0, 0, 0, 0, 0, 24576000, 0 }
- };
- static int cs42l42_pll_config(struct snd_soc_component *component)
- {
- struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
- int i;
- u32 fsync;
- for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
- if (pll_ratio_table[i].sclk == cs42l42->sclk) {
- /* Configure the internal sample rate */
- snd_soc_component_update_bits(component, CS42L42_MCLK_CTL,
- CS42L42_INTERNAL_FS_MASK,
- ((pll_ratio_table[i].mclk_int !=
- 12000000) &&
- (pll_ratio_table[i].mclk_int !=
- 24000000)) <<
- CS42L42_INTERNAL_FS_SHIFT);
- /* Set the MCLK src (PLL or SCLK) and the divide
- * ratio
- */
- snd_soc_component_update_bits(component, CS42L42_MCLK_SRC_SEL,
- CS42L42_MCLK_SRC_SEL_MASK |
- CS42L42_MCLKDIV_MASK,
- (pll_ratio_table[i].mclk_src_sel
- << CS42L42_MCLK_SRC_SEL_SHIFT) |
- (pll_ratio_table[i].mclk_div <<
- CS42L42_MCLKDIV_SHIFT));
- /* Set up the LRCLK */
- fsync = cs42l42->sclk / cs42l42->srate;
- if (((fsync * cs42l42->srate) != cs42l42->sclk)
- || ((fsync % 2) != 0)) {
- dev_err(component->dev,
- "Unsupported sclk %d/sample rate %d\n",
- cs42l42->sclk,
- cs42l42->srate);
- return -EINVAL;
- }
- /* Set the LRCLK period */
- snd_soc_component_update_bits(component,
- CS42L42_FSYNC_P_LOWER,
- CS42L42_FSYNC_PERIOD_MASK,
- CS42L42_FRAC0_VAL(fsync - 1) <<
- CS42L42_FSYNC_PERIOD_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_FSYNC_P_UPPER,
- CS42L42_FSYNC_PERIOD_MASK,
- CS42L42_FRAC1_VAL(fsync - 1) <<
- CS42L42_FSYNC_PERIOD_SHIFT);
- /* Set the LRCLK to 50% duty cycle */
- fsync = fsync / 2;
- snd_soc_component_update_bits(component,
- CS42L42_FSYNC_PW_LOWER,
- CS42L42_FSYNC_PULSE_WIDTH_MASK,
- CS42L42_FRAC0_VAL(fsync - 1) <<
- CS42L42_FSYNC_PULSE_WIDTH_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_FSYNC_PW_UPPER,
- CS42L42_FSYNC_PULSE_WIDTH_MASK,
- CS42L42_FRAC1_VAL(fsync - 1) <<
- CS42L42_FSYNC_PULSE_WIDTH_SHIFT);
- /* Set the sample rates (96k or lower) */
- snd_soc_component_update_bits(component, CS42L42_FS_RATE_EN,
- CS42L42_FS_EN_MASK,
- (CS42L42_FS_EN_IASRC_96K |
- CS42L42_FS_EN_OASRC_96K) <<
- CS42L42_FS_EN_SHIFT);
- /* Set the input/output internal MCLK clock ~12 MHz */
- snd_soc_component_update_bits(component, CS42L42_IN_ASRC_CLK,
- CS42L42_CLK_IASRC_SEL_MASK,
- CS42L42_CLK_IASRC_SEL_12 <<
- CS42L42_CLK_IASRC_SEL_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_OUT_ASRC_CLK,
- CS42L42_CLK_OASRC_SEL_MASK,
- CS42L42_CLK_OASRC_SEL_12 <<
- CS42L42_CLK_OASRC_SEL_SHIFT);
- if (pll_ratio_table[i].mclk_src_sel == 0) {
- /* Pass the clock straight through */
- snd_soc_component_update_bits(component,
- CS42L42_PLL_CTL1,
- CS42L42_PLL_START_MASK, 0);
- } else {
- /* Configure PLL per table 4-5 */
- snd_soc_component_update_bits(component,
- CS42L42_PLL_DIV_CFG1,
- CS42L42_SCLK_PREDIV_MASK,
- pll_ratio_table[i].sclk_prediv
- << CS42L42_SCLK_PREDIV_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_PLL_DIV_INT,
- CS42L42_PLL_DIV_INT_MASK,
- pll_ratio_table[i].pll_div_int
- << CS42L42_PLL_DIV_INT_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_PLL_DIV_FRAC0,
- CS42L42_PLL_DIV_FRAC_MASK,
- CS42L42_FRAC0_VAL(
- pll_ratio_table[i].pll_div_frac)
- << CS42L42_PLL_DIV_FRAC_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_PLL_DIV_FRAC1,
- CS42L42_PLL_DIV_FRAC_MASK,
- CS42L42_FRAC1_VAL(
- pll_ratio_table[i].pll_div_frac)
- << CS42L42_PLL_DIV_FRAC_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_PLL_DIV_FRAC2,
- CS42L42_PLL_DIV_FRAC_MASK,
- CS42L42_FRAC2_VAL(
- pll_ratio_table[i].pll_div_frac)
- << CS42L42_PLL_DIV_FRAC_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_PLL_CTL4,
- CS42L42_PLL_MODE_MASK,
- pll_ratio_table[i].pll_mode
- << CS42L42_PLL_MODE_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_PLL_CTL3,
- CS42L42_PLL_DIVOUT_MASK,
- pll_ratio_table[i].pll_divout
- << CS42L42_PLL_DIVOUT_SHIFT);
- snd_soc_component_update_bits(component,
- CS42L42_PLL_CAL_RATIO,
- CS42L42_PLL_CAL_RATIO_MASK,
- pll_ratio_table[i].pll_cal_ratio
- << CS42L42_PLL_CAL_RATIO_SHIFT);
- }
- return 0;
- }
- }
- return -EINVAL;
- }
- static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
- {
- struct snd_soc_component *component = codec_dai->component;
- u32 asp_cfg_val = 0;
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFM:
- asp_cfg_val |= CS42L42_ASP_MASTER_MODE <<
- CS42L42_ASP_MODE_SHIFT;
- break;
- case SND_SOC_DAIFMT_CBS_CFS:
- asp_cfg_val |= CS42L42_ASP_SLAVE_MODE <<
- CS42L42_ASP_MODE_SHIFT;
- break;
- default:
- return -EINVAL;
- }
- /* interface format */
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- /*
- * 5050 mode, frame starts on falling edge of LRCLK,
- * frame delayed by 1.0 SCLKs
- */
- snd_soc_component_update_bits(component,
- CS42L42_ASP_FRM_CFG,
- CS42L42_ASP_STP_MASK |
- CS42L42_ASP_5050_MASK |
- CS42L42_ASP_FSD_MASK,
- CS42L42_ASP_5050_MASK |
- (CS42L42_ASP_FSD_1_0 <<
- CS42L42_ASP_FSD_SHIFT));
- break;
- default:
- return -EINVAL;
- }
- /* Bitclock/frame inversion */
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT;
- break;
- case SND_SOC_DAIFMT_NB_IF:
- asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT;
- asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- break;
- case SND_SOC_DAIFMT_IB_IF:
- asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT;
- break;
- }
- snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG, CS42L42_ASP_MODE_MASK |
- CS42L42_ASP_SCPOL_MASK |
- CS42L42_ASP_LCPOL_MASK,
- asp_cfg_val);
- return 0;
- }
- static int cs42l42_pcm_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;
- struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
- unsigned int width = (params_width(params) / 8) - 1;
- unsigned int val = 0;
- cs42l42->srate = params_rate(params);
- switch(substream->stream) {
- case SNDRV_PCM_STREAM_PLAYBACK:
- val |= width << CS42L42_ASP_RX_CH_RES_SHIFT;
- /* channel 1 on low LRCLK */
- snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH1_AP_RES,
- CS42L42_ASP_RX_CH_AP_MASK |
- CS42L42_ASP_RX_CH_RES_MASK, val);
- /* Channel 2 on high LRCLK */
- val |= CS42L42_ASP_RX_CH_AP_HI << CS42L42_ASP_RX_CH_AP_SHIFT;
- snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH2_AP_RES,
- CS42L42_ASP_RX_CH_AP_MASK |
- CS42L42_ASP_RX_CH_RES_MASK, val);
- break;
- default:
- break;
- }
- return cs42l42_pll_config(component);
- }
- static int cs42l42_set_sysclk(struct snd_soc_dai *dai,
- int clk_id, unsigned int freq, int dir)
- {
- struct snd_soc_component *component = dai->component;
- struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
- cs42l42->sclk = freq;
- return 0;
- }
- static int cs42l42_mute(struct snd_soc_dai *dai, int mute, int direction)
- {
- struct snd_soc_component *component = dai->component;
- unsigned int regval;
- u8 fullScaleVol;
- if (mute) {
- /* Mark SCLK as not present to turn on the internal
- * oscillator.
- */
- snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH,
- CS42L42_SCLK_PRESENT_MASK, 0);
- snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
- CS42L42_PLL_START_MASK,
- 0 << CS42L42_PLL_START_SHIFT);
- /* Mute the headphone */
- snd_soc_component_update_bits(component, CS42L42_HP_CTL,
- CS42L42_HP_ANA_AMUTE_MASK |
- CS42L42_HP_ANA_BMUTE_MASK,
- CS42L42_HP_ANA_AMUTE_MASK |
- CS42L42_HP_ANA_BMUTE_MASK);
- } else {
- snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
- CS42L42_PLL_START_MASK,
- 1 << CS42L42_PLL_START_SHIFT);
- /* Read the headphone load */
- regval = snd_soc_component_read(component, CS42L42_LOAD_DET_RCSTAT);
- if (((regval & CS42L42_RLA_STAT_MASK) >>
- CS42L42_RLA_STAT_SHIFT) == CS42L42_RLA_STAT_15_OHM) {
- fullScaleVol = CS42L42_HP_FULL_SCALE_VOL_MASK;
- } else {
- fullScaleVol = 0;
- }
- /* Un-mute the headphone, set the full scale volume flag */
- snd_soc_component_update_bits(component, CS42L42_HP_CTL,
- CS42L42_HP_ANA_AMUTE_MASK |
- CS42L42_HP_ANA_BMUTE_MASK |
- CS42L42_HP_FULL_SCALE_VOL_MASK, fullScaleVol);
- /* Mark SCLK as present, turn off internal oscillator */
- snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH,
- CS42L42_SCLK_PRESENT_MASK,
- CS42L42_SCLK_PRESENT_MASK);
- }
- return 0;
- }
- #define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE |\
- SNDRV_PCM_FMTBIT_S32_LE )
- static const struct snd_soc_dai_ops cs42l42_ops = {
- .hw_params = cs42l42_pcm_hw_params,
- .set_fmt = cs42l42_set_dai_fmt,
- .set_sysclk = cs42l42_set_sysclk,
- .mute_stream = cs42l42_mute,
- .no_capture_mute = 1,
- };
- static struct snd_soc_dai_driver cs42l42_dai = {
- .name = "cs42l42",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = CS42L42_FORMATS,
- },
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_192000,
- .formats = CS42L42_FORMATS,
- },
- .ops = &cs42l42_ops,
- };
- static void cs42l42_process_hs_type_detect(struct cs42l42_private *cs42l42)
- {
- unsigned int hs_det_status;
- unsigned int int_status;
- /* Mask the auto detect interrupt */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_CODEC_INT_MASK,
- CS42L42_PDN_DONE_MASK |
- CS42L42_HSDET_AUTO_DONE_MASK,
- (1 << CS42L42_PDN_DONE_SHIFT) |
- (1 << CS42L42_HSDET_AUTO_DONE_SHIFT));
- /* Set hs detect to automatic, disabled mode */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSDET_CTL2,
- CS42L42_HSDET_CTRL_MASK |
- CS42L42_HSDET_SET_MASK |
- CS42L42_HSBIAS_REF_MASK |
- CS42L42_HSDET_AUTO_TIME_MASK,
- (2 << CS42L42_HSDET_CTRL_SHIFT) |
- (2 << CS42L42_HSDET_SET_SHIFT) |
- (0 << CS42L42_HSBIAS_REF_SHIFT) |
- (3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
- /* Read and save the hs detection result */
- regmap_read(cs42l42->regmap, CS42L42_HS_DET_STATUS, &hs_det_status);
- cs42l42->hs_type = (hs_det_status & CS42L42_HSDET_TYPE_MASK) >>
- CS42L42_HSDET_TYPE_SHIFT;
- /* Set up button detection */
- if ((cs42l42->hs_type == CS42L42_PLUG_CTIA) ||
- (cs42l42->hs_type == CS42L42_PLUG_OMTP)) {
- /* Set auto HS bias settings to default */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSBIAS_SC_AUTOCTL,
- CS42L42_HSBIAS_SENSE_EN_MASK |
- CS42L42_AUTO_HSBIAS_HIZ_MASK |
- CS42L42_TIP_SENSE_EN_MASK |
- CS42L42_HSBIAS_SENSE_TRIP_MASK,
- (0 << CS42L42_HSBIAS_SENSE_EN_SHIFT) |
- (0 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT) |
- (0 << CS42L42_TIP_SENSE_EN_SHIFT) |
- (3 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT));
- /* Set up hs detect level sensitivity */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MIC_DET_CTL1,
- CS42L42_LATCH_TO_VP_MASK |
- CS42L42_EVENT_STAT_SEL_MASK |
- CS42L42_HS_DET_LEVEL_MASK,
- (1 << CS42L42_LATCH_TO_VP_SHIFT) |
- (0 << CS42L42_EVENT_STAT_SEL_SHIFT) |
- (cs42l42->bias_thresholds[0] <<
- CS42L42_HS_DET_LEVEL_SHIFT));
- /* Set auto HS bias settings to default */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSBIAS_SC_AUTOCTL,
- CS42L42_HSBIAS_SENSE_EN_MASK |
- CS42L42_AUTO_HSBIAS_HIZ_MASK |
- CS42L42_TIP_SENSE_EN_MASK |
- CS42L42_HSBIAS_SENSE_TRIP_MASK,
- (1 << CS42L42_HSBIAS_SENSE_EN_SHIFT) |
- (1 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT) |
- (0 << CS42L42_TIP_SENSE_EN_SHIFT) |
- (3 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT));
- /* Turn on level detect circuitry */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MISC_DET_CTL,
- CS42L42_DETECT_MODE_MASK |
- CS42L42_HSBIAS_CTL_MASK |
- CS42L42_PDN_MIC_LVL_DET_MASK,
- (0 << CS42L42_DETECT_MODE_SHIFT) |
- (3 << CS42L42_HSBIAS_CTL_SHIFT) |
- (0 << CS42L42_PDN_MIC_LVL_DET_SHIFT));
- msleep(cs42l42->btn_det_init_dbnce);
- /* Clear any button interrupts before unmasking them */
- regmap_read(cs42l42->regmap, CS42L42_DET_INT_STATUS2,
- &int_status);
- /* Unmask button detect interrupts */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_DET_INT2_MASK,
- CS42L42_M_DETECT_TF_MASK |
- CS42L42_M_DETECT_FT_MASK |
- CS42L42_M_HSBIAS_HIZ_MASK |
- CS42L42_M_SHORT_RLS_MASK |
- CS42L42_M_SHORT_DET_MASK,
- (0 << CS42L42_M_DETECT_TF_SHIFT) |
- (0 << CS42L42_M_DETECT_FT_SHIFT) |
- (0 << CS42L42_M_HSBIAS_HIZ_SHIFT) |
- (1 << CS42L42_M_SHORT_RLS_SHIFT) |
- (1 << CS42L42_M_SHORT_DET_SHIFT));
- } else {
- /* Make sure button detect and HS bias circuits are off */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MISC_DET_CTL,
- CS42L42_DETECT_MODE_MASK |
- CS42L42_HSBIAS_CTL_MASK |
- CS42L42_PDN_MIC_LVL_DET_MASK,
- (0 << CS42L42_DETECT_MODE_SHIFT) |
- (1 << CS42L42_HSBIAS_CTL_SHIFT) |
- (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT));
- }
- regmap_update_bits(cs42l42->regmap,
- CS42L42_DAC_CTL2,
- CS42L42_HPOUT_PULLDOWN_MASK |
- CS42L42_HPOUT_LOAD_MASK |
- CS42L42_HPOUT_CLAMP_MASK |
- CS42L42_DAC_HPF_EN_MASK |
- CS42L42_DAC_MON_EN_MASK,
- (0 << CS42L42_HPOUT_PULLDOWN_SHIFT) |
- (0 << CS42L42_HPOUT_LOAD_SHIFT) |
- (0 << CS42L42_HPOUT_CLAMP_SHIFT) |
- (1 << CS42L42_DAC_HPF_EN_SHIFT) |
- (0 << CS42L42_DAC_MON_EN_SHIFT));
- /* Unmask tip sense interrupts */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_TSRS_PLUG_INT_MASK,
- CS42L42_RS_PLUG_MASK |
- CS42L42_RS_UNPLUG_MASK |
- CS42L42_TS_PLUG_MASK |
- CS42L42_TS_UNPLUG_MASK,
- (1 << CS42L42_RS_PLUG_SHIFT) |
- (1 << CS42L42_RS_UNPLUG_SHIFT) |
- (0 << CS42L42_TS_PLUG_SHIFT) |
- (0 << CS42L42_TS_UNPLUG_SHIFT));
- }
- static void cs42l42_init_hs_type_detect(struct cs42l42_private *cs42l42)
- {
- /* Mask tip sense interrupts */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_TSRS_PLUG_INT_MASK,
- CS42L42_RS_PLUG_MASK |
- CS42L42_RS_UNPLUG_MASK |
- CS42L42_TS_PLUG_MASK |
- CS42L42_TS_UNPLUG_MASK,
- (1 << CS42L42_RS_PLUG_SHIFT) |
- (1 << CS42L42_RS_UNPLUG_SHIFT) |
- (1 << CS42L42_TS_PLUG_SHIFT) |
- (1 << CS42L42_TS_UNPLUG_SHIFT));
- /* Make sure button detect and HS bias circuits are off */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MISC_DET_CTL,
- CS42L42_DETECT_MODE_MASK |
- CS42L42_HSBIAS_CTL_MASK |
- CS42L42_PDN_MIC_LVL_DET_MASK,
- (0 << CS42L42_DETECT_MODE_SHIFT) |
- (1 << CS42L42_HSBIAS_CTL_SHIFT) |
- (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT));
- /* Set auto HS bias settings to default */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSBIAS_SC_AUTOCTL,
- CS42L42_HSBIAS_SENSE_EN_MASK |
- CS42L42_AUTO_HSBIAS_HIZ_MASK |
- CS42L42_TIP_SENSE_EN_MASK |
- CS42L42_HSBIAS_SENSE_TRIP_MASK,
- (0 << CS42L42_HSBIAS_SENSE_EN_SHIFT) |
- (0 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT) |
- (0 << CS42L42_TIP_SENSE_EN_SHIFT) |
- (3 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT));
- /* Set hs detect to manual, disabled mode */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSDET_CTL2,
- CS42L42_HSDET_CTRL_MASK |
- CS42L42_HSDET_SET_MASK |
- CS42L42_HSBIAS_REF_MASK |
- CS42L42_HSDET_AUTO_TIME_MASK,
- (0 << CS42L42_HSDET_CTRL_SHIFT) |
- (2 << CS42L42_HSDET_SET_SHIFT) |
- (0 << CS42L42_HSBIAS_REF_SHIFT) |
- (3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
- regmap_update_bits(cs42l42->regmap,
- CS42L42_DAC_CTL2,
- CS42L42_HPOUT_PULLDOWN_MASK |
- CS42L42_HPOUT_LOAD_MASK |
- CS42L42_HPOUT_CLAMP_MASK |
- CS42L42_DAC_HPF_EN_MASK |
- CS42L42_DAC_MON_EN_MASK,
- (8 << CS42L42_HPOUT_PULLDOWN_SHIFT) |
- (0 << CS42L42_HPOUT_LOAD_SHIFT) |
- (1 << CS42L42_HPOUT_CLAMP_SHIFT) |
- (1 << CS42L42_DAC_HPF_EN_SHIFT) |
- (1 << CS42L42_DAC_MON_EN_SHIFT));
- /* Power up HS bias to 2.7V */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MISC_DET_CTL,
- CS42L42_DETECT_MODE_MASK |
- CS42L42_HSBIAS_CTL_MASK |
- CS42L42_PDN_MIC_LVL_DET_MASK,
- (0 << CS42L42_DETECT_MODE_SHIFT) |
- (3 << CS42L42_HSBIAS_CTL_SHIFT) |
- (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT));
- /* Wait for HS bias to ramp up */
- msleep(cs42l42->hs_bias_ramp_time);
- /* Unmask auto detect interrupt */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_CODEC_INT_MASK,
- CS42L42_PDN_DONE_MASK |
- CS42L42_HSDET_AUTO_DONE_MASK,
- (1 << CS42L42_PDN_DONE_SHIFT) |
- (0 << CS42L42_HSDET_AUTO_DONE_SHIFT));
- /* Set hs detect to automatic, enabled mode */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSDET_CTL2,
- CS42L42_HSDET_CTRL_MASK |
- CS42L42_HSDET_SET_MASK |
- CS42L42_HSBIAS_REF_MASK |
- CS42L42_HSDET_AUTO_TIME_MASK,
- (3 << CS42L42_HSDET_CTRL_SHIFT) |
- (2 << CS42L42_HSDET_SET_SHIFT) |
- (0 << CS42L42_HSBIAS_REF_SHIFT) |
- (3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
- }
- static void cs42l42_cancel_hs_type_detect(struct cs42l42_private *cs42l42)
- {
- /* Mask button detect interrupts */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_DET_INT2_MASK,
- CS42L42_M_DETECT_TF_MASK |
- CS42L42_M_DETECT_FT_MASK |
- CS42L42_M_HSBIAS_HIZ_MASK |
- CS42L42_M_SHORT_RLS_MASK |
- CS42L42_M_SHORT_DET_MASK,
- (1 << CS42L42_M_DETECT_TF_SHIFT) |
- (1 << CS42L42_M_DETECT_FT_SHIFT) |
- (1 << CS42L42_M_HSBIAS_HIZ_SHIFT) |
- (1 << CS42L42_M_SHORT_RLS_SHIFT) |
- (1 << CS42L42_M_SHORT_DET_SHIFT));
- /* Ground HS bias */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MISC_DET_CTL,
- CS42L42_DETECT_MODE_MASK |
- CS42L42_HSBIAS_CTL_MASK |
- CS42L42_PDN_MIC_LVL_DET_MASK,
- (0 << CS42L42_DETECT_MODE_SHIFT) |
- (1 << CS42L42_HSBIAS_CTL_SHIFT) |
- (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT));
- /* Set auto HS bias settings to default */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSBIAS_SC_AUTOCTL,
- CS42L42_HSBIAS_SENSE_EN_MASK |
- CS42L42_AUTO_HSBIAS_HIZ_MASK |
- CS42L42_TIP_SENSE_EN_MASK |
- CS42L42_HSBIAS_SENSE_TRIP_MASK,
- (0 << CS42L42_HSBIAS_SENSE_EN_SHIFT) |
- (0 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT) |
- (0 << CS42L42_TIP_SENSE_EN_SHIFT) |
- (3 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT));
- /* Set hs detect to manual, disabled mode */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HSDET_CTL2,
- CS42L42_HSDET_CTRL_MASK |
- CS42L42_HSDET_SET_MASK |
- CS42L42_HSBIAS_REF_MASK |
- CS42L42_HSDET_AUTO_TIME_MASK,
- (0 << CS42L42_HSDET_CTRL_SHIFT) |
- (2 << CS42L42_HSDET_SET_SHIFT) |
- (0 << CS42L42_HSBIAS_REF_SHIFT) |
- (3 << CS42L42_HSDET_AUTO_TIME_SHIFT));
- }
- static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42)
- {
- int bias_level;
- unsigned int detect_status;
- /* Mask button detect interrupts */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_DET_INT2_MASK,
- CS42L42_M_DETECT_TF_MASK |
- CS42L42_M_DETECT_FT_MASK |
- CS42L42_M_HSBIAS_HIZ_MASK |
- CS42L42_M_SHORT_RLS_MASK |
- CS42L42_M_SHORT_DET_MASK,
- (1 << CS42L42_M_DETECT_TF_SHIFT) |
- (1 << CS42L42_M_DETECT_FT_SHIFT) |
- (1 << CS42L42_M_HSBIAS_HIZ_SHIFT) |
- (1 << CS42L42_M_SHORT_RLS_SHIFT) |
- (1 << CS42L42_M_SHORT_DET_SHIFT));
- usleep_range(cs42l42->btn_det_event_dbnce * 1000,
- cs42l42->btn_det_event_dbnce * 2000);
- /* Test all 4 level detect biases */
- bias_level = 1;
- do {
- /* Adjust button detect level sensitivity */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MIC_DET_CTL1,
- CS42L42_LATCH_TO_VP_MASK |
- CS42L42_EVENT_STAT_SEL_MASK |
- CS42L42_HS_DET_LEVEL_MASK,
- (1 << CS42L42_LATCH_TO_VP_SHIFT) |
- (0 << CS42L42_EVENT_STAT_SEL_SHIFT) |
- (cs42l42->bias_thresholds[bias_level] <<
- CS42L42_HS_DET_LEVEL_SHIFT));
- regmap_read(cs42l42->regmap, CS42L42_DET_STATUS2,
- &detect_status);
- } while ((detect_status & CS42L42_HS_TRUE_MASK) &&
- (++bias_level < CS42L42_NUM_BIASES));
- switch (bias_level) {
- case 1: /* Function C button press */
- dev_dbg(cs42l42->component->dev, "Function C button press\n");
- break;
- case 2: /* Function B button press */
- dev_dbg(cs42l42->component->dev, "Function B button press\n");
- break;
- case 3: /* Function D button press */
- dev_dbg(cs42l42->component->dev, "Function D button press\n");
- break;
- case 4: /* Function A button press */
- dev_dbg(cs42l42->component->dev, "Function A button press\n");
- break;
- }
- /* Set button detect level sensitivity back to default */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_MIC_DET_CTL1,
- CS42L42_LATCH_TO_VP_MASK |
- CS42L42_EVENT_STAT_SEL_MASK |
- CS42L42_HS_DET_LEVEL_MASK,
- (1 << CS42L42_LATCH_TO_VP_SHIFT) |
- (0 << CS42L42_EVENT_STAT_SEL_SHIFT) |
- (cs42l42->bias_thresholds[0] << CS42L42_HS_DET_LEVEL_SHIFT));
- /* Clear any button interrupts before unmasking them */
- regmap_read(cs42l42->regmap, CS42L42_DET_INT_STATUS2,
- &detect_status);
- /* Unmask button detect interrupts */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_DET_INT2_MASK,
- CS42L42_M_DETECT_TF_MASK |
- CS42L42_M_DETECT_FT_MASK |
- CS42L42_M_HSBIAS_HIZ_MASK |
- CS42L42_M_SHORT_RLS_MASK |
- CS42L42_M_SHORT_DET_MASK,
- (0 << CS42L42_M_DETECT_TF_SHIFT) |
- (0 << CS42L42_M_DETECT_FT_SHIFT) |
- (0 << CS42L42_M_HSBIAS_HIZ_SHIFT) |
- (1 << CS42L42_M_SHORT_RLS_SHIFT) |
- (1 << CS42L42_M_SHORT_DET_SHIFT));
- }
- struct cs42l42_irq_params {
- u16 status_addr;
- u16 mask_addr;
- u8 mask;
- };
- static const struct cs42l42_irq_params irq_params_table[] = {
- {CS42L42_ADC_OVFL_STATUS, CS42L42_ADC_OVFL_INT_MASK,
- CS42L42_ADC_OVFL_VAL_MASK},
- {CS42L42_MIXER_STATUS, CS42L42_MIXER_INT_MASK,
- CS42L42_MIXER_VAL_MASK},
- {CS42L42_SRC_STATUS, CS42L42_SRC_INT_MASK,
- CS42L42_SRC_VAL_MASK},
- {CS42L42_ASP_RX_STATUS, CS42L42_ASP_RX_INT_MASK,
- CS42L42_ASP_RX_VAL_MASK},
- {CS42L42_ASP_TX_STATUS, CS42L42_ASP_TX_INT_MASK,
- CS42L42_ASP_TX_VAL_MASK},
- {CS42L42_CODEC_STATUS, CS42L42_CODEC_INT_MASK,
- CS42L42_CODEC_VAL_MASK},
- {CS42L42_DET_INT_STATUS1, CS42L42_DET_INT1_MASK,
- CS42L42_DET_INT_VAL1_MASK},
- {CS42L42_DET_INT_STATUS2, CS42L42_DET_INT2_MASK,
- CS42L42_DET_INT_VAL2_MASK},
- {CS42L42_SRCPL_INT_STATUS, CS42L42_SRCPL_INT_MASK,
- CS42L42_SRCPL_VAL_MASK},
- {CS42L42_VPMON_STATUS, CS42L42_VPMON_INT_MASK,
- CS42L42_VPMON_VAL_MASK},
- {CS42L42_PLL_LOCK_STATUS, CS42L42_PLL_LOCK_INT_MASK,
- CS42L42_PLL_LOCK_VAL_MASK},
- {CS42L42_TSRS_PLUG_STATUS, CS42L42_TSRS_PLUG_INT_MASK,
- CS42L42_TSRS_PLUG_VAL_MASK}
- };
- static irqreturn_t cs42l42_irq_thread(int irq, void *data)
- {
- struct cs42l42_private *cs42l42 = (struct cs42l42_private *)data;
- struct snd_soc_component *component = cs42l42->component;
- unsigned int stickies[12];
- unsigned int masks[12];
- unsigned int current_plug_status;
- unsigned int current_button_status;
- unsigned int i;
- /* Read sticky registers to clear interurpt */
- for (i = 0; i < ARRAY_SIZE(stickies); i++) {
- regmap_read(cs42l42->regmap, irq_params_table[i].status_addr,
- &(stickies[i]));
- regmap_read(cs42l42->regmap, irq_params_table[i].mask_addr,
- &(masks[i]));
- stickies[i] = stickies[i] & (~masks[i]) &
- irq_params_table[i].mask;
- }
- /* Read tip sense status before handling type detect */
- current_plug_status = (stickies[11] &
- (CS42L42_TS_PLUG_MASK | CS42L42_TS_UNPLUG_MASK)) >>
- CS42L42_TS_PLUG_SHIFT;
- /* Read button sense status */
- current_button_status = stickies[7] &
- (CS42L42_M_DETECT_TF_MASK |
- CS42L42_M_DETECT_FT_MASK |
- CS42L42_M_HSBIAS_HIZ_MASK);
- /* Check auto-detect status */
- if ((~masks[5]) & irq_params_table[5].mask) {
- if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) {
- cs42l42_process_hs_type_detect(cs42l42);
- dev_dbg(component->dev,
- "Auto detect done (%d)\n",
- cs42l42->hs_type);
- }
- }
- /* Check tip sense status */
- if ((~masks[11]) & irq_params_table[11].mask) {
- switch (current_plug_status) {
- case CS42L42_TS_PLUG:
- if (cs42l42->plug_state != CS42L42_TS_PLUG) {
- cs42l42->plug_state = CS42L42_TS_PLUG;
- cs42l42_init_hs_type_detect(cs42l42);
- }
- break;
- case CS42L42_TS_UNPLUG:
- if (cs42l42->plug_state != CS42L42_TS_UNPLUG) {
- cs42l42->plug_state = CS42L42_TS_UNPLUG;
- cs42l42_cancel_hs_type_detect(cs42l42);
- dev_dbg(component->dev,
- "Unplug event\n");
- }
- break;
- default:
- if (cs42l42->plug_state != CS42L42_TS_TRANS)
- cs42l42->plug_state = CS42L42_TS_TRANS;
- }
- }
- /* Check button detect status */
- if ((~masks[7]) & irq_params_table[7].mask) {
- if (!(current_button_status &
- CS42L42_M_HSBIAS_HIZ_MASK)) {
- if (current_button_status &
- CS42L42_M_DETECT_TF_MASK) {
- dev_dbg(component->dev,
- "Button released\n");
- } else if (current_button_status &
- CS42L42_M_DETECT_FT_MASK) {
- cs42l42_handle_button_press(cs42l42);
- }
- }
- }
- return IRQ_HANDLED;
- }
- static void cs42l42_set_interrupt_masks(struct cs42l42_private *cs42l42)
- {
- regmap_update_bits(cs42l42->regmap, CS42L42_ADC_OVFL_INT_MASK,
- CS42L42_ADC_OVFL_MASK,
- (1 << CS42L42_ADC_OVFL_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_MIXER_INT_MASK,
- CS42L42_MIX_CHB_OVFL_MASK |
- CS42L42_MIX_CHA_OVFL_MASK |
- CS42L42_EQ_OVFL_MASK |
- CS42L42_EQ_BIQUAD_OVFL_MASK,
- (1 << CS42L42_MIX_CHB_OVFL_SHIFT) |
- (1 << CS42L42_MIX_CHA_OVFL_SHIFT) |
- (1 << CS42L42_EQ_OVFL_SHIFT) |
- (1 << CS42L42_EQ_BIQUAD_OVFL_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_SRC_INT_MASK,
- CS42L42_SRC_ILK_MASK |
- CS42L42_SRC_OLK_MASK |
- CS42L42_SRC_IUNLK_MASK |
- CS42L42_SRC_OUNLK_MASK,
- (1 << CS42L42_SRC_ILK_SHIFT) |
- (1 << CS42L42_SRC_OLK_SHIFT) |
- (1 << CS42L42_SRC_IUNLK_SHIFT) |
- (1 << CS42L42_SRC_OUNLK_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_ASP_RX_INT_MASK,
- CS42L42_ASPRX_NOLRCK_MASK |
- CS42L42_ASPRX_EARLY_MASK |
- CS42L42_ASPRX_LATE_MASK |
- CS42L42_ASPRX_ERROR_MASK |
- CS42L42_ASPRX_OVLD_MASK,
- (1 << CS42L42_ASPRX_NOLRCK_SHIFT) |
- (1 << CS42L42_ASPRX_EARLY_SHIFT) |
- (1 << CS42L42_ASPRX_LATE_SHIFT) |
- (1 << CS42L42_ASPRX_ERROR_SHIFT) |
- (1 << CS42L42_ASPRX_OVLD_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_ASP_TX_INT_MASK,
- CS42L42_ASPTX_NOLRCK_MASK |
- CS42L42_ASPTX_EARLY_MASK |
- CS42L42_ASPTX_LATE_MASK |
- CS42L42_ASPTX_SMERROR_MASK,
- (1 << CS42L42_ASPTX_NOLRCK_SHIFT) |
- (1 << CS42L42_ASPTX_EARLY_SHIFT) |
- (1 << CS42L42_ASPTX_LATE_SHIFT) |
- (1 << CS42L42_ASPTX_SMERROR_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_CODEC_INT_MASK,
- CS42L42_PDN_DONE_MASK |
- CS42L42_HSDET_AUTO_DONE_MASK,
- (1 << CS42L42_PDN_DONE_SHIFT) |
- (1 << CS42L42_HSDET_AUTO_DONE_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_SRCPL_INT_MASK,
- CS42L42_SRCPL_ADC_LK_MASK |
- CS42L42_SRCPL_DAC_LK_MASK |
- CS42L42_SRCPL_ADC_UNLK_MASK |
- CS42L42_SRCPL_DAC_UNLK_MASK,
- (1 << CS42L42_SRCPL_ADC_LK_SHIFT) |
- (1 << CS42L42_SRCPL_DAC_LK_SHIFT) |
- (1 << CS42L42_SRCPL_ADC_UNLK_SHIFT) |
- (1 << CS42L42_SRCPL_DAC_UNLK_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_DET_INT1_MASK,
- CS42L42_TIP_SENSE_UNPLUG_MASK |
- CS42L42_TIP_SENSE_PLUG_MASK |
- CS42L42_HSBIAS_SENSE_MASK,
- (1 << CS42L42_TIP_SENSE_UNPLUG_SHIFT) |
- (1 << CS42L42_TIP_SENSE_PLUG_SHIFT) |
- (1 << CS42L42_HSBIAS_SENSE_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_DET_INT2_MASK,
- CS42L42_M_DETECT_TF_MASK |
- CS42L42_M_DETECT_FT_MASK |
- CS42L42_M_HSBIAS_HIZ_MASK |
- CS42L42_M_SHORT_RLS_MASK |
- CS42L42_M_SHORT_DET_MASK,
- (1 << CS42L42_M_DETECT_TF_SHIFT) |
- (1 << CS42L42_M_DETECT_FT_SHIFT) |
- (1 << CS42L42_M_HSBIAS_HIZ_SHIFT) |
- (1 << CS42L42_M_SHORT_RLS_SHIFT) |
- (1 << CS42L42_M_SHORT_DET_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_VPMON_INT_MASK,
- CS42L42_VPMON_MASK,
- (1 << CS42L42_VPMON_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_PLL_LOCK_INT_MASK,
- CS42L42_PLL_LOCK_MASK,
- (1 << CS42L42_PLL_LOCK_SHIFT));
- regmap_update_bits(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK,
- CS42L42_RS_PLUG_MASK |
- CS42L42_RS_UNPLUG_MASK |
- CS42L42_TS_PLUG_MASK |
- CS42L42_TS_UNPLUG_MASK,
- (1 << CS42L42_RS_PLUG_SHIFT) |
- (1 << CS42L42_RS_UNPLUG_SHIFT) |
- (0 << CS42L42_TS_PLUG_SHIFT) |
- (0 << CS42L42_TS_UNPLUG_SHIFT));
- }
- static void cs42l42_setup_hs_type_detect(struct cs42l42_private *cs42l42)
- {
- unsigned int reg;
- cs42l42->hs_type = CS42L42_PLUG_INVALID;
- /* Latch analog controls to VP power domain */
- regmap_update_bits(cs42l42->regmap, CS42L42_MIC_DET_CTL1,
- CS42L42_LATCH_TO_VP_MASK |
- CS42L42_EVENT_STAT_SEL_MASK |
- CS42L42_HS_DET_LEVEL_MASK,
- (1 << CS42L42_LATCH_TO_VP_SHIFT) |
- (0 << CS42L42_EVENT_STAT_SEL_SHIFT) |
- (cs42l42->bias_thresholds[0] <<
- CS42L42_HS_DET_LEVEL_SHIFT));
- /* Remove ground noise-suppression clamps */
- regmap_update_bits(cs42l42->regmap,
- CS42L42_HS_CLAMP_DISABLE,
- CS42L42_HS_CLAMP_DISABLE_MASK,
- (1 << CS42L42_HS_CLAMP_DISABLE_SHIFT));
- /* Enable the tip sense circuit */
- regmap_update_bits(cs42l42->regmap, CS42L42_TSENSE_CTL,
- CS42L42_TS_INV_MASK, CS42L42_TS_INV_MASK);
- regmap_update_bits(cs42l42->regmap, CS42L42_TIPSENSE_CTL,
- CS42L42_TIP_SENSE_CTRL_MASK |
- CS42L42_TIP_SENSE_INV_MASK |
- CS42L42_TIP_SENSE_DEBOUNCE_MASK,
- (3 << CS42L42_TIP_SENSE_CTRL_SHIFT) |
- (!cs42l42->ts_inv << CS42L42_TIP_SENSE_INV_SHIFT) |
- (2 << CS42L42_TIP_SENSE_DEBOUNCE_SHIFT));
- /* Save the initial status of the tip sense */
- regmap_read(cs42l42->regmap,
- CS42L42_TSRS_PLUG_STATUS,
- ®);
- cs42l42->plug_state = (((char) reg) &
- (CS42L42_TS_PLUG_MASK | CS42L42_TS_UNPLUG_MASK)) >>
- CS42L42_TS_PLUG_SHIFT;
- }
- static const unsigned int threshold_defaults[] = {
- CS42L42_HS_DET_LEVEL_15,
- CS42L42_HS_DET_LEVEL_8,
- CS42L42_HS_DET_LEVEL_4,
- CS42L42_HS_DET_LEVEL_1
- };
- static int cs42l42_handle_device_data(struct device *dev,
- struct cs42l42_private *cs42l42)
- {
- unsigned int val;
- u32 thresholds[CS42L42_NUM_BIASES];
- int ret;
- int i;
- ret = device_property_read_u32(dev, "cirrus,ts-inv", &val);
- if (!ret) {
- switch (val) {
- case CS42L42_TS_INV_EN:
- case CS42L42_TS_INV_DIS:
- cs42l42->ts_inv = val;
- break;
- default:
- dev_err(dev,
- "Wrong cirrus,ts-inv DT value %d\n",
- val);
- cs42l42->ts_inv = CS42L42_TS_INV_DIS;
- }
- } else {
- cs42l42->ts_inv = CS42L42_TS_INV_DIS;
- }
- ret = device_property_read_u32(dev, "cirrus,ts-dbnc-rise", &val);
- if (!ret) {
- switch (val) {
- case CS42L42_TS_DBNCE_0:
- case CS42L42_TS_DBNCE_125:
- case CS42L42_TS_DBNCE_250:
- case CS42L42_TS_DBNCE_500:
- case CS42L42_TS_DBNCE_750:
- case CS42L42_TS_DBNCE_1000:
- case CS42L42_TS_DBNCE_1250:
- case CS42L42_TS_DBNCE_1500:
- cs42l42->ts_dbnc_rise = val;
- break;
- default:
- dev_err(dev,
- "Wrong cirrus,ts-dbnc-rise DT value %d\n",
- val);
- cs42l42->ts_dbnc_rise = CS42L42_TS_DBNCE_1000;
- }
- } else {
- cs42l42->ts_dbnc_rise = CS42L42_TS_DBNCE_1000;
- }
- regmap_update_bits(cs42l42->regmap, CS42L42_TSENSE_CTL,
- CS42L42_TS_RISE_DBNCE_TIME_MASK,
- (cs42l42->ts_dbnc_rise <<
- CS42L42_TS_RISE_DBNCE_TIME_SHIFT));
- ret = device_property_read_u32(dev, "cirrus,ts-dbnc-fall", &val);
- if (!ret) {
- switch (val) {
- case CS42L42_TS_DBNCE_0:
- case CS42L42_TS_DBNCE_125:
- case CS42L42_TS_DBNCE_250:
- case CS42L42_TS_DBNCE_500:
- case CS42L42_TS_DBNCE_750:
- case CS42L42_TS_DBNCE_1000:
- case CS42L42_TS_DBNCE_1250:
- case CS42L42_TS_DBNCE_1500:
- cs42l42->ts_dbnc_fall = val;
- break;
- default:
- dev_err(dev,
- "Wrong cirrus,ts-dbnc-fall DT value %d\n",
- val);
- cs42l42->ts_dbnc_fall = CS42L42_TS_DBNCE_0;
- }
- } else {
- cs42l42->ts_dbnc_fall = CS42L42_TS_DBNCE_0;
- }
- regmap_update_bits(cs42l42->regmap, CS42L42_TSENSE_CTL,
- CS42L42_TS_FALL_DBNCE_TIME_MASK,
- (cs42l42->ts_dbnc_fall <<
- CS42L42_TS_FALL_DBNCE_TIME_SHIFT));
- ret = device_property_read_u32(dev, "cirrus,btn-det-init-dbnce", &val);
- if (!ret) {
- if (val <= CS42L42_BTN_DET_INIT_DBNCE_MAX)
- cs42l42->btn_det_init_dbnce = val;
- else {
- dev_err(dev,
- "Wrong cirrus,btn-det-init-dbnce DT value %d\n",
- val);
- cs42l42->btn_det_init_dbnce =
- CS42L42_BTN_DET_INIT_DBNCE_DEFAULT;
- }
- } else {
- cs42l42->btn_det_init_dbnce =
- CS42L42_BTN_DET_INIT_DBNCE_DEFAULT;
- }
- ret = device_property_read_u32(dev, "cirrus,btn-det-event-dbnce", &val);
- if (!ret) {
- if (val <= CS42L42_BTN_DET_EVENT_DBNCE_MAX)
- cs42l42->btn_det_event_dbnce = val;
- else {
- dev_err(dev,
- "Wrong cirrus,btn-det-event-dbnce DT value %d\n", val);
- cs42l42->btn_det_event_dbnce =
- CS42L42_BTN_DET_EVENT_DBNCE_DEFAULT;
- }
- } else {
- cs42l42->btn_det_event_dbnce =
- CS42L42_BTN_DET_EVENT_DBNCE_DEFAULT;
- }
- ret = device_property_read_u32_array(dev, "cirrus,bias-lvls",
- thresholds, ARRAY_SIZE(thresholds));
- if (!ret) {
- for (i = 0; i < CS42L42_NUM_BIASES; i++) {
- if (thresholds[i] <= CS42L42_HS_DET_LEVEL_MAX)
- cs42l42->bias_thresholds[i] = thresholds[i];
- else {
- dev_err(dev,
- "Wrong cirrus,bias-lvls[%d] DT value %d\n", i,
- thresholds[i]);
- cs42l42->bias_thresholds[i] = threshold_defaults[i];
- }
- }
- } else {
- for (i = 0; i < CS42L42_NUM_BIASES; i++)
- cs42l42->bias_thresholds[i] = threshold_defaults[i];
- }
- ret = device_property_read_u32(dev, "cirrus,hs-bias-ramp-rate", &val);
- if (!ret) {
- switch (val) {
- case CS42L42_HSBIAS_RAMP_FAST_RISE_SLOW_FALL:
- cs42l42->hs_bias_ramp_rate = val;
- cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME0;
- break;
- case CS42L42_HSBIAS_RAMP_FAST:
- cs42l42->hs_bias_ramp_rate = val;
- cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME1;
- break;
- case CS42L42_HSBIAS_RAMP_SLOW:
- cs42l42->hs_bias_ramp_rate = val;
- cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME2;
- break;
- case CS42L42_HSBIAS_RAMP_SLOWEST:
- cs42l42->hs_bias_ramp_rate = val;
- cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME3;
- break;
- default:
- dev_err(dev,
- "Wrong cirrus,hs-bias-ramp-rate DT value %d\n",
- val);
- cs42l42->hs_bias_ramp_rate = CS42L42_HSBIAS_RAMP_SLOW;
- cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME2;
- }
- } else {
- cs42l42->hs_bias_ramp_rate = CS42L42_HSBIAS_RAMP_SLOW;
- cs42l42->hs_bias_ramp_time = CS42L42_HSBIAS_RAMP_TIME2;
- }
- regmap_update_bits(cs42l42->regmap, CS42L42_HS_BIAS_CTL,
- CS42L42_HSBIAS_RAMP_MASK,
- (cs42l42->hs_bias_ramp_rate <<
- CS42L42_HSBIAS_RAMP_SHIFT));
- return 0;
- }
- static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
- {
- struct cs42l42_private *cs42l42;
- int ret, i;
- unsigned int devid = 0;
- unsigned int reg;
- cs42l42 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l42_private),
- GFP_KERNEL);
- if (!cs42l42)
- return -ENOMEM;
- i2c_set_clientdata(i2c_client, cs42l42);
- cs42l42->regmap = devm_regmap_init_i2c(i2c_client, &cs42l42_regmap);
- if (IS_ERR(cs42l42->regmap)) {
- ret = PTR_ERR(cs42l42->regmap);
- dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
- return ret;
- }
- for (i = 0; i < ARRAY_SIZE(cs42l42->supplies); i++)
- cs42l42->supplies[i].supply = cs42l42_supply_names[i];
- ret = devm_regulator_bulk_get(&i2c_client->dev,
- ARRAY_SIZE(cs42l42->supplies),
- cs42l42->supplies);
- if (ret != 0) {
- dev_err(&i2c_client->dev,
- "Failed to request supplies: %d\n", ret);
- return ret;
- }
- ret = regulator_bulk_enable(ARRAY_SIZE(cs42l42->supplies),
- cs42l42->supplies);
- if (ret != 0) {
- dev_err(&i2c_client->dev,
- "Failed to enable supplies: %d\n", ret);
- return ret;
- }
- /* Reset the Device */
- cs42l42->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev,
- "reset", GPIOD_OUT_LOW);
- if (IS_ERR(cs42l42->reset_gpio)) {
- ret = PTR_ERR(cs42l42->reset_gpio);
- goto err_disable;
- }
- if (cs42l42->reset_gpio) {
- dev_dbg(&i2c_client->dev, "Found reset GPIO\n");
- gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
- }
- usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
- /* Request IRQ */
- ret = devm_request_threaded_irq(&i2c_client->dev,
- i2c_client->irq,
- NULL, cs42l42_irq_thread,
- IRQF_ONESHOT | IRQF_TRIGGER_LOW,
- "cs42l42", cs42l42);
- if (ret == -EPROBE_DEFER)
- goto err_disable;
- else if (ret != 0)
- dev_err(&i2c_client->dev,
- "Failed to request IRQ: %d\n", ret);
- /* initialize codec */
- ret = regmap_read(cs42l42->regmap, CS42L42_DEVID_AB, ®);
- devid = (reg & 0xFF) << 12;
- ret = regmap_read(cs42l42->regmap, CS42L42_DEVID_CD, ®);
- devid |= (reg & 0xFF) << 4;
- ret = regmap_read(cs42l42->regmap, CS42L42_DEVID_E, ®);
- devid |= (reg & 0xF0) >> 4;
- if (devid != CS42L42_CHIP_ID) {
- ret = -ENODEV;
- dev_err(&i2c_client->dev,
- "CS42L42 Device ID (%X). Expected %X\n",
- devid, CS42L42_CHIP_ID);
- goto err_disable;
- }
- ret = regmap_read(cs42l42->regmap, CS42L42_REVID, ®);
- if (ret < 0) {
- dev_err(&i2c_client->dev, "Get Revision ID failed\n");
- goto err_disable;
- }
- dev_info(&i2c_client->dev,
- "Cirrus Logic CS42L42, Revision: %02X\n", reg & 0xFF);
- /* Power up the codec */
- regmap_update_bits(cs42l42->regmap, CS42L42_PWR_CTL1,
- CS42L42_ASP_DAO_PDN_MASK |
- CS42L42_ASP_DAI_PDN_MASK |
- CS42L42_MIXER_PDN_MASK |
- CS42L42_EQ_PDN_MASK |
- CS42L42_HP_PDN_MASK |
- CS42L42_ADC_PDN_MASK |
- CS42L42_PDN_ALL_MASK,
- (1 << CS42L42_ASP_DAO_PDN_SHIFT) |
- (1 << CS42L42_ASP_DAI_PDN_SHIFT) |
- (1 << CS42L42_MIXER_PDN_SHIFT) |
- (1 << CS42L42_EQ_PDN_SHIFT) |
- (1 << CS42L42_HP_PDN_SHIFT) |
- (1 << CS42L42_ADC_PDN_SHIFT) |
- (0 << CS42L42_PDN_ALL_SHIFT));
- ret = cs42l42_handle_device_data(&i2c_client->dev, cs42l42);
- if (ret != 0)
- goto err_disable;
- /* Setup headset detection */
- cs42l42_setup_hs_type_detect(cs42l42);
- /* Mask/Unmask Interrupts */
- cs42l42_set_interrupt_masks(cs42l42);
- /* Register codec for machine driver */
- ret = devm_snd_soc_register_component(&i2c_client->dev,
- &soc_component_dev_cs42l42, &cs42l42_dai, 1);
- if (ret < 0)
- goto err_disable;
- return 0;
- err_disable:
- regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
- cs42l42->supplies);
- return ret;
- }
- static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
- {
- struct cs42l42_private *cs42l42 = i2c_get_clientdata(i2c_client);
- /* Hold down reset */
- gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
- return 0;
- }
- #ifdef CONFIG_PM
- static int cs42l42_runtime_suspend(struct device *dev)
- {
- struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
- regcache_cache_only(cs42l42->regmap, true);
- regcache_mark_dirty(cs42l42->regmap);
- /* Hold down reset */
- gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
- /* remove power */
- regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
- cs42l42->supplies);
- return 0;
- }
- static int cs42l42_runtime_resume(struct device *dev)
- {
- struct cs42l42_private *cs42l42 = dev_get_drvdata(dev);
- int ret;
- /* Enable power */
- ret = regulator_bulk_enable(ARRAY_SIZE(cs42l42->supplies),
- cs42l42->supplies);
- if (ret != 0) {
- dev_err(dev, "Failed to enable supplies: %d\n",
- ret);
- return ret;
- }
- gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
- usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
- regcache_cache_only(cs42l42->regmap, false);
- regcache_sync(cs42l42->regmap);
- return 0;
- }
- #endif
- static const struct dev_pm_ops cs42l42_runtime_pm = {
- SET_RUNTIME_PM_OPS(cs42l42_runtime_suspend, cs42l42_runtime_resume,
- NULL)
- };
- static const struct of_device_id cs42l42_of_match[] = {
- { .compatible = "cirrus,cs42l42", },
- {},
- };
- MODULE_DEVICE_TABLE(of, cs42l42_of_match);
- static const struct i2c_device_id cs42l42_id[] = {
- {"cs42l42", 0},
- {}
- };
- MODULE_DEVICE_TABLE(i2c, cs42l42_id);
- static struct i2c_driver cs42l42_i2c_driver = {
- .driver = {
- .name = "cs42l42",
- .pm = &cs42l42_runtime_pm,
- .of_match_table = cs42l42_of_match,
- },
- .id_table = cs42l42_id,
- .probe = cs42l42_i2c_probe,
- .remove = cs42l42_i2c_remove,
- };
- module_i2c_driver(cs42l42_i2c_driver);
- MODULE_DESCRIPTION("ASoC CS42L42 driver");
- MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
- MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
- MODULE_AUTHOR("Michael White, Cirrus Logic Inc, <michael.white@cirrus.com>");
- MODULE_LICENSE("GPL");
|